diff --git a/CHANGES b/CHANGES index c681eb28a4..697a4002a2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +3715. [bug] The region and city databases could fail to + initialize when using some versions of libGeoIP, + causing assertion failures when named was + configured to use them. [RT #35427] + 3714. [test] System tests that need to test for cryptography support before running can now use a common "testcrypto.sh" script to do so. [RT #35213] diff --git a/bin/named/geoip.c b/bin/named/geoip.c index 6f27da53d8..83fe825b05 100644 --- a/bin/named/geoip.c +++ b/bin/named/geoip.c @@ -31,7 +31,7 @@ static dns_geoip_databases_t geoip_table = { }; static void -init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, +init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, GeoIPDBTypes fallback, GeoIPOptions method, const char *name) { char *info; @@ -49,22 +49,22 @@ init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, 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; + "GeoIP %s (type %d) DB not available", name, edition); + goto fail; } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, - "initializing GeoIP %s DB", name); + "initializing GeoIP %s (type %d) DB", name, edition); 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; + "failed to initialize GeoIP %s (type %d) DB%s", + name, edition, fallback == 0 + ? "geoip matches using this database will fail" : ""); + goto fail; } info = GeoIP_database_info(db); @@ -74,18 +74,11 @@ init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, "%s", info); *dbp = db; -} + return; + fail: + if (fallback != 0) + init_geoip_db(dbp, fallback, 0, method, name); -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 */ @@ -124,41 +117,32 @@ ns_geoip_load(char *dir) { GeoIP_setup_custom_directory(dir); } - init_geoip_db(&ns_g_geoip->country_v4, GEOIP_COUNTRY_EDITION, + init_geoip_db(&ns_g_geoip->country_v4, GEOIP_COUNTRY_EDITION, 0, method, "Country (IPv4)"); #ifdef HAVE_GEOIP_V6 - init_geoip_db(&ns_g_geoip->country_v6, GEOIP_COUNTRY_EDITION_V6, + init_geoip_db(&ns_g_geoip->country_v6, GEOIP_COUNTRY_EDITION_V6, 0, 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)"); + init_geoip_db(&ns_g_geoip->city_v4, GEOIP_CITY_EDITION_REV1, + GEOIP_CITY_EDITION_REV0, 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)"); + init_geoip_db(&ns_g_geoip->city_v6, GEOIP_CITY_EDITION_REV1_V6, + GEOIP_CITY_EDITION_REV0_V6, method, "City (IPv6)"); #endif + init_geoip_db(&ns_g_geoip->region, GEOIP_REGION_EDITION_REV1, + GEOIP_REGION_EDITION_REV0, method, "Region"); - 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, + init_geoip_db(&ns_g_geoip->isp, GEOIP_ISP_EDITION, 0, method, "ISP"); - init_geoip_db(&ns_g_geoip->org, GEOIP_ORG_EDITION, + init_geoip_db(&ns_g_geoip->org, GEOIP_ORG_EDITION, 0, method, "Org"); - init_geoip_db(&ns_g_geoip->as, GEOIP_ASNUM_EDITION, + init_geoip_db(&ns_g_geoip->as, GEOIP_ASNUM_EDITION, 0, method, "AS"); - init_geoip_db(&ns_g_geoip->domain, GEOIP_DOMAIN_EDITION, + init_geoip_db(&ns_g_geoip->domain, GEOIP_DOMAIN_EDITION, 0, method, "Domain"); - init_geoip_db(&ns_g_geoip->netspeed, GEOIP_NETSPEED_EDITION, + init_geoip_db(&ns_g_geoip->netspeed, GEOIP_NETSPEED_EDITION, 0, method, "NetSpeed"); #endif /* HAVE_GEOIP */ } diff --git a/lib/dns/geoip.c b/lib/dns/geoip.c index 753d2b6e68..1f55962cbf 100644 --- a/lib/dns/geoip.c +++ b/lib/dns/geoip.c @@ -655,8 +655,11 @@ dns_geoip_match(const isc_netaddr_t *reqaddr, maxlen = 255; getcountry: db = DB46(reqaddr, geoip, country); - INSIST(db != NULL); + if (db == NULL) + return (ISC_FALSE); + INSIST(elt->as_string != NULL); + cs = country_lookup(db, subtype, reqaddr->family, ipnum, ipnum6); if (cs != NULL && strncasecmp(elt->as_string, cs, maxlen) == 0) @@ -675,6 +678,9 @@ dns_geoip_match(const isc_netaddr_t *reqaddr, INSIST(elt->as_string != NULL); db = DB46(reqaddr, geoip, city); + if (db == NULL) + return (ISC_FALSE); + record = city_lookup(db, subtype, reqaddr->family, ipnum, ipnum6); if (record == NULL) @@ -688,6 +694,9 @@ dns_geoip_match(const isc_netaddr_t *reqaddr, case dns_geoip_city_metrocode: db = DB46(reqaddr, geoip, city); + if (db == NULL) + return (ISC_FALSE); + record = city_lookup(db, subtype, reqaddr->family, ipnum, ipnum6); if (record == NULL) @@ -699,6 +708,9 @@ dns_geoip_match(const isc_netaddr_t *reqaddr, case dns_geoip_city_areacode: db = DB46(reqaddr, geoip, city); + if (db == NULL) + return (ISC_FALSE); + record = city_lookup(db, subtype, reqaddr->family, ipnum, ipnum6); if (record == NULL) @@ -711,7 +723,10 @@ dns_geoip_match(const isc_netaddr_t *reqaddr, case dns_geoip_region_countrycode: case dns_geoip_region_code: case dns_geoip_region_name: - INSIST(geoip->region != NULL); + case dns_geoip_region: + if (geoip->region == NULL) + return (ISC_FALSE); + INSIST(elt->as_string != NULL); /* Region DB is not supported for IPv6 */ @@ -744,7 +759,9 @@ dns_geoip_match(const isc_netaddr_t *reqaddr, db = geoip->domain; getname: - INSIST(db != NULL); + if (db == NULL) + return (ISC_FALSE); + INSIST(elt->as_string != NULL); /* ISP, Org, AS, and Domain are not supported for IPv6 */ if (reqaddr->family == AF_INET6) diff --git a/lib/dns/tests/geoip_test.c b/lib/dns/tests/geoip_test.c index 48110375b3..74fcbc4598 100644 --- a/lib/dns/tests/geoip_test.c +++ b/lib/dns/tests/geoip_test.c @@ -45,7 +45,7 @@ static dns_geoip_databases_t geoip = { }; static void -init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, +init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, GeoIPDBTypes fallback, GeoIPOptions method, const char *name) { char *info; @@ -61,18 +61,22 @@ init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, } if (! GeoIP_db_avail(edition)) { - fprintf(stderr, "GeoIP %s DB not available\n", name); - return; + fprintf(stderr, "GeoIP %s (type %d) DB not available\n", + name, edition); + goto fail; } - fprintf(stderr, "initializing GeoIP %s DB\n", name); + fprintf(stderr, "initializing GeoIP %s (type %d) DB\n", + name, edition); db = GeoIP_open_type(edition, method); if (db == NULL) { - fprintf(stderr, "failed to initialize GeoIP %s DB; " - "geoip matches using this database will fail\n", - name); - return; + fprintf(stderr, + "failed to initialize GeoIP %s (type %d) DB%s\n", + name, edition, fallback == 0 + ? "; geoip matches using this database will fail" + : ""); + goto fail; } info = GeoIP_database_info(db); @@ -80,22 +84,16 @@ init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, fprintf(stderr, "%s\n", info); *dbp = db; -} + return; -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); + fail: + if (fallback != 0) + init_geoip_db(dbp, fallback, 0, method, name); } static void load_geoip(const char *dir) { GeoIPOptions method; - GeoIPDBTypes edition; #ifdef _WIN32 method = GEOIP_STANDARD; @@ -109,38 +107,31 @@ load_geoip(const char *dir) { GeoIP_setup_custom_directory(p); } - init_geoip_db(&geoip.country_v4, GEOIP_COUNTRY_EDITION, + init_geoip_db(&geoip.country_v4, GEOIP_COUNTRY_EDITION, 0, method, "Country (IPv4)"); #ifdef HAVE_GEOIP_V6 - init_geoip_db(&geoip.country_v6, GEOIP_COUNTRY_EDITION_V6, + init_geoip_db(&geoip.country_v6, GEOIP_COUNTRY_EDITION_V6, 0, 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)"); + init_geoip_db(&geoip.city_v4, GEOIP_CITY_EDITION_REV1, + GEOIP_CITY_EDITION_REV0, method, "City (IPv4)"); #if defined(HAVE_GEOIP_V6) && defined(HAVE_GEOIP_CITY_V6) - 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)"); + init_geoip_db(&geoip.city_v6, GEOIP_CITY_EDITION_REV1_V6, + GEOIP_CITY_EDITION_REV0_V6, 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, + init_geoip_db(&geoip.region, GEOIP_REGION_EDITION_REV1, + GEOIP_REGION_EDITION_REV0, method, "Region"); + init_geoip_db(&geoip.isp, GEOIP_ISP_EDITION, 0, method, "ISP"); - init_geoip_db(&geoip.org, GEOIP_ORG_EDITION, + init_geoip_db(&geoip.org, GEOIP_ORG_EDITION, 0, method, "Org"); - init_geoip_db(&geoip.as, GEOIP_ASNUM_EDITION, + init_geoip_db(&geoip.as, GEOIP_ASNUM_EDITION, 0, method, "AS"); - init_geoip_db(&geoip.domain, GEOIP_DOMAIN_EDITION, + init_geoip_db(&geoip.domain, GEOIP_DOMAIN_EDITION, 0, method, "Domain"); - init_geoip_db(&geoip.netspeed, GEOIP_NETSPEED_EDITION, + init_geoip_db(&geoip.netspeed, GEOIP_NETSPEED_EDITION, 0, method, "NetSpeed"); }