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 <stefan.schantl@ipfire.org>
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
This commit is contained in:
Stefan Schantl
2019-01-10 13:00:17 +01:00
committed by Michael Tremer
parent 9d1708e081
commit ff21ff90d2

View File

@@ -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;
# Load the database into memory if not already done
if (!$database) {
$database = Geo::IP::PurePerl->new(GEOIP_MEMORY_CACHE);
# Check if the given address is valid.
unless(&Network::check_ip_address($address)) {
return;
}
# Return the name of the country
return $database->country_code_by_name($address);
# 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 = <ADDRESS>) {
# 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";
# Loop through the file.
while(my $line = <LOCATION>) {
# 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;
}
}
# Close filehandle.
close(LOCATION);
# Return the obtained country code.
return $country_code;
}
# Function to get the flag icon for a specified country code.