"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/geoip.c" (7 Sep 2020, 20284 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "geoip.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*! \file */
   13 
   14 #include <config.h>
   15 
   16 #include <stdbool.h>
   17 
   18 #include <isc/util.h>
   19 
   20 #include <isc/mem.h>
   21 #include <isc/once.h>
   22 #include <isc/string.h>
   23 
   24 #include <dns/acl.h>
   25 #include <dns/geoip.h>
   26 
   27 #include <isc/thread.h>
   28 #include <math.h>
   29 #ifndef WIN32
   30 #include <netinet/in.h>
   31 #else
   32 #ifndef _WINSOCKAPI_
   33 #define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */
   34 #endif
   35 #include <winsock2.h>
   36 #endif  /* WIN32 */
   37 #include <dns/log.h>
   38 
   39 #ifdef HAVE_GEOIP
   40 #include <GeoIP.h>
   41 #include <GeoIPCity.h>
   42 
   43 /*
   44  * This structure preserves state from the previous GeoIP lookup,
   45  * so that successive lookups for the same data from the same IP
   46  * address will not require repeated calls into the GeoIP library
   47  * to look up data in the database. This should improve performance
   48  * somewhat.
   49  *
   50  * For lookups in the City and Region databases, we preserve pointers
   51  * to the GeoIPRecord and GeoIPregion structures; these will need to be
   52  * freed by GeoIPRecord_delete() and GeoIPRegion_delete().
   53  *
   54  * for lookups in ISP, AS, Org and Domain we prserve a pointer to
   55  * the returned name; these must be freed by free().
   56  *
   57  * For lookups in Country we preserve a pointer to the text of
   58  * the country code, name, etc (we use a different pointer for this
   59  * than for the names returned by Org, ISP, etc, because those need
   60  * to be freed but country lookups do not).
   61  *
   62  * For lookups in Netspeed we preserve the returned ID.
   63  *
   64  * XXX: Currently this mechanism is only used for IPv4 lookups; the
   65  * family and addr6 fields are to be used IPv6 is added.
   66  */
   67 typedef struct geoip_state {
   68     uint16_t subtype;
   69     unsigned int family;
   70     uint32_t ipnum;
   71     geoipv6_t ipnum6;
   72     uint8_t scope;
   73     GeoIPRecord *record;
   74     GeoIPRegion *region;
   75     const char *text;
   76     char *name;
   77     int id;
   78     isc_mem_t *mctx;
   79 } geoip_state_t;
   80 
   81 #ifdef ISC_PLATFORM_USETHREADS
   82 static isc_mutex_t key_mutex;
   83 static bool state_key_initialized = false;
   84 static isc_thread_key_t state_key;
   85 static isc_once_t mutex_once = ISC_ONCE_INIT;
   86 static isc_mem_t *state_mctx = NULL;
   87 
   88 static void
   89 key_mutex_init(void) {
   90     RUNTIME_CHECK(isc_mutex_init(&key_mutex) == ISC_R_SUCCESS);
   91 }
   92 
   93 static void
   94 free_state(void *arg) {
   95     geoip_state_t *state = arg;
   96     if (state != NULL && state->record != NULL)
   97         GeoIPRecord_delete(state->record);
   98     if (state != NULL)
   99         isc_mem_putanddetach(&state->mctx,
  100                      state, sizeof(geoip_state_t));
  101     isc_thread_key_setspecific(state_key, NULL);
  102 }
  103 
  104 static isc_result_t
  105 state_key_init(void) {
  106     isc_result_t result;
  107 
  108     result = isc_once_do(&mutex_once, key_mutex_init);
  109     if (result != ISC_R_SUCCESS)
  110         return (result);
  111 
  112     if (!state_key_initialized) {
  113         LOCK(&key_mutex);
  114         if (!state_key_initialized) {
  115             int ret;
  116 
  117             if (state_mctx == NULL)
  118                 result = isc_mem_create2(0, 0, &state_mctx, 0);
  119             if (result != ISC_R_SUCCESS)
  120                 goto unlock;
  121             isc_mem_setname(state_mctx, "geoip_state", NULL);
  122             isc_mem_setdestroycheck(state_mctx, false);
  123 
  124             ret = isc_thread_key_create(&state_key, free_state);
  125             if (ret == 0)
  126                 state_key_initialized = true;
  127             else
  128                 result = ISC_R_FAILURE;
  129         }
  130  unlock:
  131         UNLOCK(&key_mutex);
  132     }
  133 
  134     return (result);
  135 }
  136 #else
  137 static geoip_state_t saved_state;
  138 #endif
  139 
  140 static void
  141 clean_state(geoip_state_t *state) {
  142     if (state == NULL)
  143         return;
  144 
  145     if (state->record != NULL) {
  146         GeoIPRecord_delete(state->record);
  147         state->record = NULL;
  148     }
  149     if (state->region != NULL) {
  150         GeoIPRegion_delete(state->region);
  151         state->region = NULL;
  152     }
  153     if (state->name != NULL) {
  154         free (state->name);
  155         state->name = NULL;
  156     }
  157     state->ipnum = 0;
  158     state->text = NULL;
  159     state->id = 0;
  160 }
  161 
  162 static isc_result_t
  163 set_state(unsigned int family, uint32_t ipnum, const geoipv6_t *ipnum6,
  164       uint8_t scope, dns_geoip_subtype_t subtype, GeoIPRecord *record,
  165       GeoIPRegion *region, char *name, const char *text, int id)
  166 {
  167     geoip_state_t *state = NULL;
  168 #ifdef ISC_PLATFORM_USETHREADS
  169     isc_result_t result;
  170 
  171     result = state_key_init();
  172     if (result != ISC_R_SUCCESS)
  173         return (result);
  174 
  175     state = (geoip_state_t *) isc_thread_key_getspecific(state_key);
  176     if (state == NULL) {
  177         state = (geoip_state_t *) isc_mem_get(state_mctx,
  178                               sizeof(geoip_state_t));
  179         if (state == NULL)
  180             return (ISC_R_NOMEMORY);
  181         memset(state, 0, sizeof(*state));
  182 
  183         result = isc_thread_key_setspecific(state_key, state);
  184         if (result != ISC_R_SUCCESS) {
  185             isc_mem_put(state_mctx, state, sizeof(geoip_state_t));
  186             return (result);
  187         }
  188 
  189         isc_mem_attach(state_mctx, &state->mctx);
  190     } else
  191         clean_state(state);
  192 #else
  193     state = &saved_state;
  194     clean_state(state);
  195 #endif
  196 
  197     if (family == AF_INET) {
  198         state->ipnum = ipnum;
  199     } else {
  200         INSIST(ipnum6 != NULL);
  201         state->ipnum6 = *ipnum6;
  202     }
  203 
  204     state->family = family;
  205     state->subtype = subtype;
  206     state->scope = scope;
  207     state->record = record;
  208     state->region = region;
  209     state->name = name;
  210     state->text = text;
  211     state->id = id;
  212 
  213     return (ISC_R_SUCCESS);
  214 }
  215 
  216 static geoip_state_t *
  217 get_state_for(unsigned int family, uint32_t ipnum,
  218           const geoipv6_t *ipnum6)
  219 {
  220     geoip_state_t *state;
  221 
  222 #ifdef ISC_PLATFORM_USETHREADS
  223     isc_result_t result;
  224 
  225     result = state_key_init();
  226     if (result != ISC_R_SUCCESS)
  227         return (NULL);
  228 
  229     state = (geoip_state_t *) isc_thread_key_getspecific(state_key);
  230     if (state == NULL)
  231         return (NULL);
  232 #else
  233     state = &saved_state;
  234 #endif
  235 
  236     if (state->family == family &&
  237         ((state->family == AF_INET && state->ipnum == ipnum) ||
  238          (state->family == AF_INET6 && ipnum6 != NULL &&
  239           memcmp(state->ipnum6.s6_addr, ipnum6->s6_addr, 16) == 0)))
  240         return (state);
  241 
  242     return (NULL);
  243 }
  244 
  245 /*
  246  * Country lookups are performed if the previous lookup was from a
  247  * different IP address than the current, or was for a search of a
  248  * different subtype.
  249  */
  250 static const char *
  251 country_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
  252            unsigned int family,
  253            uint32_t ipnum, const geoipv6_t *ipnum6,
  254            uint8_t *scope)
  255 {
  256     geoip_state_t *prev_state = NULL;
  257     const char *text = NULL;
  258     GeoIPLookup gl;
  259 
  260     REQUIRE(db != NULL);
  261 
  262 #ifndef HAVE_GEOIP_V6
  263     /* no IPv6 support? give up now */
  264     if (family == AF_INET6)
  265         return (NULL);
  266 #endif
  267 
  268     prev_state = get_state_for(family, ipnum, ipnum6);
  269     if (prev_state != NULL && prev_state->subtype == subtype) {
  270         text = prev_state->text;
  271         if (scope != NULL)
  272             *scope = prev_state->scope;
  273     }
  274 
  275     if (text == NULL) {
  276         switch (subtype) {
  277         case dns_geoip_country_code:
  278             if (family == AF_INET)
  279                 text = GeoIP_country_code_by_ipnum_gl(db,
  280                                  ipnum, &gl);
  281 #ifdef HAVE_GEOIP_V6
  282             else
  283                 text = GeoIP_country_code_by_ipnum_v6_gl(db,
  284                                  *ipnum6, &gl);
  285 #endif
  286             break;
  287         case dns_geoip_country_code3:
  288             if (family == AF_INET)
  289                 text = GeoIP_country_code3_by_ipnum_gl(db,
  290                                  ipnum, &gl);
  291 #ifdef HAVE_GEOIP_V6
  292             else
  293                 text = GeoIP_country_code3_by_ipnum_v6_gl(db,
  294                                  *ipnum6, &gl);
  295 #endif
  296             break;
  297         case dns_geoip_country_name:
  298             if (family == AF_INET)
  299                 text = GeoIP_country_name_by_ipnum_gl(db,
  300                                  ipnum, &gl);
  301 #ifdef HAVE_GEOIP_V6
  302             else
  303                 text = GeoIP_country_name_by_ipnum_v6_gl(db,
  304                                  *ipnum6, &gl);
  305 #endif
  306             break;
  307         default:
  308             INSIST(0);
  309             ISC_UNREACHABLE();
  310         }
  311 
  312         if (text == NULL)
  313             return (NULL);
  314 
  315         if (scope != NULL)
  316             *scope = gl.netmask;
  317 
  318         set_state(family, ipnum, ipnum6, gl.netmask, subtype,
  319               NULL, NULL, NULL, text, 0);
  320     }
  321 
  322     return (text);
  323 }
  324 
  325 static char *
  326 city_string(GeoIPRecord *record, dns_geoip_subtype_t subtype, int *maxlen) {
  327     const char *s;
  328     char *deconst;
  329 
  330     REQUIRE(record != NULL);
  331     REQUIRE(maxlen != NULL);
  332 
  333     /* Set '*maxlen' to the maximum length of this subtype, if any */
  334     switch (subtype) {
  335     case dns_geoip_city_countrycode:
  336     case dns_geoip_city_region:
  337     case dns_geoip_city_continentcode:
  338         *maxlen = 2;
  339         break;
  340 
  341     case dns_geoip_city_countrycode3:
  342         *maxlen = 3;
  343         break;
  344 
  345     default:
  346         /* No fixed length; just use strcasecmp() for comparison */
  347         *maxlen = 255;
  348     }
  349 
  350     switch (subtype) {
  351     case dns_geoip_city_countrycode:
  352         return (record->country_code);
  353     case dns_geoip_city_countrycode3:
  354         return (record->country_code3);
  355     case dns_geoip_city_countryname:
  356         return (record->country_name);
  357     case dns_geoip_city_region:
  358         return (record->region);
  359     case dns_geoip_city_regionname:
  360         s = GeoIP_region_name_by_code(record->country_code,
  361                           record->region);
  362         DE_CONST(s, deconst);
  363         return (deconst);
  364     case dns_geoip_city_name:
  365         return (record->city);
  366     case dns_geoip_city_postalcode:
  367         return (record->postal_code);
  368     case dns_geoip_city_continentcode:
  369         return (record->continent_code);
  370     case dns_geoip_city_timezonecode:
  371         s = GeoIP_time_zone_by_country_and_region(record->country_code,
  372                               record->region);
  373         DE_CONST(s, deconst);
  374         return (deconst);
  375     default:
  376         INSIST(0);
  377         ISC_UNREACHABLE();
  378     }
  379 }
  380 
  381 static bool
  382 is_city(dns_geoip_subtype_t subtype) {
  383     switch (subtype) {
  384     case dns_geoip_city_countrycode:
  385     case dns_geoip_city_countrycode3:
  386     case dns_geoip_city_countryname:
  387     case dns_geoip_city_region:
  388     case dns_geoip_city_regionname:
  389     case dns_geoip_city_name:
  390     case dns_geoip_city_postalcode:
  391     case dns_geoip_city_continentcode:
  392     case dns_geoip_city_timezonecode:
  393     case dns_geoip_city_metrocode:
  394     case dns_geoip_city_areacode:
  395         return (true);
  396     default:
  397         return (false);
  398     }
  399 }
  400 
  401 /*
  402  * GeoIPRecord lookups are performed if the previous lookup was
  403  * from a different IP address than the current, or was for a search
  404  * outside the City database.
  405  */
  406 static GeoIPRecord *
  407 city_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
  408         unsigned int family, uint32_t ipnum,
  409         const geoipv6_t *ipnum6,
  410         uint8_t *scope)
  411 {
  412     GeoIPRecord *record = NULL;
  413     geoip_state_t *prev_state = NULL;
  414 
  415     REQUIRE(db != NULL);
  416 
  417 #ifndef HAVE_GEOIP_V6
  418     /* no IPv6 support? give up now */
  419     if (family == AF_INET6)
  420         return (NULL);
  421 #endif
  422 
  423     prev_state = get_state_for(family, ipnum, ipnum6);
  424     if (prev_state != NULL && is_city(prev_state->subtype)) {
  425         record = prev_state->record;
  426         if (scope != NULL)
  427             *scope = record->netmask;
  428     }
  429 
  430     if (record == NULL) {
  431         if (family == AF_INET)
  432             record = GeoIP_record_by_ipnum(db, ipnum);
  433 #ifdef HAVE_GEOIP_V6
  434         else
  435             record = GeoIP_record_by_ipnum_v6(db, *ipnum6);
  436 #endif
  437         if (record == NULL)
  438             return (NULL);
  439 
  440         if (scope != NULL)
  441             *scope = record->netmask;
  442 
  443         set_state(family, ipnum, ipnum6, record->netmask, subtype,
  444               record, NULL, NULL, NULL, 0);
  445     }
  446 
  447     return (record);
  448 }
  449 
  450 static char * region_string(GeoIPRegion *region, dns_geoip_subtype_t subtype, int *maxlen) {
  451     const char *s;
  452     char *deconst;
  453 
  454     REQUIRE(region != NULL);
  455     REQUIRE(maxlen != NULL);
  456 
  457     switch (subtype) {
  458     case dns_geoip_region_countrycode:
  459         *maxlen = 2;
  460         return (region->country_code);
  461     case dns_geoip_region_code:
  462         *maxlen = 2;
  463         return (region->region);
  464     case dns_geoip_region_name:
  465         *maxlen = 255;
  466         s = GeoIP_region_name_by_code(region->country_code,
  467                           region->region);
  468         DE_CONST(s, deconst);
  469         return (deconst);
  470     default:
  471         INSIST(0);
  472         ISC_UNREACHABLE();
  473     }
  474 }
  475 
  476 static bool
  477 is_region(dns_geoip_subtype_t subtype) {
  478     switch (subtype) {
  479     case dns_geoip_region_countrycode:
  480     case dns_geoip_region_code:
  481         return (true);
  482     default:
  483         return (false);
  484     }
  485 }
  486 
  487 /*
  488  * GeoIPRegion lookups are performed if the previous lookup was
  489  * from a different IP address than the current, or was for a search
  490  * outside the Region database.
  491  */
  492 static GeoIPRegion *
  493 region_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
  494           uint32_t ipnum, uint8_t *scope)
  495 {
  496     GeoIPRegion *region = NULL;
  497     geoip_state_t *prev_state = NULL;
  498     GeoIPLookup gl;
  499 
  500     REQUIRE(db != NULL);
  501 
  502     prev_state = get_state_for(AF_INET, ipnum, NULL);
  503     if (prev_state != NULL && is_region(prev_state->subtype)) {
  504         region = prev_state->region;
  505         if (scope != NULL)
  506             *scope = prev_state->scope;
  507     }
  508 
  509     if (region == NULL) {
  510         region = GeoIP_region_by_ipnum_gl(db, ipnum, &gl);
  511         if (region == NULL)
  512             return (NULL);
  513 
  514         if (scope != NULL)
  515             *scope = gl.netmask;
  516 
  517         set_state(AF_INET, ipnum, NULL, gl.netmask,
  518               subtype, NULL, region, NULL, NULL, 0);
  519     }
  520 
  521     return (region);
  522 }
  523 
  524 /*
  525  * ISP, Organization, AS Number and Domain lookups are performed if
  526  * the previous lookup was from a different IP address than the current,
  527  * or was for a search of a different subtype.
  528  */
  529 static char *
  530 name_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
  531         uint32_t ipnum, uint8_t *scope)
  532 {
  533     char *name = NULL;
  534     geoip_state_t *prev_state = NULL;
  535     GeoIPLookup gl;
  536 
  537     REQUIRE(db != NULL);
  538 
  539     prev_state = get_state_for(AF_INET, ipnum, NULL);
  540     if (prev_state != NULL && prev_state->subtype == subtype) {
  541         name = prev_state->name;
  542         if (scope != NULL)
  543             *scope = prev_state->scope;
  544     }
  545 
  546     if (name == NULL) {
  547         name = GeoIP_name_by_ipnum_gl(db, ipnum, &gl);
  548         if (name == NULL)
  549             return (NULL);
  550 
  551         if (scope != NULL)
  552             *scope = gl.netmask;
  553 
  554         set_state(AF_INET, ipnum, NULL, gl.netmask,
  555               subtype, NULL, NULL, name, NULL, 0);
  556     }
  557 
  558     return (name);
  559 }
  560 
  561 /*
  562  * Netspeed lookups are performed if the previous lookup was from a
  563  * different IP address than the current, or was for a search of a
  564  * different subtype.
  565  */
  566 static int
  567 netspeed_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
  568         uint32_t ipnum, uint8_t *scope)
  569 {
  570     geoip_state_t *prev_state = NULL;
  571     bool found = false;
  572     GeoIPLookup gl;
  573     int id = -1;
  574 
  575     REQUIRE(db != NULL);
  576 
  577     prev_state = get_state_for(AF_INET, ipnum, NULL);
  578     if (prev_state != NULL && prev_state->subtype == subtype) {
  579         id = prev_state->id;
  580         if (scope != NULL)
  581             *scope = prev_state->scope;
  582         found = true;
  583     }
  584 
  585     if (!found) {
  586         id = GeoIP_id_by_ipnum_gl(db, ipnum, &gl);
  587         if (id == 0)
  588             return (0);
  589 
  590         if (scope != NULL)
  591             *scope = gl.netmask;
  592 
  593         set_state(AF_INET, ipnum, NULL, gl.netmask,
  594               subtype, NULL, NULL, NULL, NULL, id);
  595     }
  596 
  597     return (id);
  598 }
  599 #endif /* HAVE_GEOIP */
  600 
  601 #define DB46(addr, geoip, name) \
  602     ((addr->family == AF_INET) ? (geoip->name##_v4) : (geoip->name##_v6))
  603 
  604 #ifdef HAVE_GEOIP
  605 /*
  606  * Find the best database to answer a generic subtype
  607  */
  608 static dns_geoip_subtype_t
  609 fix_subtype(const isc_netaddr_t *reqaddr, const dns_geoip_databases_t *geoip,
  610         dns_geoip_subtype_t subtype)
  611 {
  612     dns_geoip_subtype_t ret = subtype;
  613 
  614     switch (subtype) {
  615     case dns_geoip_countrycode:
  616         if (DB46(reqaddr, geoip, city) != NULL)
  617             ret = dns_geoip_city_countrycode;
  618         else if (reqaddr->family == AF_INET && geoip->region != NULL)
  619             ret = dns_geoip_region_countrycode;
  620         else if (DB46(reqaddr, geoip, country) != NULL)
  621             ret = dns_geoip_country_code;
  622         break;
  623     case dns_geoip_countrycode3:
  624         if (DB46(reqaddr, geoip, city) != NULL)
  625             ret = dns_geoip_city_countrycode3;
  626         else if (DB46(reqaddr, geoip, country) != NULL)
  627             ret = dns_geoip_country_code3;
  628         break;
  629     case dns_geoip_countryname:
  630         if (DB46(reqaddr, geoip, city) != NULL)
  631             ret = dns_geoip_city_countryname;
  632         else if (DB46(reqaddr, geoip, country) != NULL)
  633             ret = dns_geoip_country_name;
  634         break;
  635     case dns_geoip_region:
  636         if (DB46(reqaddr, geoip, city) != NULL)
  637             ret = dns_geoip_city_region;
  638         else if (reqaddr->family == AF_INET && geoip->region != NULL)
  639             ret = dns_geoip_region_code;
  640         break;
  641     case dns_geoip_regionname:
  642         if (DB46(reqaddr, geoip, city) != NULL)
  643             ret = dns_geoip_city_regionname;
  644         else if (reqaddr->family == AF_INET && geoip->region != NULL)
  645             ret = dns_geoip_region_name;
  646         break;
  647     default:
  648         break;
  649     }
  650 
  651     return (ret);
  652 }
  653 #endif /* HAVE_GEOIP */
  654 
  655 bool
  656 dns_geoip_match(const isc_netaddr_t *reqaddr, uint8_t *scope,
  657         const dns_geoip_databases_t *geoip,
  658         const dns_geoip_elem_t *elt)
  659 {
  660 #ifndef HAVE_GEOIP
  661     UNUSED(reqaddr);
  662     UNUSED(geoip);
  663     UNUSED(elt);
  664 
  665     return (false);
  666 #else
  667     GeoIP *db;
  668     GeoIPRecord *record;
  669     GeoIPRegion *region;
  670     dns_geoip_subtype_t subtype;
  671     uint32_t ipnum = 0;
  672     int maxlen = 0, id, family;
  673     const char *cs;
  674     char *s;
  675 #ifdef HAVE_GEOIP_V6
  676     const geoipv6_t *ipnum6 = NULL;
  677 #else
  678     const void *ipnum6 = NULL;
  679 #endif
  680 
  681     INSIST(geoip != NULL);
  682 
  683     family = reqaddr->family;
  684     switch (family) {
  685     case AF_INET:
  686         ipnum = ntohl(reqaddr->type.in.s_addr);
  687         break;
  688     case AF_INET6:
  689 #ifdef HAVE_GEOIP_V6
  690         ipnum6 = &reqaddr->type.in6;
  691         break;
  692 #else
  693         return (false);
  694 #endif
  695     default:
  696         return (false);
  697     }
  698 
  699     subtype = fix_subtype(reqaddr, geoip, elt->subtype);
  700 
  701     switch (subtype) {
  702     case dns_geoip_country_code:
  703         maxlen = 2;
  704         goto getcountry;
  705 
  706     case dns_geoip_country_code3:
  707         maxlen = 3;
  708         goto getcountry;
  709 
  710     case dns_geoip_country_name:
  711         maxlen = 255;
  712  getcountry:
  713         db = DB46(reqaddr, geoip, country);
  714         if (db == NULL)
  715             return (false);
  716 
  717         INSIST(elt->as_string != NULL);
  718 
  719         cs = country_lookup(db, subtype, family, ipnum, ipnum6, scope);
  720         if (cs != NULL && strncasecmp(elt->as_string, cs, maxlen) == 0)
  721             return (true);
  722         break;
  723 
  724     case dns_geoip_city_countrycode:
  725     case dns_geoip_city_countrycode3:
  726     case dns_geoip_city_countryname:
  727     case dns_geoip_city_region:
  728     case dns_geoip_city_regionname:
  729     case dns_geoip_city_name:
  730     case dns_geoip_city_postalcode:
  731     case dns_geoip_city_continentcode:
  732     case dns_geoip_city_timezonecode:
  733         INSIST(elt->as_string != NULL);
  734 
  735         db = DB46(reqaddr, geoip, city);
  736         if (db == NULL)
  737             return (false);
  738 
  739         record = city_lookup(db, subtype, family,
  740                      ipnum, ipnum6, scope);
  741         if (record == NULL)
  742             break;
  743 
  744         s = city_string(record, subtype, &maxlen);
  745         INSIST(maxlen != 0);
  746         if (s != NULL && strncasecmp(elt->as_string, s, maxlen) == 0)
  747             return (true);
  748         break;
  749 
  750     case dns_geoip_city_metrocode:
  751         db = DB46(reqaddr, geoip, city);
  752         if (db == NULL)
  753             return (false);
  754 
  755         record = city_lookup(db, subtype, family,
  756                      ipnum, ipnum6, scope);
  757         if (record == NULL)
  758             break;
  759 
  760         if (elt->as_int == record->metro_code)
  761             return (true);
  762         break;
  763 
  764     case dns_geoip_city_areacode:
  765         db = DB46(reqaddr, geoip, city);
  766         if (db == NULL)
  767             return (false);
  768 
  769         record = city_lookup(db, subtype, family,
  770                      ipnum, ipnum6, scope);
  771         if (record == NULL)
  772             break;
  773 
  774         if (elt->as_int == record->area_code)
  775             return (true);
  776         break;
  777 
  778     case dns_geoip_region_countrycode:
  779     case dns_geoip_region_code:
  780     case dns_geoip_region_name:
  781     case dns_geoip_region:
  782         if (geoip->region == NULL)
  783             return (false);
  784 
  785         INSIST(elt->as_string != NULL);
  786 
  787         /* Region DB is not supported for IPv6 */
  788         if (family == AF_INET6)
  789             return (false);
  790 
  791         region = region_lookup(geoip->region, subtype, ipnum, scope);
  792         if (region == NULL)
  793             break;
  794 
  795         s = region_string(region, subtype, &maxlen);
  796         INSIST(maxlen != 0);
  797         if (s != NULL && strncasecmp(elt->as_string, s, maxlen) == 0)
  798             return (true);
  799         break;
  800 
  801     case dns_geoip_isp_name:
  802         db = geoip->isp;
  803         goto getname;
  804 
  805     case dns_geoip_org_name:
  806         db = geoip->org;
  807         goto getname;
  808 
  809     case dns_geoip_as_asnum:
  810         db = geoip->as;
  811         goto getname;
  812 
  813     case dns_geoip_domain_name:
  814         db = geoip->domain;
  815 
  816  getname:
  817         if (db == NULL)
  818             return (false);
  819 
  820         INSIST(elt->as_string != NULL);
  821         /* ISP, Org, AS, and Domain are not supported for IPv6 */
  822         if (family == AF_INET6)
  823             return (false);
  824 
  825         s = name_lookup(db, subtype, ipnum, scope);
  826         if (s != NULL) {
  827             size_t l;
  828             if (strcasecmp(elt->as_string, s) == 0)
  829                 return (true);
  830             if (subtype != dns_geoip_as_asnum)
  831                 break;
  832             /*
  833              * Just check if the ASNNNN value matches.
  834              */
  835             l = strlen(elt->as_string);
  836             if (l > 0U && strchr(elt->as_string, ' ') == NULL &&
  837                 strncasecmp(elt->as_string, s, l) == 0 &&
  838                 s[l] == ' ')
  839                 return (true);
  840         }
  841         break;
  842 
  843     case dns_geoip_netspeed_id:
  844         INSIST(geoip->netspeed != NULL);
  845 
  846         /* Netspeed DB is not supported for IPv6 */
  847         if (family == AF_INET6)
  848             return (false);
  849 
  850         id = netspeed_lookup(geoip->netspeed, subtype, ipnum, scope);
  851         if (id == elt->as_int)
  852             return (true);
  853         break;
  854 
  855     case dns_geoip_countrycode:
  856     case dns_geoip_countrycode3:
  857     case dns_geoip_countryname:
  858     case dns_geoip_regionname:
  859         /*
  860          * If these were not remapped by fix_subtype(),
  861          * the database was unavailable. Always return false.
  862          */
  863         break;
  864 
  865     default:
  866         INSIST(0);
  867         ISC_UNREACHABLE();
  868     }
  869 
  870     return (false);
  871 #endif
  872 }
  873 
  874 void
  875 dns_geoip_shutdown(void) {
  876 #ifdef HAVE_GEOIP
  877     GeoIP_cleanup();
  878 #ifdef ISC_PLATFORM_USETHREADS
  879     if (state_mctx != NULL)
  880         isc_mem_detach(&state_mctx);
  881 #endif
  882 #else
  883     return;
  884 #endif
  885 }