Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / geoip.c
blob2b36d47737dd655be7b0f841a2cf5e825294d478
1 /* $NetBSD: geoip.c,v 1.1.1.6 2015/07/08 15:38:01 christos Exp $ */
3 /*
4 * Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /*! \file */
21 #include <config.h>
23 #include <isc/util.h>
25 #include <isc/mem.h>
26 #include <isc/once.h>
27 #include <isc/string.h>
29 #include <dns/acl.h>
30 #include <dns/geoip.h>
32 #include <isc/thread.h>
33 #include <math.h>
34 #ifndef WIN32
35 #include <netinet/in.h>
36 #else
37 #ifndef _WINSOCKAPI_
38 #define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
39 #endif
40 #include <winsock2.h>
41 #endif /* WIN32 */
42 #include <dns/log.h>
44 #ifdef HAVE_GEOIP
45 #include <GeoIP.h>
46 #include <GeoIPCity.h>
49 * This structure preserves state from the previous GeoIP lookup,
50 * so that successive lookups for the same data from the same IP
51 * address will not require repeated calls into the GeoIP library
52 * to look up data in the database. This should improve performance
53 * somewhat.
55 * For lookups in the City and Region databases, we preserve pointers
56 * to the GeoIPRecord and GeoIPregion structures; these will need to be
57 * freed by GeoIPRecord_delete() and GeoIPRegion_delete().
59 * for lookups in ISP, AS, Org and Domain we prserve a pointer to
60 * the returned name; these must be freed by free().
62 * For lookups in Country we preserve a pointer to the text of
63 * the country code, name, etc (we use a different pointer for this
64 * than for the names returned by Org, ISP, etc, because those need
65 * to be freed but country lookups do not).
67 * For lookups in Netspeed we preserve the returned ID.
69 * XXX: Currently this mechanism is only used for IPv4 lookups; the
70 * family and addr6 fields are to be used IPv6 is added.
72 typedef struct geoip_state {
73 isc_uint16_t subtype;
74 unsigned int family;
75 isc_uint32_t ipnum;
76 geoipv6_t ipnum6;
77 GeoIPRecord *record;
78 GeoIPRegion *region;
79 const char *text;
80 char *name;
81 int id;
82 isc_mem_t *mctx;
83 } geoip_state_t;
85 #ifdef ISC_PLATFORM_USETHREADS
86 static isc_mutex_t key_mutex;
87 static isc_boolean_t state_key_initialized = ISC_FALSE;
88 static isc_thread_key_t state_key;
89 static isc_once_t mutex_once = ISC_ONCE_INIT;
90 static isc_mem_t *state_mctx = NULL;
92 static void
93 key_mutex_init(void) {
94 RUNTIME_CHECK(isc_mutex_init(&key_mutex) == ISC_R_SUCCESS);
97 static void
98 free_state(void *arg) {
99 geoip_state_t *state = arg;
100 if (state != NULL && state->record != NULL)
101 GeoIPRecord_delete(state->record);
102 if (state != NULL)
103 isc_mem_putanddetach(&state->mctx,
104 state, sizeof(geoip_state_t));
105 isc_thread_key_setspecific(state_key, NULL);
108 static isc_result_t
109 state_key_init(void) {
110 isc_result_t result;
112 result = isc_once_do(&mutex_once, key_mutex_init);
113 if (result != ISC_R_SUCCESS)
114 return (result);
116 if (!state_key_initialized) {
117 LOCK(&key_mutex);
118 if (!state_key_initialized) {
119 int ret;
121 if (state_mctx == NULL)
122 result = isc_mem_create2(0, 0, &state_mctx, 0);
123 if (result != ISC_R_SUCCESS)
124 goto unlock;
125 isc_mem_setname(state_mctx, "geoip_state", NULL);
126 isc_mem_setdestroycheck(state_mctx, ISC_FALSE);
128 ret = isc_thread_key_create(&state_key, free_state);
129 if (ret == 0)
130 state_key_initialized = ISC_TRUE;
131 else
132 result = ISC_R_FAILURE;
134 unlock:
135 UNLOCK(&key_mutex);
138 return (result);
140 #else
141 geoip_state_t prev_state;
142 #endif
144 static void
145 clean_state(geoip_state_t *state) {
146 if (state == NULL)
147 return;
149 if (state->record != NULL) {
150 GeoIPRecord_delete(state->record);
151 state->record = NULL;
153 if (state->region != NULL) {
154 GeoIPRegion_delete(state->region);
155 state->region = NULL;
157 if (state->name != NULL) {
158 free (state->name);
159 state->name = NULL;
161 state->ipnum = 0;
162 state->text = NULL;
163 state->id = 0;
166 static isc_result_t
167 set_state(unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6,
168 dns_geoip_subtype_t subtype, GeoIPRecord *record,
169 GeoIPRegion *region, char *name, const char *text, int id)
171 geoip_state_t *state = NULL;
173 #ifdef ISC_PLATFORM_USETHREADS
174 isc_result_t result;
176 result = state_key_init();
177 if (result != ISC_R_SUCCESS)
178 return (result);
180 state = (geoip_state_t *) isc_thread_key_getspecific(state_key);
181 if (state == NULL) {
182 state = (geoip_state_t *) isc_mem_get(state_mctx,
183 sizeof(geoip_state_t));
184 if (state == NULL)
185 return (ISC_R_NOMEMORY);
186 memset(state, 0, sizeof(*state));
188 result = isc_thread_key_setspecific(state_key, state);
189 if (result != ISC_R_SUCCESS) {
190 isc_mem_put(state_mctx, state, sizeof(geoip_state_t));
191 return (result);
194 isc_mem_attach(state_mctx, &state->mctx);
195 } else
196 clean_state(state);
197 #else
198 state = &prev_state;
199 clean_state(state);
200 #endif
202 if (family == AF_INET)
203 state->ipnum = ipnum;
204 else
205 state->ipnum6 = *ipnum6;
207 state->family = family;
208 state->subtype = subtype;
209 state->record = record;
210 state->region = region;
211 state->name = name;
212 state->text = text;
213 state->id = id;
215 return (ISC_R_SUCCESS);
218 static geoip_state_t *
219 get_state_for(unsigned int family, isc_uint32_t ipnum,
220 const geoipv6_t *ipnum6)
222 geoip_state_t *state;
224 #ifdef ISC_PLATFORM_USETHREADS
225 isc_result_t result;
227 result = state_key_init();
228 if (result != ISC_R_SUCCESS)
229 return (NULL);
231 state = (geoip_state_t *) isc_thread_key_getspecific(state_key);
232 if (state == NULL)
233 return (NULL);
234 #else
235 state = &prev_state;
236 #endif
238 if (state->family == family &&
239 ((state->family == AF_INET && state->ipnum == ipnum) ||
240 (state->family == AF_INET6 && ipnum6 != NULL &&
241 memcmp(state->ipnum6.s6_addr, ipnum6->s6_addr, 16) == 0)))
242 return (state);
244 return (NULL);
248 * Country lookups are performed if the previous lookup was from a
249 * different IP address than the current, or was for a search of a
250 * different subtype.
252 static const char *
253 country_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
254 unsigned int family,
255 isc_uint32_t ipnum, const geoipv6_t *ipnum6)
257 geoip_state_t *prev_state = NULL;
258 const char *text = NULL;
260 REQUIRE(db != NULL);
262 #ifndef HAVE_GEOIP_V6
263 /* no IPv6 support? give up now */
264 if (family == AF_INET6)
265 return (NULL);
266 #endif
268 prev_state = get_state_for(family, ipnum, ipnum6);
269 if (prev_state != NULL && prev_state->subtype == subtype)
270 text = prev_state->text;
272 if (text == NULL) {
273 switch (subtype) {
274 case dns_geoip_country_code:
275 if (family == AF_INET)
276 text = GeoIP_country_code_by_ipnum(db, ipnum);
277 #ifdef HAVE_GEOIP_V6
278 else
279 text = GeoIP_country_code_by_ipnum_v6(db,
280 *ipnum6);
281 #endif
282 break;
283 case dns_geoip_country_code3:
284 if (family == AF_INET)
285 text = GeoIP_country_code3_by_ipnum(db, ipnum);
286 #ifdef HAVE_GEOIP_V6
287 else
288 text = GeoIP_country_code3_by_ipnum_v6(db,
289 *ipnum6);
290 #endif
291 break;
292 case dns_geoip_country_name:
293 if (family == AF_INET)
294 text = GeoIP_country_name_by_ipnum(db, ipnum);
295 #ifdef HAVE_GEOIP_V6
296 else
297 text = GeoIP_country_name_by_ipnum_v6(db,
298 *ipnum6);
299 #endif
300 break;
301 default:
302 INSIST(0);
305 set_state(family, ipnum, ipnum6, subtype,
306 NULL, NULL, NULL, text, 0);
309 return (text);
312 static char *
313 city_string(GeoIPRecord *record, dns_geoip_subtype_t subtype, int *maxlen) {
314 const char *s;
315 char *deconst;
317 REQUIRE(record != NULL);
318 REQUIRE(maxlen != NULL);
320 /* Set '*maxlen' to the maximum length of this subtype, if any */
321 switch (subtype) {
322 case dns_geoip_city_countrycode:
323 case dns_geoip_city_region:
324 case dns_geoip_city_continentcode:
325 *maxlen = 2;
326 break;
328 case dns_geoip_city_countrycode3:
329 *maxlen = 3;
330 break;
332 default:
333 /* No fixed length; just use strcasecmp() for comparison */
334 *maxlen = 255;
337 switch (subtype) {
338 case dns_geoip_city_countrycode:
339 return (record->country_code);
340 case dns_geoip_city_countrycode3:
341 return (record->country_code3);
342 case dns_geoip_city_countryname:
343 return (record->country_name);
344 case dns_geoip_city_region:
345 return (record->region);
346 case dns_geoip_city_regionname:
347 s = GeoIP_region_name_by_code(record->country_code,
348 record->region);
349 DE_CONST(s, deconst);
350 return (deconst);
351 case dns_geoip_city_name:
352 return (record->city);
353 case dns_geoip_city_postalcode:
354 return (record->postal_code);
355 case dns_geoip_city_continentcode:
356 return (record->continent_code);
357 case dns_geoip_city_timezonecode:
358 s = GeoIP_time_zone_by_country_and_region(record->country_code,
359 record->region);
360 DE_CONST(s, deconst);
361 return (deconst);
362 default:
363 INSIST(0);
367 static isc_boolean_t
368 is_city(dns_geoip_subtype_t subtype) {
369 switch (subtype) {
370 case dns_geoip_city_countrycode:
371 case dns_geoip_city_countrycode3:
372 case dns_geoip_city_countryname:
373 case dns_geoip_city_region:
374 case dns_geoip_city_regionname:
375 case dns_geoip_city_name:
376 case dns_geoip_city_postalcode:
377 case dns_geoip_city_continentcode:
378 case dns_geoip_city_timezonecode:
379 case dns_geoip_city_metrocode:
380 case dns_geoip_city_areacode:
381 return (ISC_TRUE);
382 default:
383 return (ISC_FALSE);
388 * GeoIPRecord lookups are performed if the previous lookup was
389 * from a different IP address than the current, or was for a search
390 * outside the City database.
392 static GeoIPRecord *
393 city_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
394 unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6)
396 GeoIPRecord *record = NULL;
397 geoip_state_t *prev_state = NULL;
399 REQUIRE(db != NULL);
401 #ifndef HAVE_GEOIP_V6
402 /* no IPv6 support? give up now */
403 if (family == AF_INET6)
404 return (NULL);
405 #endif
407 prev_state = get_state_for(family, ipnum, ipnum6);
408 if (prev_state != NULL && is_city(prev_state->subtype))
409 record = prev_state->record;
411 if (record == NULL) {
412 if (family == AF_INET)
413 record = GeoIP_record_by_ipnum(db, ipnum);
414 #ifdef HAVE_GEOIP_V6
415 else
416 record = GeoIP_record_by_ipnum_v6(db, *ipnum6);
417 #endif
418 if (record == NULL)
419 return (NULL);
421 set_state(family, ipnum, ipnum6, subtype,
422 record, NULL, NULL, NULL, 0);
425 return (record);
428 static char *
429 region_string(GeoIPRegion *region, dns_geoip_subtype_t subtype, int *maxlen) {
430 const char *s;
431 char *deconst;
433 REQUIRE(region != NULL);
434 REQUIRE(maxlen != NULL);
436 switch (subtype) {
437 case dns_geoip_region_countrycode:
438 *maxlen = 2;
439 return (region->country_code);
440 case dns_geoip_region_code:
441 *maxlen = 2;
442 return (region->region);
443 case dns_geoip_region_name:
444 *maxlen = 255;
445 s = GeoIP_region_name_by_code(region->country_code,
446 region->region);
447 DE_CONST(s, deconst);
448 return (deconst);
449 default:
450 INSIST(0);
454 static isc_boolean_t
455 is_region(dns_geoip_subtype_t subtype) {
456 switch (subtype) {
457 case dns_geoip_region_countrycode:
458 case dns_geoip_region_code:
459 return (ISC_TRUE);
460 default:
461 return (ISC_FALSE);
466 * GeoIPRegion lookups are performed if the previous lookup was
467 * from a different IP address than the current, or was for a search
468 * outside the Region database.
470 static GeoIPRegion *
471 region_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) {
472 GeoIPRegion *region = NULL;
473 geoip_state_t *prev_state = NULL;
475 REQUIRE(db != NULL);
477 prev_state = get_state_for(AF_INET, ipnum, NULL);
478 if (prev_state != NULL && is_region(prev_state->subtype))
479 region = prev_state->region;
481 if (region == NULL) {
482 region = GeoIP_region_by_ipnum(db, ipnum);
483 if (region == NULL)
484 return (NULL);
486 set_state(AF_INET, ipnum, NULL,
487 subtype, NULL, region, NULL, NULL, 0);
490 return (region);
494 * ISP, Organization, AS Number and Domain lookups are performed if
495 * the previous lookup was from a different IP address than the current,
496 * or was for a search of a different subtype.
498 static char *
499 name_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) {
500 char *name = NULL;
501 geoip_state_t *prev_state = NULL;
503 REQUIRE(db != NULL);
505 prev_state = get_state_for(AF_INET, ipnum, NULL);
506 if (prev_state != NULL && prev_state->subtype == subtype)
507 name = prev_state->name;
509 if (name == NULL) {
510 name = GeoIP_name_by_ipnum(db, ipnum);
511 if (name == NULL)
512 return (NULL);
514 set_state(AF_INET, ipnum, NULL,
515 subtype, NULL, NULL, name, NULL, 0);
518 return (name);
522 * Netspeed lookups are performed if the previous lookup was from a
523 * different IP address than the current, or was for a search of a
524 * different subtype.
526 static int
527 netspeed_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) {
528 geoip_state_t *prev_state = NULL;
529 isc_boolean_t found = ISC_FALSE;
530 int id = -1;
532 REQUIRE(db != NULL);
534 prev_state = get_state_for(AF_INET, ipnum, NULL);
535 if (prev_state != NULL && prev_state->subtype == subtype) {
536 id = prev_state->id;
537 found = ISC_TRUE;
540 if (!found) {
541 id = GeoIP_id_by_ipnum(db, ipnum);
542 set_state(AF_INET, ipnum, NULL,
543 subtype, NULL, NULL, NULL, NULL, id);
546 return (id);
548 #endif /* HAVE_GEOIP */
550 #define DB46(addr, geoip, name) \
551 ((addr->family == AF_INET) ? (geoip->name##_v4) : (geoip->name##_v6))
553 #ifdef HAVE_GEOIP
555 * Find the best database to answer a generic subtype
557 static dns_geoip_subtype_t
558 fix_subtype(const isc_netaddr_t *reqaddr, const dns_geoip_databases_t *geoip,
559 dns_geoip_subtype_t subtype)
561 dns_geoip_subtype_t ret = subtype;
563 switch (subtype) {
564 case dns_geoip_countrycode:
565 if (DB46(reqaddr, geoip, city) != NULL)
566 ret = dns_geoip_city_countrycode;
567 else if (reqaddr->family == AF_INET && geoip->region != NULL)
568 ret = dns_geoip_region_countrycode;
569 else if (DB46(reqaddr, geoip, country) != NULL)
570 ret = dns_geoip_country_code;
571 break;
572 case dns_geoip_countrycode3:
573 if (DB46(reqaddr, geoip, city) != NULL)
574 ret = dns_geoip_city_countrycode3;
575 else if (DB46(reqaddr, geoip, country) != NULL)
576 ret = dns_geoip_country_code3;
577 break;
578 case dns_geoip_countryname:
579 if (DB46(reqaddr, geoip, city) != NULL)
580 ret = dns_geoip_city_countryname;
581 else if (DB46(reqaddr, geoip, country) != NULL)
582 ret = dns_geoip_country_name;
583 break;
584 case dns_geoip_region:
585 if (DB46(reqaddr, geoip, city) != NULL)
586 ret = dns_geoip_city_region;
587 else if (reqaddr->family == AF_INET && geoip->region != NULL)
588 ret = dns_geoip_region_code;
589 break;
590 case dns_geoip_regionname:
591 if (DB46(reqaddr, geoip, city) != NULL)
592 ret = dns_geoip_city_regionname;
593 else if (reqaddr->family == AF_INET && geoip->region != NULL)
594 ret = dns_geoip_region_name;
595 break;
596 default:
597 break;
600 return (ret);
602 #endif /* HAVE_GEOIP */
604 isc_boolean_t
605 dns_geoip_match(const isc_netaddr_t *reqaddr,
606 const dns_geoip_databases_t *geoip,
607 const dns_geoip_elem_t *elt)
609 #ifndef HAVE_GEOIP
610 UNUSED(reqaddr);
611 UNUSED(geoip);
612 UNUSED(elt);
614 return (ISC_FALSE);
615 #else
616 GeoIP *db;
617 GeoIPRecord *record;
618 GeoIPRegion *region;
619 dns_geoip_subtype_t subtype;
620 isc_uint32_t ipnum = 0;
621 int maxlen = 0, id, family;
622 const char *cs;
623 char *s;
624 #ifdef HAVE_GEOIP_V6
625 const geoipv6_t *ipnum6 = NULL;
626 #else
627 const void *ipnum6 = NULL;
628 #endif
630 INSIST(geoip != NULL);
632 family = reqaddr->family;
633 switch (family) {
634 case AF_INET:
635 ipnum = ntohl(reqaddr->type.in.s_addr);
636 break;
637 case AF_INET6:
638 #ifdef HAVE_GEOIP_V6
639 ipnum6 = &reqaddr->type.in6;
640 break;
641 #else
642 return (ISC_FALSE);
643 #endif
644 default:
645 return (ISC_FALSE);
648 subtype = fix_subtype(reqaddr, geoip, elt->subtype);
650 switch (subtype) {
651 case dns_geoip_country_code:
652 maxlen = 2;
653 goto getcountry;
655 case dns_geoip_country_code3:
656 maxlen = 3;
657 goto getcountry;
659 case dns_geoip_country_name:
660 maxlen = 255;
661 getcountry:
662 db = DB46(reqaddr, geoip, country);
663 if (db == NULL)
664 return (ISC_FALSE);
666 INSIST(elt->as_string != NULL);
668 cs = country_lookup(db, subtype, family, ipnum, ipnum6);
669 if (cs != NULL && strncasecmp(elt->as_string, cs, maxlen) == 0)
670 return (ISC_TRUE);
671 break;
673 case dns_geoip_city_countrycode:
674 case dns_geoip_city_countrycode3:
675 case dns_geoip_city_countryname:
676 case dns_geoip_city_region:
677 case dns_geoip_city_regionname:
678 case dns_geoip_city_name:
679 case dns_geoip_city_postalcode:
680 case dns_geoip_city_continentcode:
681 case dns_geoip_city_timezonecode:
682 INSIST(elt->as_string != NULL);
684 db = DB46(reqaddr, geoip, city);
685 if (db == NULL)
686 return (ISC_FALSE);
688 record = city_lookup(db, subtype, family, ipnum, ipnum6);
689 if (record == NULL)
690 break;
692 s = city_string(record, subtype, &maxlen);
693 INSIST(maxlen != 0);
694 if (s != NULL && strncasecmp(elt->as_string, s, maxlen) == 0)
695 return (ISC_TRUE);
696 break;
698 case dns_geoip_city_metrocode:
699 db = DB46(reqaddr, geoip, city);
700 if (db == NULL)
701 return (ISC_FALSE);
703 record = city_lookup(db, subtype, family, ipnum, ipnum6);
704 if (record == NULL)
705 break;
707 if (elt->as_int == record->metro_code)
708 return (ISC_TRUE);
709 break;
711 case dns_geoip_city_areacode:
712 db = DB46(reqaddr, geoip, city);
713 if (db == NULL)
714 return (ISC_FALSE);
716 record = city_lookup(db, subtype, family, ipnum, ipnum6);
717 if (record == NULL)
718 break;
720 if (elt->as_int == record->area_code)
721 return (ISC_TRUE);
722 break;
724 case dns_geoip_region_countrycode:
725 case dns_geoip_region_code:
726 case dns_geoip_region_name:
727 case dns_geoip_region:
728 if (geoip->region == NULL)
729 return (ISC_FALSE);
731 INSIST(elt->as_string != NULL);
733 /* Region DB is not supported for IPv6 */
734 if (family == AF_INET6)
735 return (ISC_FALSE);
737 region = region_lookup(geoip->region, subtype, ipnum);
738 if (region == NULL)
739 break;
741 s = region_string(region, subtype, &maxlen);
742 INSIST(maxlen != 0);
743 if (s != NULL && strncasecmp(elt->as_string, s, maxlen) == 0)
744 return (ISC_TRUE);
745 break;
747 case dns_geoip_isp_name:
748 db = geoip->isp;
749 goto getname;
751 case dns_geoip_org_name:
752 db = geoip->org;
753 goto getname;
755 case dns_geoip_as_asnum:
756 db = geoip->as;
757 goto getname;
759 case dns_geoip_domain_name:
760 db = geoip->domain;
762 getname:
763 if (db == NULL)
764 return (ISC_FALSE);
766 INSIST(elt->as_string != NULL);
767 /* ISP, Org, AS, and Domain are not supported for IPv6 */
768 if (family == AF_INET6)
769 return (ISC_FALSE);
771 s = name_lookup(db, subtype, ipnum);
772 if (s != NULL) {
773 size_t l;
774 if (strcasecmp(elt->as_string, s) == 0)
775 return (ISC_TRUE);
776 if (subtype != dns_geoip_as_asnum)
777 break;
779 * Just check if the ASNNNN value matches.
781 l = strlen(elt->as_string);
782 if (l > 0U && strchr(elt->as_string, ' ') == NULL &&
783 strncasecmp(elt->as_string, s, l) == 0 &&
784 s[l] == ' ')
785 return (ISC_TRUE);
787 break;
789 case dns_geoip_netspeed_id:
790 INSIST(geoip->netspeed != NULL);
792 /* Netspeed DB is not supported for IPv6 */
793 if (family == AF_INET6)
794 return (ISC_FALSE);
796 id = netspeed_lookup(geoip->netspeed, subtype, ipnum);
797 if (id == elt->as_int)
798 return (ISC_TRUE);
799 break;
801 case dns_geoip_countrycode:
802 case dns_geoip_countrycode3:
803 case dns_geoip_countryname:
804 case dns_geoip_regionname:
806 * If these were not remapped by fix_subtype(),
807 * the database was unavailable. Always return false.
809 break;
811 default:
812 INSIST(0);
815 return (ISC_FALSE);
816 #endif
819 void
820 dns_geoip_shutdown(void) {
821 #ifdef HAVE_GEOIP
822 GeoIP_cleanup();
823 #ifdef ISC_PLATFORM_USETHREADS
824 if (state_mctx != NULL)
825 isc_mem_detach(&state_mctx);
826 #endif
827 #else
828 return;
829 #endif