/* * ndpi_geoip.c * * Copyright (C) 2021 - ntop.org * * This file is part of nDPI, an open source deep packet inspection * library. * * nDPI is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * nDPI is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with nDPI. If not, see . * */ #include #include #include #include #include "ndpi_api.h" #include "ndpi_private.h" #include "ndpi_config.h" #ifdef HAVE_MAXMINDDB #include #endif /* ********************************************************************************* */ int ndpi_load_geoip(struct ndpi_detection_module_struct *ndpi_str, const char *ip_city_data, const char *ip_as_data) { #ifdef HAVE_MAXMINDDB int status; ndpi_str->mmdb_city = (void*)ndpi_malloc(sizeof(MMDB_s)); ndpi_str->mmdb_as = (void*)ndpi_malloc(sizeof(MMDB_s)); if((ndpi_str->mmdb_city == NULL) || (ndpi_str->mmdb_as == NULL)) return(-1); /* Open the MMDB files */ if((status = MMDB_open(ip_city_data, MMDB_MODE_MMAP, (MMDB_s*)ndpi_str->mmdb_city)) != MMDB_SUCCESS) return(-1); else ndpi_str->mmdb_city_loaded = 1; if((status = MMDB_open(ip_as_data, MMDB_MODE_MMAP, (MMDB_s*)ndpi_str->mmdb_as)) != MMDB_SUCCESS) return(-2); else ndpi_str->mmdb_as_loaded = 1; return(0); #else (void)ndpi_str; (void)ip_city_data; (void)ip_as_data; return(-3); #endif } /* ********************************************************************************* */ void ndpi_free_geoip(struct ndpi_detection_module_struct *ndpi_str) { #ifdef HAVE_MAXMINDDB if(ndpi_str->mmdb_city_loaded) MMDB_close((MMDB_s*)ndpi_str->mmdb_city); if(ndpi_str->mmdb_as_loaded) MMDB_close((MMDB_s*)ndpi_str->mmdb_as); ndpi_free(ndpi_str->mmdb_city); ndpi_free(ndpi_str->mmdb_as); #else (void)ndpi_str; #endif } /* ********************************************************************************* */ int ndpi_get_geoip_asn(struct ndpi_detection_module_struct *ndpi_str, char *ip, u_int32_t *asn) { #ifdef HAVE_MAXMINDDB int gai_error, mmdb_error, status; MMDB_lookup_result_s result; MMDB_entry_data_s entry_data; if(ndpi_str->mmdb_as_loaded) { result = MMDB_lookup_string((MMDB_s*)ndpi_str->mmdb_as, ip, &gai_error, &mmdb_error); if((gai_error != 0) || (mmdb_error != MMDB_SUCCESS) || (!result.found_entry)) *asn = 0; else { /* Get the ASN */ if((status = MMDB_get_value(&result.entry, &entry_data, "autonomous_system_number", NULL)) == MMDB_SUCCESS) { if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UINT32) *asn = entry_data.uint32; else *asn = 0; } } return(0); } #else (void)ndpi_str; (void)ip; (void)asn; #endif return(-2); } /* ********************************************************************************* */ int ndpi_get_geoip_country_continent(struct ndpi_detection_module_struct *ndpi_str, char *ip, char *country_code, u_int8_t country_code_len, char *continent, u_int8_t continent_len) { #ifdef HAVE_MAXMINDDB int gai_error, mmdb_error; MMDB_lookup_result_s result; MMDB_entry_data_s entry_data; if(ndpi_str->mmdb_city_loaded) { int status; result = MMDB_lookup_string((MMDB_s*)ndpi_str->mmdb_city, ip, &gai_error, &mmdb_error); if((gai_error != 0) || (mmdb_error != MMDB_SUCCESS) || (!result.found_entry)) country_code[0] = '\0'; else { if(country_code_len > 0) { status = MMDB_get_value(&result.entry, &entry_data, "country", "iso_code", NULL); if((status != MMDB_SUCCESS) || (!entry_data.has_data)) country_code[0] = '\0'; else { int str_len = ndpi_min(entry_data.data_size, country_code_len); memcpy(country_code, entry_data.utf8_string, str_len); country_code[str_len] = '\0'; } } if(continent_len > 0) { status = MMDB_get_value(&result.entry, &entry_data, "continent", "names", "en", NULL); if((status != MMDB_SUCCESS) || (!entry_data.has_data)) continent[0] = '\0'; else { int str_len = ndpi_min(entry_data.data_size, continent_len); memcpy(continent, entry_data.utf8_string, str_len); continent[str_len] = '\0'; } } } return(0); } #else (void)ndpi_str; (void)ip; (void)country_code; (void)country_code_len; (void)continent; (void)continent_len; #endif return(-2); }