diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f4f949a6f..fcdc3a71c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,11 +140,11 @@ include_directories(BEFORE # Optional Dependencies set(USE_GEOIP false) -find_package(LibGeoIP) -if (LIBGEOIP_FOUND) +find_package(LibMMDB) +if (LibMMDB_FOUND) set(USE_GEOIP true) - include_directories(BEFORE ${LibGeoIP_INCLUDE_DIR}) - list(APPEND OPTLIBS ${LibGeoIP_LIBRARY}) + include_directories(BEFORE ${LibMMDB_INCLUDE_DIR}) + list(APPEND OPTLIBS ${LibMMDB_LIBRARY}) endif () set(USE_KRB5 false) @@ -323,7 +323,7 @@ message( "\nBroctl: ${INSTALL_BROCTL}" "\nAux. Tools: ${INSTALL_AUX_TOOLS}" "\n" - "\nGeoIP: ${USE_GEOIP}" + "\nlibmaxminddb: ${USE_GEOIP}" "\nKerberos: ${USE_KRB5}" "\ngperftools found: ${HAVE_PERFTOOLS}" "\n tcmalloc: ${USE_PERFTOOLS_TCMALLOC}" diff --git a/NEWS b/NEWS index 3cb0fd79b3..921c402c76 100644 --- a/NEWS +++ b/NEWS @@ -356,6 +356,15 @@ Changed Functionality - The string_to_pattern() built-in (and the now-deprecated merge_pattern() built-in) is no longer restricted to only be called at initialization time. +- GeoIP Legacy Database support has been replaced with GeoIP2 MaxMind DB + format support. + + - This updates the "lookup_location" and "lookup_asn" BIFs to use + libmaxminddb. The motivation for this is that MaxMind is discontinuing + GeoLite Legacy databases: no updates after April 1, 2018, no downloads + after January 2, 2019. It's also noted that all GeoIP Legacy databases + may be discontinued as they are superseded by GeoIP2. + Removed Functionality --------------------- diff --git a/bro-config.h.in b/bro-config.h.in index 19ab863a3f..1b351e550f 100644 --- a/bro-config.h.in +++ b/bro-config.h.in @@ -111,12 +111,6 @@ /* Define if KRB5 is available */ #cmakedefine USE_KRB5 -/* Whether the found GeoIP API supports IPv6 Country Edition */ -#cmakedefine HAVE_GEOIP_COUNTRY_EDITION_V6 - -/* Whether the found GeoIP API supports IPv6 City Edition */ -#cmakedefine HAVE_GEOIP_CITY_EDITION_REV0_V6 - /* Use Google's perftools */ #cmakedefine USE_PERFTOOLS_DEBUG diff --git a/configure b/configure index 830a70b60f..56954368ef 100755 --- a/configure +++ b/configure @@ -72,7 +72,7 @@ Usage: $0 [OPTION]... [VAR=VALUE]... (a required Broker dependency) Optional Packages in Non-Standard Locations: - --with-geoip=PATH path to the libGeoIP install root + --with-geoip=PATH path to the libmaxminddb install root --with-krb5=PATH path to krb5 install root --with-perftools=PATH path to Google Perftools install root --with-jemalloc=PATH path to jemalloc install root @@ -252,7 +252,7 @@ while [ $# -ne 0 ]; do append_cache_entry BISON_EXECUTABLE PATH $optarg ;; --with-geoip=*) - append_cache_entry LibGeoIP_ROOT_DIR PATH $optarg + append_cache_entry LibMMDB_ROOT_DIR PATH $optarg ;; --with-krb5=*) append_cache_entry LibKrb5_ROOT_DIR PATH $optarg diff --git a/doc/frameworks/geoip.rst b/doc/frameworks/geoip.rst index d756f97589..d826aabff6 100644 --- a/doc/frameworks/geoip.rst +++ b/doc/frameworks/geoip.rst @@ -8,11 +8,13 @@ GeoLocation .. rst-class:: opening During the process of creating policy scripts the need may arise - to find the geographic location for an IP address. Bro has support + to find the geographic location for an IP address. Bro had support for the `GeoIP library `__ at the - policy script level beginning with release 1.3 to account for this - need. To use this functionality, you need to first install the libGeoIP - software, and then install the GeoLite city database before building + policy script level from release 1.3 to 2.5.X to account for this + need. Starting with release 2.6 GeoIP support requires `libmaxminddb + `__. + To use this functionality, you need to first install the libmaxminddb + software, and then install the GeoLite2 city database before building Bro. .. contents:: @@ -20,85 +22,91 @@ GeoLocation Install libGeoIP ---------------- -Before building Bro, you need to install libGeoIP. +Before building Bro, you need to install libmaxminddb. * FreeBSD: .. console:: - sudo pkg install GeoIP + sudo pkg install libmaxminddb * RPM/RedHat-based Linux: .. console:: - sudo yum install GeoIP-devel + sudo yum install libmaxminddb-devel * DEB/Debian-based Linux: .. console:: - sudo apt-get install libgeoip-dev + sudo apt-get install libmaxminddb-dev * Mac OS X: You need to install from your preferred package management system (e.g. MacPorts, Fink, or Homebrew). The name of the package that you need - may be libgeoip, geoip, or geoip-dev, depending on which package management - system you are using. + may be libmaxminddb, maxminddb, or libmaxminddb-dev, depending on which + package management system you are using. -GeoIPLite Database Installation -------------------------------- +GeoLite2-City Database Installation +----------------------------------- -A country database for GeoIPLite is included when you do the C API -install, but for Bro, we are using the city database which includes -cities and regions in addition to countries. +Bro can use the city or country database. The city database includes cities +and regions in addition to countries. -`Download `__ the GeoLite city -binary database: +`Download `__ +the GeoLite2 city binary database: .. console:: - wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz - gunzip GeoLiteCity.dat.gz + wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz + tar zxf GeoLite2-City.tar.gz -Next, the file needs to be renamed and put in the GeoIP database directory. -This directory should already exist and will vary depending on which platform -and package you are using. For FreeBSD, use ``/usr/local/share/GeoIP``. For -Linux, use ``/usr/share/GeoIP`` or ``/var/lib/GeoIP`` (choose whichever one -already exists). +Next, the file "GeoLite2-City_YYYYMMDD/GeoLite2-City.mmdb" needs to be renamed +and put in the GeoIP database directory. This directory should already exist +and will vary depending on which platform and package you are using. For +FreeBSD, use ``/usr/local/share/GeoIP``. For Linux, use ``/usr/share/GeoIP`` +or ``/var/lib/GeoIP`` (choose whichever one already exists). .. console:: - mv GeoLiteCity.dat /GeoIPCity.dat - -Note that there is a separate database for IPv6 addresses, which can also -be installed if you want GeoIP functionality for IPv6. + mv /GeoLite2-City.mmdb /GeoLite2-City.mmdb Testing ------- Before using the GeoIP functionality, it is a good idea to verify that -everything is setup correctly. After installing libGeoIP and the GeoIP city -database, and building Bro, you can quickly check if the GeoIP functionality -works by running a command like this: +everything is setup correctly. After installing libmaxminddb and the GeoIP +city database, and building Bro, you can quickly check if the GeoIP +functionality works by running a command like this: .. console:: bro -e "print lookup_location(8.8.8.8);" -If you see an error message similar to "Failed to open GeoIP City database", -then you may need to either rename or move your GeoIP city database file (the -error message should give you the full pathname of the database file that -Bro is looking for). +If you see an error message similar to "Failed to open GeoIP location +database", then you may need to either rename or move your GeoIP +location database file. Bro looks for location database files in the +following order by default: + + /usr/share/GeoIP/GeoLite2-City.mmdb + /var/lib/GeoIP/GeoLite2-City.mmdb + /usr/local/share/GeoIP/GeoLite2-City.mmdb + /usr/local/var/GeoIP/GeoLite2-City.mmdb + /usr/share/GeoIP/GeoLite2-Country.mmdb + /var/lib/GeoIP/GeoLite2-Country.mmdb + /usr/local/share/GeoIP/GeoLite2-Country.mmdb + /usr/local/var/GeoIP/GeoLite2-Country.mmdb If you see an error message similar to "Bro was not configured for GeoIP -support", then you need to rebuild Bro and make sure it is linked against -libGeoIP. Normally, if libGeoIP is installed correctly then it should -automatically be found when building Bro. If this doesn't happen, then -you may need to specify the path to the libGeoIP installation -(e.g. ``./configure --with-geoip=``). +support", then you either need to rebuild Bro and make sure it is linked +against libmaxminddb or else set the :bro:see:`mmdb_dir`` value +correctly. Normally, if libmaxminddb is installed correctly then it +should automatically be found when building Bro. If this doesn't +happen, then you may need to specify the path to the libmaxminddb +installation (e.g. ``./configure --with-geoip=``). Usage ----- diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index c502607cbd..b39490ed7e 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -872,6 +872,9 @@ type geo_location: record { longitude: double &optional; ##< Longitude. } &log; +## The directory containing MaxMind DB (*.mmdb) files to use for GeoIP support. +const mmdb_dir: string = "" &redef; + ## Computed entropy values. The record captures a number of measures that are ## computed in parallel. See `A Pseudorandom Number Sequence Test Program ## `_ for more information, Bro uses the same diff --git a/src/bro.bif b/src/bro.bif index c7b26dea04..d6cacec96d 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -3599,77 +3599,269 @@ function lookup_hostname%(host: string%) : addr_set %%{ #ifdef USE_GEOIP extern "C" { -#include +#include +#include +#include +#include +#include } -static GeoIP* open_geoip_db(GeoIPDBTypes type) +class MMDB { +public: + MMDB(const char* filename); + + ~MMDB(); + + MMDB_lookup_result_s Lookup(const struct sockaddr* const sa); + +private: + MMDB_s mmdb; +}; + +MMDB::MMDB(const char *filename) { - GeoIP* geoip = 0; + int status = MMDB_open(filename, MMDB_MODE_MMAP, &mmdb); - if ( GeoIP_db_avail(type) ) - geoip = GeoIP_open_type(type, GEOIP_MEMORY_CACHE); - - return geoip; + if ( MMDB_SUCCESS != status ) + { + throw std::runtime_error(MMDB_strerror(status)); + } } -static GeoIP* open_geoip_city_db() +MMDB::~MMDB() { - GeoIP* geoip = open_geoip_db(GEOIP_CITY_EDITION_REV0); - - if ( ! geoip ) - geoip = open_geoip_db(GEOIP_CITY_EDITION_REV1); - - if ( ! geoip ) - { - string rev0_path = GeoIPDBFileName[GEOIP_CITY_EDITION_REV0]; - string rev1_path = GeoIPDBFileName[GEOIP_CITY_EDITION_REV1]; - string db_path = rev0_path; - - // Maybe in the future the revisions won't share a common default path. - if ( rev0_path != rev1_path ) - db_path = rev0_path + " or " + rev1_path; - - reporter->Info("Failed to open GeoIP City database: %s", - db_path.c_str()); - } - - return geoip; + MMDB_close(&mmdb); } -static GeoIP* open_geoip_city_db_v6() +MMDB_lookup_result_s MMDB::Lookup(const struct sockaddr* const sa) { - GeoIP* geoip = 0; + int mmdb_error; + MMDB_lookup_result_s result = MMDB_lookup_sockaddr(&mmdb, sa, &mmdb_error); - // Both city edition revisions for IPv6 show up in libGeoIP 1.4.7. -#ifdef HAVE_GEOIP_CITY_EDITION_REV0_V6 - geoip = open_geoip_db(GEOIP_CITY_EDITION_REV0_V6); - - if ( ! geoip ) - geoip = open_geoip_db(GEOIP_CITY_EDITION_REV1_V6); - - if ( ! geoip ) + if ( MMDB_SUCCESS != mmdb_error ) { - string rev0_path = GeoIPDBFileName[GEOIP_CITY_EDITION_REV0_V6]; - string rev1_path = GeoIPDBFileName[GEOIP_CITY_EDITION_REV1_V6]; - string db_path = rev0_path; - - // Maybe in the future the revisions won't share a common default path. - if ( rev0_path != rev1_path ) - db_path = rev0_path + " or " + rev1_path; - - reporter->Info("Failed to open GeoIP Cityv6 database: %s", - db_path.c_str()); + throw std::runtime_error(MMDB_strerror(mmdb_error)); } -#endif - return geoip; + return result; + } + +std::unique_ptr mmdb_loc; +std::unique_ptr mmdb_asn; + +static bool mmdb_open(const char* filename, bool asn) + { + struct stat buf; + + if ( 0 != stat(filename, &buf) ) + { + return false; + } + + try + { + if ( asn ) + { + mmdb_asn.reset(new MMDB(filename)); + } + else + { + mmdb_loc.reset(new MMDB(filename)); + } + } + + catch ( const std::exception& e ) + { + reporter->Info("Failed to open MaxMind DB: %s [%s]", filename, + e.what()); + return false; + } + + return true; + } + +static bool mmdb_open_loc(const char* filename) + { + return mmdb_open(filename, false); + } + +static bool mmdb_open_asn(const char* filename) + { + return mmdb_open(filename, true); + } + +static bool mmdb_lookup(const IPAddr& addr, MMDB_lookup_result_s& result, + bool asn) + { + struct sockaddr_storage ss = {0}; + + if ( IPv4 == addr.GetFamily() ) + { + struct sockaddr_in* sa = (struct sockaddr_in*)&ss; + sa->sin_family = AF_INET; + addr.CopyIPv4(&sa->sin_addr); + } + + else + { + struct sockaddr_in6* sa = (struct sockaddr_in6*)&ss; + sa->sin6_family = AF_INET6; + addr.CopyIPv6(&sa->sin6_addr); + } + + try + { + result = asn ? mmdb_asn->Lookup((struct sockaddr*)&ss) + : mmdb_loc->Lookup((struct sockaddr*)&ss); + } + + catch ( const std::exception& e ) + { + reporter->Info("MaxMind DB lookup location error [%s]", + e.what()); + return false; + } + + return result.found_entry; + } + +static bool mmdb_lookup_loc(const IPAddr& addr, MMDB_lookup_result_s& result) + { + return mmdb_lookup(addr, result, false); + } + +static bool mmdb_lookup_asn(const IPAddr& addr, MMDB_lookup_result_s& result) + { + return mmdb_lookup(addr, result, true); + } + +static Val* mmdb_getvalue(MMDB_entry_data_s* entry_data, int status, + int data_type ) + { + switch (status) + { + case MMDB_SUCCESS: + if ( entry_data->has_data ) + { + switch (data_type) + { + case MMDB_DATA_TYPE_UTF8_STRING: + return new StringVal(entry_data->data_size, + entry_data->utf8_string); + break; + + case MMDB_DATA_TYPE_DOUBLE: + return new Val(entry_data->double_value, TYPE_DOUBLE); + break; + + case MMDB_DATA_TYPE_UINT32: + return new Val(entry_data->uint32, TYPE_COUNT); + + default: + break; + } + } + break; + + case MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR: + // key doesn't exist, nothing to do + break; + + default: + reporter->Info("MaxMind DB error [%s]", MMDB_strerror(status)); + break; + } + + return nullptr; + } + +static bool mmdb_try_open_loc () + { + // City database is always preferred over Country database. + auto mmdb_dir_val = global_scope()->Lookup("mmdb_dir")->ID_Val(); + std::string mmdb_dir = mmdb_dir_val->AsString()->CheckString(); + + if ( ! mmdb_dir.empty() ) + { + auto d = mmdb_dir + "/GeoLite2-City.mmdb"; + + if ( mmdb_open_loc(d.data()) ) + return true; + + d = mmdb_dir + "/GeoLite2-Country.mmdb"; + + if ( mmdb_open_loc(d.data()) ) + return true;; + } + + return mmdb_open_loc("/usr/share/GeoIP/GeoLite2-City.mmdb") + || mmdb_open_loc("/var/lib/GeoIP/GeoLite2-City.mmdb") + || mmdb_open_loc("/usr/local/share/GeoIP/GeoLite2-City.mmdb") + || mmdb_open_loc("/usr/local/var/GeoIP/GeoLite2-City.mmdb") + || mmdb_open_loc("/usr/share/GeoIP/GeoLite2-Country.mmdb") + || mmdb_open_loc("/var/lib/GeoIP/GeoLite2-Country.mmdb") + || mmdb_open_loc("/usr/local/share/GeoIP/GeoLite2-Country.mmdb") + || mmdb_open_loc("/usr/local/var/GeoIP/GeoLite2-Country.mmdb"); + } + +static bool mmdb_try_open_asn () + { + auto mmdb_dir_val = global_scope()->Lookup("mmdb_dir")->ID_Val(); + std::string mmdb_dir = mmdb_dir_val->AsString()->CheckString(); + + if ( ! mmdb_dir.empty() ) + { + auto d = mmdb_dir + "/GeoLite2-ASN.mmdb"; + + if ( mmdb_open_asn(d.data()) ) + return true; + } + + return mmdb_open_asn("/usr/share/GeoIP/GeoLite2-ASN.mmdb") + || mmdb_open_asn("/var/lib/GeoIP/GeoLite2-ASN.mmdb") + || mmdb_open_asn("/usr/local/share/GeoIP/GeoLite2-ASN.mmdb") + || mmdb_open_asn("/usr/local/var/GeoIP/GeoLite2-ASN.mmdb"); } #endif %%} +## Initializes MMDB for later use of lookup_location. +## Requires Bro to be built with ``libmaxminddb``. +## +## f: The filename of the MaxMind City or Country DB. +## +## Returns: A boolean indicating whether the db was successfully opened. +## +## .. bro:see:: lookup_asn +function mmdb_open_location_db%(f: string%) : bool + %{ +#ifdef USE_GEOIP + return new Val(mmdb_open_loc(f->CheckString()), TYPE_BOOL); +#else + return new Val(0, TYPE_BOOL); +#endif + %} + +## Initializes MMDB for later use of lookup_asn. +## Requires Bro to be built with ``libmaxminddb``. +## +## f: The filename of the MaxMind ASN DB. +## +## Returns: A boolean indicating whether the db was successfully opened. +## +## .. bro:see:: lookup_asn +function mmdb_open_asn_db%(f: string%) : bool + %{ +#ifdef USE_GEOIP + return new Val(mmdb_open_asn(f->CheckString()), TYPE_BOOL); +#else + return new Val(0, TYPE_BOOL); +#endif + %} + ## Performs a geo-lookup of an IP address. -## Requires Bro to be built with ``libgeoip``. +## Requires Bro to be built with ``libmaxminddb``. ## ## a: The IP address to lookup. ## @@ -3681,104 +3873,52 @@ function lookup_location%(a: addr%) : geo_location RecordVal* location = new RecordVal(geo_location); #ifdef USE_GEOIP - static bool geoip_initialized = false; - static GeoIP* geoip = 0; - static GeoIP* geoip_v6 = 0; - static bool have_city_db = false; - static bool have_cityv6_db = false; - GeoIPRecord* gir = 0; - const char* cc = 0; - - if ( ! geoip_initialized ) + if ( ! mmdb_loc ) { - geoip_initialized = true; - geoip = open_geoip_city_db(); - - if ( ! geoip ) + if ( ! mmdb_try_open_loc() ) { - geoip = open_geoip_db(GEOIP_COUNTRY_EDITION); - string db_path = GeoIPDBFileName[GEOIP_COUNTRY_EDITION]; - - if ( ! geoip ) - builtin_error(fmt("Failed fall back to GeoIP Country " - "database: %s", - GeoIPDBFileName[GEOIP_COUNTRY_EDITION])); - else - reporter->Info("Fell back to GeoIP Country database"); + builtin_error("Failed to open GeoIP location database"); + return location; } - else - have_city_db = true; - - geoip_v6 = open_geoip_city_db_v6(); - - if ( geoip_v6 ) - have_cityv6_db = true; - -#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6 - if ( ! geoip_v6 ) - { - geoip_v6 = open_geoip_db(GEOIP_COUNTRY_EDITION_V6); - - if ( ! geoip_v6 ) - reporter->Info("Failed to open GeoIPv6 Country database: %s", - GeoIPDBFileName[GEOIP_COUNTRY_EDITION_V6]); - } -#endif - - if ( ! geoip_v6 ) - builtin_error("Can't open GeoIPv6 City/Country database"); } -#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6 - if ( geoip_v6 && a->AsAddr().GetFamily() == IPv6 ) + MMDB_lookup_result_s result; + + if ( mmdb_lookup_loc(a->AsAddr(), result) ) { - geoipv6_t ga; - a->AsAddr().CopyIPv6(&ga); - if ( have_cityv6_db ) - gir = GeoIP_record_by_ipnum_v6(geoip_v6, ga); - else - cc = GeoIP_country_code_by_ipnum_v6(geoip_v6, ga); - } - else -#endif + MMDB_entry_data_s entry_data; + int status; - if ( geoip && a->AsAddr().GetFamily() == IPv4 ) - { - const uint32* bytes; - a->AsAddr().GetBytes(&bytes); - if ( have_city_db ) - gir = GeoIP_record_by_ipnum(geoip, ntohl(*bytes)); - else - cc = GeoIP_country_code_by_ipnum(geoip, ntohl(*bytes)); - } + // Get Country ISO Code + status = MMDB_get_value(&result.entry, &entry_data, + "country", "iso_code", nullptr); + location->Assign(0, mmdb_getvalue(&entry_data, status, + MMDB_DATA_TYPE_UTF8_STRING)); - if ( gir ) - { - if ( gir->country_code ) - location->Assign(0, new StringVal(gir->country_code)); + // Get Major Subdivision ISO Code + status = MMDB_get_value(&result.entry, &entry_data, + "subdivisions", "0", "iso_code", nullptr); + location->Assign(1, mmdb_getvalue(&entry_data, status, + MMDB_DATA_TYPE_UTF8_STRING)); - if ( gir->region ) - location->Assign(1, new StringVal(gir->region)); + // Get City English Name + status = MMDB_get_value(&result.entry, &entry_data, + "city", "names", "en", nullptr); + location->Assign(2, mmdb_getvalue(&entry_data, status, + MMDB_DATA_TYPE_UTF8_STRING)); - if ( gir->city ) - location->Assign(2, new StringVal(gir->city)); + // Get Location Latitude + status = MMDB_get_value(&result.entry, &entry_data, + "location", "latitude", nullptr); + location->Assign(3, mmdb_getvalue(&entry_data, status, + MMDB_DATA_TYPE_DOUBLE)); - if ( gir->latitude ) - location->Assign(3, new Val(gir->latitude, - TYPE_DOUBLE)); + // Get Location Longitude + status = MMDB_get_value(&result.entry, &entry_data, + "location", "longitude", nullptr); + location->Assign(4, mmdb_getvalue(&entry_data, status, + MMDB_DATA_TYPE_DOUBLE)); - if ( gir->longitude ) - location->Assign(4, new Val(gir->longitude, - TYPE_DOUBLE)); - - GeoIPRecord_delete(gir); - - return location; - } - - else if ( cc ) - { - location->Assign(0, new StringVal(cc)); return location; } @@ -3792,64 +3932,45 @@ function lookup_location%(a: addr%) : geo_location } #endif - // We can get here even if we have GeoIP support if we weren't + // We can get here even if we have MMDB support if we weren't // able to initialize it or it didn't return any information for // the address. return location; %} -## Performs an AS lookup of an IP address. -## Requires Bro to be built with ``libgeoip``. +## Performs an ASN lookup of an IP address. +## Requires Bro to be built with ``libmaxminddb``. ## ## a: The IP address to lookup. ## -## Returns: The number of the AS that contains *a*. +## Returns: The number of the ASN that contains *a*. ## ## .. bro:see:: lookup_location function lookup_asn%(a: addr%) : count %{ #ifdef USE_GEOIP - static GeoIP* geoip_asn = 0; - static bool geoip_asn_initialized = false; - char* gir = 0; - - if ( ! geoip_asn_initialized ) + if ( ! mmdb_asn ) { - geoip_asn_initialized = true; - geoip_asn = open_geoip_db(GEOIP_ASNUM_EDITION); - - if ( ! geoip_asn ) - builtin_error(fmt("Can't open GeoIP ASNUM database: %s", - GeoIPDBFileName[GEOIP_ASNUM_EDITION])); - } - - if ( geoip_asn ) - { -// IPv6 support showed up in 1.4.5. -#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6 - if ( a->AsAddr().GetFamily() == IPv6 ) + if ( ! mmdb_try_open_asn() ) { - geoipv6_t ga; - a->AsAddr().CopyIPv6(&ga); - gir = GeoIP_name_by_ipnum_v6(geoip_asn, ga); - } - else -#endif - - if ( a->AsAddr().GetFamily() == IPv4 ) - { - const uint32* bytes; - a->AsAddr().GetBytes(&bytes); - gir = GeoIP_name_by_ipnum(geoip_asn, ntohl(*bytes)); + builtin_error("No open GeoIP ASN database"); + return new Val(0, TYPE_COUNT); } } - if ( gir ) + MMDB_lookup_result_s result; + + if ( mmdb_lookup_asn(a->AsAddr(), result) ) { - // Move the pointer +2 so we don't return - // the first two characters: "AS". - return new Val(atoi(gir+2), TYPE_COUNT); + MMDB_entry_data_s entry_data; + int status; + + // Get Autonomous System Number + status = MMDB_get_value(&result.entry, &entry_data, + "autonomous_system_number", nullptr); + Val* asn = mmdb_getvalue(&entry_data, status, MMDB_DATA_TYPE_UINT32); + return asn == nullptr ? new Val(0, TYPE_COUNT) : asn; } #else // not USE_GEOIP