/* * 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_aso(struct ndpi_detection_module_struct *ndpi_str, char *ip, char *aso, u_int8_t aso_len) { #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 && aso_len > 0) { 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)) aso[0] = '\0'; else { /* Get the ASO */ if (aso_len > 0) { status = MMDB_get_value(&result.entry, &entry_data, "autonomous_system_organization", NULL); if (status != MMDB_SUCCESS || !entry_data.has_data) aso[0] = '\0'; else { int str_len = ndpi_min(entry_data.data_size, aso_len); memcpy(aso, entry_data.utf8_string, str_len); aso[str_len] = '\0'; } } } return (0); } #else (void)ndpi_str; (void)ip; (void)aso; (void)aso_len; #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); } int ndpi_get_geoip_country_continent_city(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, char *city, u_int8_t city_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'; } } if (city_len > 0) { status = MMDB_get_value(&result.entry, &entry_data, "city", "names", "en", NULL); if ((status != MMDB_SUCCESS) || (!entry_data.has_data)) city[0] = '\0'; else { int len = ndpi_min(entry_data.data_size, city_len); memcpy(city, entry_data.utf8_string, len); city[len] = 0; } } return (0); } } #else (void)ndpi_str; (void)ip; (void)country_code; (void)country_code_len; (void)continent; (void)continent_len; (void)city; (void)city_len; #endif return (-2); }