1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * SPDX-License-Identifier: MPL-2.0
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 /*! \file */
15
16 #if defined(HAVE_GEOIP2)
17 #include <maxminddb.h>
18 #endif /* if defined(HAVE_GEOIP2) */
19
20 #include <isc/print.h>
21 #include <isc/string.h>
22 #include <isc/util.h>
23
24 #include <dns/geoip.h>
25
26 #include <named/geoip.h>
27 #include <named/log.h>
28
29 static dns_geoip_databases_t geoip_table;
30
31 #if defined(HAVE_GEOIP2)
32 static MMDB_s geoip_country, geoip_city, geoip_as, geoip_isp, geoip_domain;
33
34 static MMDB_s *
open_geoip2(const char * dir,const char * dbfile,MMDB_s * mmdb)35 open_geoip2(const char *dir, const char *dbfile, MMDB_s *mmdb) {
36 char pathbuf[PATH_MAX];
37 unsigned int n;
38 int ret;
39
40 n = snprintf(pathbuf, sizeof(pathbuf), "%s/%s", dir, dbfile);
41 if (n >= sizeof(pathbuf)) {
42 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
43 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
44 "GeoIP2 database '%s/%s': path too long", dir,
45 dbfile);
46 return (NULL);
47 }
48
49 ret = MMDB_open(pathbuf, MMDB_MODE_MMAP, mmdb);
50 if (ret == MMDB_SUCCESS) {
51 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
52 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
53 "opened GeoIP2 database '%s'", pathbuf);
54 return (mmdb);
55 }
56
57 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
58 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
59 "unable to open GeoIP2 database '%s' (status %d)",
60 pathbuf, ret);
61
62 return (NULL);
63 }
64 #endif /* HAVE_GEOIP2 */
65
66 void
named_geoip_init(void)67 named_geoip_init(void) {
68 #if defined(HAVE_GEOIP2)
69 if (named_g_geoip == NULL) {
70 named_g_geoip = &geoip_table;
71 }
72 #else /* if defined(HAVE_GEOIP2) */
73 return;
74 #endif /* if defined(HAVE_GEOIP2) */
75 }
76
77 void
named_geoip_load(char * dir)78 named_geoip_load(char *dir) {
79 #if defined(HAVE_GEOIP2)
80 REQUIRE(dir != NULL);
81
82 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
83 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
84 "looking for GeoIP2 databases in '%s'", dir);
85
86 named_g_geoip->country = open_geoip2(dir, "GeoIP2-Country.mmdb",
87 &geoip_country);
88 if (named_g_geoip->country == NULL) {
89 named_g_geoip->country = open_geoip2(
90 dir, "GeoLite2-Country.mmdb", &geoip_country);
91 }
92
93 named_g_geoip->city = open_geoip2(dir, "GeoIP2-City.mmdb", &geoip_city);
94 if (named_g_geoip->city == NULL) {
95 named_g_geoip->city = open_geoip2(dir, "GeoLite2-City.mmdb",
96 &geoip_city);
97 }
98
99 named_g_geoip->as = open_geoip2(dir, "GeoIP2-ASN.mmdb", &geoip_as);
100 if (named_g_geoip->as == NULL) {
101 named_g_geoip->as = open_geoip2(dir, "GeoLite2-ASN.mmdb",
102 &geoip_as);
103 }
104
105 named_g_geoip->isp = open_geoip2(dir, "GeoIP2-ISP.mmdb", &geoip_isp);
106 named_g_geoip->domain = open_geoip2(dir, "GeoIP2-Domain.mmdb",
107 &geoip_domain);
108 #else /* if defined(HAVE_GEOIP2) */
109 UNUSED(dir);
110
111 return;
112 #endif /* if defined(HAVE_GEOIP2) */
113 }
114
115 void
named_geoip_unload(void)116 named_geoip_unload(void) {
117 #ifdef HAVE_GEOIP2
118 if (named_g_geoip->country != NULL) {
119 MMDB_close(named_g_geoip->country);
120 named_g_geoip->country = NULL;
121 }
122 if (named_g_geoip->city != NULL) {
123 MMDB_close(named_g_geoip->city);
124 named_g_geoip->city = NULL;
125 }
126 if (named_g_geoip->as != NULL) {
127 MMDB_close(named_g_geoip->as);
128 named_g_geoip->as = NULL;
129 }
130 if (named_g_geoip->isp != NULL) {
131 MMDB_close(named_g_geoip->isp);
132 named_g_geoip->isp = NULL;
133 }
134 if (named_g_geoip->domain != NULL) {
135 MMDB_close(named_g_geoip->domain);
136 named_g_geoip->domain = NULL;
137 }
138 #endif /* ifdef HAVE_GEOIP2 */
139 }
140
141 void
named_geoip_shutdown(void)142 named_geoip_shutdown(void) {
143 #ifdef HAVE_GEOIP2
144 named_geoip_unload();
145 #endif /* HAVE_GEOIP2 */
146 }
147