From ff21ff90d24de0f648d24bb906c45738b81ce67a Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Thu, 10 Jan 2019 13:00:17 +0100 Subject: [PATCH] geoip-functions.pl: Re-write code to lookup the iso country code of a given IP-address. Drop the usage of the old legacy GeoIP perl module which was not able to handle the new GeoLite2 databases. Write some code to directly access the databases and extract the required data. Usage of the GeoIP2 perl module would provide a lot of more functionality which is not used/needed. Unfortunately ir requires at lot of additional perl modules which are not available on IPFire and would only be build and shipped for this module. Buildig all of them will slow down the entire build process, mess up the system and requires a lot more space on disk. Fixes #11962. Signed-off-by: Stefan Schantl Signed-off-by: Michael Tremer --- config/cfgroot/geoip-functions.pl | 75 ++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/config/cfgroot/geoip-functions.pl b/config/cfgroot/geoip-functions.pl index be50d5e142..e8ce8377f5 100644 --- a/config/cfgroot/geoip-functions.pl +++ b/config/cfgroot/geoip-functions.pl @@ -23,21 +23,82 @@ package GeoIP; -use Geo::IP::PurePerl; +require '/var/ipfire/network-functions.pl'; + use Locale::Codes::Country; -my $database; +# Path where all the GeoIP related databases are stored. +my $geoip_database_dir = "/var/lib/GeoIP"; + +# Database which contains all IPv4 networks. +my $address_ipv4_database = "GeoLite2-Country-Blocks-IPv4.csv"; + +# Database wich contains the locations data. +my $location_database = "GeoLite2-Country-Locations-en.csv"; sub lookup($) { my $address = shift; + my $location_id; + my $country_code; + + # Check if the given address is valid. + unless(&Network::check_ip_address($address)) { + return; + } + + # Open the address database. + open(ADDRESS, "$geoip_database_dir/$address_ipv4_database") or die "Could not open $geoip_database_dir/$address_ipv4_database. $!\n"; + + # Loop through the file. + while(my $line =
) { + # Remove newlines. + chomp($line); + + # Split the line content. + my ($network, $geoname_id, $registered_country_geoname_id, $represented_country_geoname_id, $is_anonymous_proxy, $is_satellite_provider) = split(/\,/, $line); + + # Check if the given address is part of the current processed network. + if (&Network::ip_address_in_network($address, $network)) { + # Store the geoname_id for this address. + $location_id = $geoname_id; + + # Break loop. + last; + } + } + + # Return nothing if no location_id could be found. + return unless($location_id); + + # Close filehandle. + close(ADDRESS); + + # Open the location database. + open(LOCATION, "$geoip_database_dir/$location_database") or die "Could not open $geoip_database_dir/$location_database. $!\n"; - # Load the database into memory if not already done - if (!$database) { - $database = Geo::IP::PurePerl->new(GEOIP_MEMORY_CACHE); + # Loop through the file. + while(my $line = ) { + # Remove newlines. + chomp($line); + + # Split the line content. + my ($geoname_id, $locale_code, $continent_code, $continent_name, $country_iso_code, $country_name, $is_in_european_union) = split(/\,/, $line); + + # Check if the correct location_id has been found. + if ($geoname_id eq $location_id) { + # Store the county code. + $country_code = $country_iso_code; + + # Break loop. + last; + } } - # Return the name of the country - return $database->country_code_by_name($address); + # Close filehandle. + close(LOCATION); + + # Return the obtained country code. + return $country_code; } # Function to get the flag icon for a specified country code. -- 2.39.2