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 https://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
key_mutex_init(void)89 key_mutex_init(void) {
90 RUNTIME_CHECK(isc_mutex_init(&key_mutex) == ISC_R_SUCCESS);
91 }
92
93 static void
free_state(void * arg)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
state_key_init(void)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
clean_state(geoip_state_t * state)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
set_state(unsigned int family,uint32_t ipnum,const geoipv6_t * ipnum6,uint8_t scope,dns_geoip_subtype_t subtype,GeoIPRecord * record,GeoIPRegion * region,char * name,const char * text,int id)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 *
get_state_for(unsigned int family,uint32_t ipnum,const geoipv6_t * ipnum6)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 *
country_lookup(GeoIP * db,dns_geoip_subtype_t subtype,unsigned int family,uint32_t ipnum,const geoipv6_t * ipnum6,uint8_t * scope)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 *
city_string(GeoIPRecord * record,dns_geoip_subtype_t subtype,int * maxlen)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
is_city(dns_geoip_subtype_t subtype)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 *
city_lookup(GeoIP * db,dns_geoip_subtype_t subtype,unsigned int family,uint32_t ipnum,const geoipv6_t * ipnum6,uint8_t * scope)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
region_string(GeoIPRegion * region,dns_geoip_subtype_t subtype,int * maxlen)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
is_region(dns_geoip_subtype_t subtype)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 *
region_lookup(GeoIP * db,dns_geoip_subtype_t subtype,uint32_t ipnum,uint8_t * scope)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 *
name_lookup(GeoIP * db,dns_geoip_subtype_t subtype,uint32_t ipnum,uint8_t * scope)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
netspeed_lookup(GeoIP * db,dns_geoip_subtype_t subtype,uint32_t ipnum,uint8_t * scope)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
fix_subtype(const isc_netaddr_t * reqaddr,const dns_geoip_databases_t * geoip,dns_geoip_subtype_t subtype)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
dns_geoip_match(const isc_netaddr_t * reqaddr,uint8_t * scope,const dns_geoip_databases_t * geoip,const dns_geoip_elem_t * elt)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
dns_geoip_shutdown(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 }
886