1 /* $NetBSD: geoip.c,v 1.5 2021/02/19 16:42:10 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 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 * 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 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 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 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 142 named_geoip_shutdown(void) { 143 #ifdef HAVE_GEOIP2 144 named_geoip_unload(); 145 #endif /* HAVE_GEOIP2 */ 146 } 147