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