#!/usr/bin/perl -w ############################################################################ # # # This file is part of the IPFire Firewall. # # # # IPFire is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # IPFire 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 General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with IPFire; if not, write to the Free Software # # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # # Copyright (C) 2015 IPFire Team . # # # ############################################################################ package GeoIP; use Location; use Locale::Codes::Country; # Hash which contains country codes and their names which are special or not # part of ISO 3166-1. my %not_iso_3166_location = ( "a1" => "Anonymous Proxy", "a2" => "Satellite Provider", "a3" => "Worldwide Anycast Instance", "an" => "Netherlands Antilles", "ap" => "Asia/Pacific Region", "eu" => "Europe", "fx" => "France, Metropolitan", "o1" => "Other Country", "yu" => "Yugoslavia" ); # Directory where the libloc database and keyfile lives. our $location_dir = "/var/lib/location/"; # Libloc database file. our $database = "$location_dir/database.db"; # Libloc keyfile to verify the database. our $keyfile = "$location_dir/signing-key.pem"; # Directory which contains the exported databases. our $xt_geoip_db_directory = "/usr/share/xt_geoip/"; # ## Tiny function to init the location database. # sub init () { # Init and open the database. my $db = &Location::init($database); # Return the database handle. return $db; } # ## Function to verify the integrity of the location database. # sub verify ($) { my ($db_handle) = @_; # Verify the integrity of the database. if(&Location::verify($db_handle, $keyfile)) { # Success, return "1". return 1; } # If we got here, return nothing. return; } # ## Function to the the country code of a given address. # sub lookup_country_code($$) { my ($db_handle, $address) = @_; # Lookup the given address. my $country_code = &Location::lookup_country_code($db_handle, $address); # Return the name of the country return $country_code; } # Function to get the flag icon for a specified country code. sub get_flag_icon($) { my ($input) = @_; # Webserver's root dir. (Required for generating full path) my $webroot = "/srv/web/ipfire/html"; # Directory which contains the flag icons. my $flagdir = "/images/flags"; # File extension of the country flags. my $ext = "png"; # Remove whitespaces. chomp($input); # Convert given country code to upper case. my $ccode = uc($input); # Generate filename, based on the contry code in lower case # and the defined file extension. my $file = join('.', $ccode,$ext); # Generate path inside webroot to the previously generated file. my $flag_icon = join('/', $flagdir,$file); # Generate absolute path to the icon file. my $absolute_path = join('', $webroot,$flag_icon); # Check if the a icon file exists. if (-e "$absolute_path") { # Return content of flag_icon. return $flag_icon; } else { # If no icon for the specified country exists, try to use # the icon for "unknown". my $ccode = "unknown"; # Redoing all the stuff from above for the "unknown" icon. my $file = join('.', $ccode, $ext); my $flag_icon = join('/', $flagdir, $file); my $absolute_path = join('', $webroot, $flag_icon); # Check if the icon is present. if (-e "$absolute_path") { # Return "unknown" icon. return $flag_icon; } } } # Function to get the county name by a given country code. sub get_full_country_name($) { my ($input) = @_; my $name; # Remove whitespaces. chomp($input); # Convert input into lower case format. my $code = lc($input); # Handle country codes which are not in the list. if ($not_iso_3166_location{$code}) { # Grab location name from hash. $name = $not_iso_3166_location{$code}; } else { # Use perl built-in module to get the country code. $name = &Locale::Codes::Country::code2country($code); } return $name; } # Function to get all available GeoIP locations. sub get_geoip_locations() { my @locations = (); # Get listed country codes from ISO 3166-1. @locations = &Locale::Codes::Country::all_country_codes(); # Add locations from not_iso_3166_locations. foreach my $location (keys %not_iso_3166_location) { push(@locations, $location); } # Sort locations array in alphabetical order. my @sorted_locations = sort(@locations); # Return the array.. return @sorted_locations; } # Function to get the continent code of a given country code. sub get_continent_code($$) { my ($db_handle, $ccode) = @_; # Omit the continent code. my $continent_code = &Location::get_continent_code($db_handle, $ccode); return $continent_code; } # Function to flush all exported GeoIP locations. sub flush_exported_locations () { # Check if the xt_geoip_db_directory exists. if (-e $xt_geoip_db_directory) { # Perform a direcory listing. opendir (DIR, $xt_geoip_db_directory) or die "Could not open $xt_geoip_db_directory. $!\n"; # Loop through the files. while (my $file = readdir(DIR)) { # Check if the element is a file. if (-f "$xt_geoip_db_directory/$file") { # Delete it. unlink("$xt_geoip_db_directory/$file"); } } } } # Function which calls location-exporter to export a given array # of locations. sub export_locations (\@) { my @locations = @{ shift() }; # String to store the given locations and pass it to the exporter tool. my $locations_string; # Only export IPv4 addresses. my $family = "--family=ipv4"; # Specify xt_geoip as output format. my $format = "--format=xt_geoip"; # Location export command. my @command = ("/usr/bin/location-exporter", "--directory=$xt_geoip_db_directory", "$format", "$family"); # Check if the export directory exists, otherwise create it. unless (-d $xt_geoip_db_directory) { mkdir $xt_geoip_db_directory }; # Loop through the array of locations which needs to be exported. foreach my $location (@locations) { # Add location to the command array. push(@command, $location); } # Execute location-exporter to export the requested country codes. system(@command) == 0 or die "@command failed: $?"; } 1;