1 /* $NetBSD: geoip.c,v 1.1.1.6 2015/07/08 15:38:01 christos Exp $ */
2
3 /*
4 * Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC")
5 *
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.
9 *
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.
17 */
18
19 /*! \file */
20
21 #include <config.h>
22
23 #include <isc/util.h>
24
25 #include <isc/mem.h>
26 #include <isc/once.h>
27 #include <isc/string.h>
28
29 #include <dns/acl.h>
30 #include <dns/geoip.h>
31
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>
43
44 #ifdef HAVE_GEOIP
45 #include <GeoIP.h>
46 #include <GeoIPCity.h>
47
48 /*
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.
54 *
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().
58 *
59 * for lookups in ISP, AS, Org and Domain we prserve a pointer to
60 * the returned name; these must be freed by free().
61 *
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).
66 *
67 * For lookups in Netspeed we preserve the returned ID.
68 *
69 * XXX: Currently this mechanism is only used for IPv4 lookups; the
70 * family and addr6 fields are to be used IPv6 is added.
71 */
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;
84
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;
91
92 static void
key_mutex_init(void)93 key_mutex_init(void) {
94 RUNTIME_CHECK(isc_mutex_init(&key_mutex) == ISC_R_SUCCESS);
95 }
96
97 static void
free_state(void * arg)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);
106 }
107
108 static isc_result_t
state_key_init(void)109 state_key_init(void) {
110 isc_result_t result;
111
112 result = isc_once_do(&mutex_once, key_mutex_init);
113 if (result != ISC_R_SUCCESS)
114 return (result);
115
116 if (!state_key_initialized) {
117 LOCK(&key_mutex);
118 if (!state_key_initialized) {
119 int ret;
120
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);
127
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;
133 }
134 unlock:
135 UNLOCK(&key_mutex);
136 }
137
138 return (result);
139 }
140 #else
141 geoip_state_t prev_state;
142 #endif
143
144 static void
clean_state(geoip_state_t * state)145 clean_state(geoip_state_t *state) {
146 if (state == NULL)
147 return;
148
149 if (state->record != NULL) {
150 GeoIPRecord_delete(state->record);
151 state->record = NULL;
152 }
153 if (state->region != NULL) {
154 GeoIPRegion_delete(state->region);
155 state->region = NULL;
156 }
157 if (state->name != NULL) {
158 free (state->name);
159 state->name = NULL;
160 }
161 state->ipnum = 0;
162 state->text = NULL;
163 state->id = 0;
164 }
165
166 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)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)
170 {
171 geoip_state_t *state = NULL;
172
173 #ifdef ISC_PLATFORM_USETHREADS
174 isc_result_t result;
175
176 result = state_key_init();
177 if (result != ISC_R_SUCCESS)
178 return (result);
179
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));
187
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);
192 }
193
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
201
202 if (family == AF_INET)
203 state->ipnum = ipnum;
204 else
205 state->ipnum6 = *ipnum6;
206
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;
214
215 return (ISC_R_SUCCESS);
216 }
217
218 static geoip_state_t *
get_state_for(unsigned int family,isc_uint32_t ipnum,const geoipv6_t * ipnum6)219 get_state_for(unsigned int family, isc_uint32_t ipnum,
220 const geoipv6_t *ipnum6)
221 {
222 geoip_state_t *state;
223
224 #ifdef ISC_PLATFORM_USETHREADS
225 isc_result_t result;
226
227 result = state_key_init();
228 if (result != ISC_R_SUCCESS)
229 return (NULL);
230
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
237
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);
243
244 return (NULL);
245 }
246
247 /*
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.
251 */
252 static const char *
country_lookup(GeoIP * db,dns_geoip_subtype_t subtype,unsigned int family,isc_uint32_t ipnum,const geoipv6_t * ipnum6)253 country_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
254 unsigned int family,
255 isc_uint32_t ipnum, const geoipv6_t *ipnum6)
256 {
257 geoip_state_t *prev_state = NULL;
258 const char *text = NULL;
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
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);
303 }
304
305 set_state(family, ipnum, ipnum6, subtype,
306 NULL, NULL, NULL, text, 0);
307 }
308
309 return (text);
310 }
311
312 static char *
city_string(GeoIPRecord * record,dns_geoip_subtype_t subtype,int * maxlen)313 city_string(GeoIPRecord *record, dns_geoip_subtype_t subtype, int *maxlen) {
314 const char *s;
315 char *deconst;
316
317 REQUIRE(record != NULL);
318 REQUIRE(maxlen != NULL);
319
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;
327
328 case dns_geoip_city_countrycode3:
329 *maxlen = 3;
330 break;
331
332 default:
333 /* No fixed length; just use strcasecmp() for comparison */
334 *maxlen = 255;
335 }
336
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);
364 }
365 }
366
367 static isc_boolean_t
is_city(dns_geoip_subtype_t subtype)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);
384 }
385 }
386
387 /*
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.
391 */
392 static GeoIPRecord *
city_lookup(GeoIP * db,dns_geoip_subtype_t subtype,unsigned int family,isc_uint32_t ipnum,const geoipv6_t * ipnum6)393 city_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
394 unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6)
395 {
396 GeoIPRecord *record = NULL;
397 geoip_state_t *prev_state = NULL;
398
399 REQUIRE(db != NULL);
400
401 #ifndef HAVE_GEOIP_V6
402 /* no IPv6 support? give up now */
403 if (family == AF_INET6)
404 return (NULL);
405 #endif
406
407 prev_state = get_state_for(family, ipnum, ipnum6);
408 if (prev_state != NULL && is_city(prev_state->subtype))
409 record = prev_state->record;
410
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);
420
421 set_state(family, ipnum, ipnum6, subtype,
422 record, NULL, NULL, NULL, 0);
423 }
424
425 return (record);
426 }
427
428 static char *
region_string(GeoIPRegion * region,dns_geoip_subtype_t subtype,int * maxlen)429 region_string(GeoIPRegion *region, dns_geoip_subtype_t subtype, int *maxlen) {
430 const char *s;
431 char *deconst;
432
433 REQUIRE(region != NULL);
434 REQUIRE(maxlen != NULL);
435
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);
451 }
452 }
453
454 static isc_boolean_t
is_region(dns_geoip_subtype_t subtype)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);
462 }
463 }
464
465 /*
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.
469 */
470 static GeoIPRegion *
region_lookup(GeoIP * db,dns_geoip_subtype_t subtype,isc_uint32_t ipnum)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;
474
475 REQUIRE(db != NULL);
476
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;
480
481 if (region == NULL) {
482 region = GeoIP_region_by_ipnum(db, ipnum);
483 if (region == NULL)
484 return (NULL);
485
486 set_state(AF_INET, ipnum, NULL,
487 subtype, NULL, region, NULL, NULL, 0);
488 }
489
490 return (region);
491 }
492
493 /*
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.
497 */
498 static char *
name_lookup(GeoIP * db,dns_geoip_subtype_t subtype,isc_uint32_t ipnum)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;
502
503 REQUIRE(db != NULL);
504
505 prev_state = get_state_for(AF_INET, ipnum, NULL);
506 if (prev_state != NULL && prev_state->subtype == subtype)
507 name = prev_state->name;
508
509 if (name == NULL) {
510 name = GeoIP_name_by_ipnum(db, ipnum);
511 if (name == NULL)
512 return (NULL);
513
514 set_state(AF_INET, ipnum, NULL,
515 subtype, NULL, NULL, name, NULL, 0);
516 }
517
518 return (name);
519 }
520
521 /*
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.
525 */
526 static int
netspeed_lookup(GeoIP * db,dns_geoip_subtype_t subtype,isc_uint32_t ipnum)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;
531
532 REQUIRE(db != NULL);
533
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;
538 }
539
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);
544 }
545
546 return (id);
547 }
548 #endif /* HAVE_GEOIP */
549
550 #define DB46(addr, geoip, name) \
551 ((addr->family == AF_INET) ? (geoip->name##_v4) : (geoip->name##_v6))
552
553 #ifdef HAVE_GEOIP
554 /*
555 * Find the best database to answer a generic subtype
556 */
557 static dns_geoip_subtype_t
fix_subtype(const isc_netaddr_t * reqaddr,const dns_geoip_databases_t * geoip,dns_geoip_subtype_t subtype)558 fix_subtype(const isc_netaddr_t *reqaddr, const dns_geoip_databases_t *geoip,
559 dns_geoip_subtype_t subtype)
560 {
561 dns_geoip_subtype_t ret = subtype;
562
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;
598 }
599
600 return (ret);
601 }
602 #endif /* HAVE_GEOIP */
603
604 isc_boolean_t
dns_geoip_match(const isc_netaddr_t * reqaddr,const dns_geoip_databases_t * geoip,const dns_geoip_elem_t * elt)605 dns_geoip_match(const isc_netaddr_t *reqaddr,
606 const dns_geoip_databases_t *geoip,
607 const dns_geoip_elem_t *elt)
608 {
609 #ifndef HAVE_GEOIP
610 UNUSED(reqaddr);
611 UNUSED(geoip);
612 UNUSED(elt);
613
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
629
630 INSIST(geoip != NULL);
631
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);
646 }
647
648 subtype = fix_subtype(reqaddr, geoip, elt->subtype);
649
650 switch (subtype) {
651 case dns_geoip_country_code:
652 maxlen = 2;
653 goto getcountry;
654
655 case dns_geoip_country_code3:
656 maxlen = 3;
657 goto getcountry;
658
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);
665
666 INSIST(elt->as_string != NULL);
667
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;
672
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);
683
684 db = DB46(reqaddr, geoip, city);
685 if (db == NULL)
686 return (ISC_FALSE);
687
688 record = city_lookup(db, subtype, family, ipnum, ipnum6);
689 if (record == NULL)
690 break;
691
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;
697
698 case dns_geoip_city_metrocode:
699 db = DB46(reqaddr, geoip, city);
700 if (db == NULL)
701 return (ISC_FALSE);
702
703 record = city_lookup(db, subtype, family, ipnum, ipnum6);
704 if (record == NULL)
705 break;
706
707 if (elt->as_int == record->metro_code)
708 return (ISC_TRUE);
709 break;
710
711 case dns_geoip_city_areacode:
712 db = DB46(reqaddr, geoip, city);
713 if (db == NULL)
714 return (ISC_FALSE);
715
716 record = city_lookup(db, subtype, family, ipnum, ipnum6);
717 if (record == NULL)
718 break;
719
720 if (elt->as_int == record->area_code)
721 return (ISC_TRUE);
722 break;
723
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);
730
731 INSIST(elt->as_string != NULL);
732
733 /* Region DB is not supported for IPv6 */
734 if (family == AF_INET6)
735 return (ISC_FALSE);
736
737 region = region_lookup(geoip->region, subtype, ipnum);
738 if (region == NULL)
739 break;
740
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;
746
747 case dns_geoip_isp_name:
748 db = geoip->isp;
749 goto getname;
750
751 case dns_geoip_org_name:
752 db = geoip->org;
753 goto getname;
754
755 case dns_geoip_as_asnum:
756 db = geoip->as;
757 goto getname;
758
759 case dns_geoip_domain_name:
760 db = geoip->domain;
761
762 getname:
763 if (db == NULL)
764 return (ISC_FALSE);
765
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);
770
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;
778 /*
779 * Just check if the ASNNNN value matches.
780 */
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);
786 }
787 break;
788
789 case dns_geoip_netspeed_id:
790 INSIST(geoip->netspeed != NULL);
791
792 /* Netspeed DB is not supported for IPv6 */
793 if (family == AF_INET6)
794 return (ISC_FALSE);
795
796 id = netspeed_lookup(geoip->netspeed, subtype, ipnum);
797 if (id == elt->as_int)
798 return (ISC_TRUE);
799 break;
800
801 case dns_geoip_countrycode:
802 case dns_geoip_countrycode3:
803 case dns_geoip_countryname:
804 case dns_geoip_regionname:
805 /*
806 * If these were not remapped by fix_subtype(),
807 * the database was unavailable. Always return false.
808 */
809 break;
810
811 default:
812 INSIST(0);
813 }
814
815 return (ISC_FALSE);
816 #endif
817 }
818
819 void
dns_geoip_shutdown(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
830 }
831