]> git.ipfire.org Git - thirdparty/AWStats.git/commitdiff
New: #199 Added geoip6 plugin with support for IPv4 AND IPv6
authorLaurent Destailleur <eldy@destailleur.fr>
Sat, 8 Feb 2014 10:52:16 +0000 (11:52 +0100)
committerLaurent Destailleur <eldy@destailleur.fr>
Sat, 8 Feb 2014 10:52:16 +0000 (11:52 +0100)
docs/awstats_changelog.txt
wwwroot/cgi-bin/awstats.model.conf
wwwroot/cgi-bin/awstats.pl
wwwroot/cgi-bin/plugins/geoip6.pm [new file with mode: 0644]

index a0c0099d2e14b923690f8263c55c4f98ca760b79..ba2f740ba8dace2f4630713be9e64e7193e67476 100644 (file)
@@ -6,6 +6,7 @@ AWStats Changelog
 New features:
 - Add debian patch debian-patches-1019_allow_frame_resize.patch to add
   option nboflastupdatelookuptosave on command line.
+- #199 Added geoip6 plugin with support for IPv4 AND IPv6.
 
 Fixes:
 - Fixes permission on some .pl scripts.
index b152870dd408d3707b9a25937a5d9fae38e10e5c..ab473e451ec65ca49a6612b212cbd5f32feabe53 100644 (file)
@@ -1442,6 +1442,16 @@ color_x="C1B2E2"                         # Background color for number of exit pages (Default = "C1B2
 #
 #LoadPlugin="geoip GEOIP_STANDARD /pathto/GeoIP.dat"
 
+# PLUGIN: GeoIP6
+# REQUIRED MODULES: Geo::IP or Geo::IP::PurePerl (from Maxmind, version >= 1.40)
+# PARAMETERS: [GEOIP_STANDARD | GEOIP_MEMORY_CACHE] [/pathto/geoipv6.dat[+/pathto/override.txt]]
+# DESCRIPTION: Builds a country chart and adds an entry to the hosts 
+# table with country name
+# works with IPv4 and also IPv6 addresses
+# Replace spaces in the path of geoip data file with string "%20".
+#
+#LoadPlugin="geoip6 GEOIP_STANDARD /pathto/GeoIPv6.dat"
+
 # PLUGIN: GeoIP_City_Maxmind
 # REQUIRED MODULES: Geo::IP or Geo::IP::PurePerl (from Maxmind)
 # PARAMETERS: [GEOIP_STANDARD | GEOIP_MEMORY_CACHE] [/pathto/GeoIPCity.dat[+/pathto/override.txt]]
index 7df54070a975ece685666f007d42c6a972b1f51f..fdb8bcc654f02415ce9279dbb131e0f888018725 100755 (executable)
@@ -3118,6 +3118,7 @@ sub Read_Plugins {
                                        'hashfiles'            => 'u',
                                        'geoipfree'            => 'u',
                                        'geoip'                => 'ou',
+                                       'geoip6'               => 'ou',
                                        'geoip_region_maxmind' => 'mou',
                                        'geoip_city_maxmind'   => 'mou',
                                        'geoip_isp_maxmind'    => 'mou',
@@ -3293,6 +3294,7 @@ sub Read_Plugins {
 
 # In output mode, geo ip plugins are not loaded, so message changes are done here (can't be done in plugin init function)
        if (   $PluginsLoaded{'init'}{'geoip'}
+               || $PluginsLoaded{'init'}{'geoip6'}
                || $PluginsLoaded{'init'}{'geoipfree'} )
        {
                $Message[17] = $Message[25] = $Message[148];
@@ -19248,7 +19250,10 @@ if ( $UpdateStats && $FrameName ne 'index' && $FrameName ne 'mainleft' )
                                $HostResolved = $Host;
 
                                # Resolve Domain
-                               if ( $PluginsLoaded{'GetCountryCodeByAddr'}{'geoip'} ) {
+                               if ( $PluginsLoaded{'GetCountryCodeByAddr'}{'geoip6'} ) {
+                                       $Domain = GetCountryCodeByAddr_geoip6($HostResolved);
+                               }
+                               elsif ( $PluginsLoaded{'GetCountryCodeByAddr'}{'geoip'} ) {
                                        $Domain = GetCountryCodeByAddr_geoip($HostResolved);
                                }
 
@@ -19277,7 +19282,10 @@ if ( $UpdateStats && $FrameName ne 'index' && $FrameName ne 'mainleft' )
                                # Resolve Domain
                                if ($ip)
                                {    # If we have ip, we use it in priority instead of hostname
-                                       if ( $PluginsLoaded{'GetCountryCodeByAddr'}{'geoip'} ) {
+                                       if ( $PluginsLoaded{'GetCountryCodeByAddr'}{'geoip6'} ) {
+                                               $Domain = GetCountryCodeByAddr_geoip6($Host);
+                                       }
+                                       elsif ( $PluginsLoaded{'GetCountryCodeByAddr'}{'geoip'} ) {
                                                $Domain = GetCountryCodeByAddr_geoip($Host);
                                        }
 
@@ -19303,7 +19311,10 @@ if ( $UpdateStats && $FrameName ne 'index' && $FrameName ne 'mainleft' )
                                        }
                                }
                                else {
-                                       if ( $PluginsLoaded{'GetCountryCodeByName'}{'geoip'} ) {
+                                       if ( $PluginsLoaded{'GetCountryCodeByName'}{'geoip6'} ) {
+                                               $Domain = GetCountryCodeByName_geoip6($HostResolved);
+                                       }
+                                       elsif ( $PluginsLoaded{'GetCountryCodeByName'}{'geoip'} ) {
                                                $Domain = GetCountryCodeByName_geoip($HostResolved);
                                        }
 
diff --git a/wwwroot/cgi-bin/plugins/geoip6.pm b/wwwroot/cgi-bin/plugins/geoip6.pm
new file mode 100644 (file)
index 0000000..399e587
--- /dev/null
@@ -0,0 +1,270 @@
+#!/usr/bin/perl\r
+# extended geoip.pm by Sven Strickroth <email@cs-ware.de>\r
+#-----------------------------------------------------------------------------\r
+# GeoIP Maxmind AWStats plugin with IPv6 support\r
+# This plugin allow you to get country report with countries detected\r
+# from a Geographical database (GeoIP internal database) instead of domain\r
+# hostname suffix.\r
+# This works with IPv4 and also IPv6\r
+# Needs the IPv6 country database from Maxmind (free).\r
+#-----------------------------------------------------------------------------\r
+# Perl Required Modules: Geo::IP (Geo::IP::PurePerl does not support IPv6 yet)\r
+#-----------------------------------------------------------------------------\r
+\r
+# <-----\r
+# ENTER HERE THE USE COMMAND FOR ALL REQUIRED PERL MODULES\r
+use vars qw/ $type /;\r
+$type='geoip';\r
+if (!eval ('require "Geo/IP.pm";')) {\r
+       $error1=$@;\r
+#      $type='geoippureperl';\r
+#      if (!eval ('require "Geo/IP/PurePerl.pm";')) {\r
+#              $error2=$@;\r
+#              $ret=($error1||$error2)?"Error:\n$error1$error2":"";\r
+               $ret.="Error: Need Perl module Geo::IP";\r
+               return $ret;\r
+#      }\r
+} else {\r
+        Geo::IP->VERSION >= 1.40 || die("Requires Geo/IP.pm >= 1.40");\r
+}\r
+# ----->\r
+#use strict;\r
+no strict "refs";\r
+\r
+\r
+\r
+#-----------------------------------------------------------------------------\r
+# PLUGIN VARIABLES\r
+#-----------------------------------------------------------------------------\r
+# <-----\r
+# ENTER HERE THE MINIMUM AWSTATS VERSION REQUIRED BY YOUR PLUGIN\r
+# AND THE NAME OF ALL FUNCTIONS THE PLUGIN MANAGE.\r
+my $PluginNeedAWStatsVersion="5.4";\r
+my $PluginHooksFunctions="GetCountryCodeByAddr GetCountryCodeByName ShowInfoHost";\r
+my $PluginName = "geoip6";\r
+my $LoadedOverride=0;\r
+my $OverrideFile="";\r
+my %TmpDomainLookup;\r
+# ----->\r
+\r
+# <-----\r
+# IF YOUR PLUGIN NEED GLOBAL VARIABLES, THEY MUST BE DECLARED HERE.\r
+use vars qw/\r
+$gi\r
+/;\r
+# ----->\r
+\r
+\r
+#-----------------------------------------------------------------------------\r
+# PLUGIN FUNCTION: Init_pluginname\r
+#-----------------------------------------------------------------------------\r
+sub Init_geoip6 {\r
+       my $InitParams=shift;\r
+       my $checkversion=&Check_Plugin_Version($PluginNeedAWStatsVersion);\r
+\r
+       # <-----\r
+       # ENTER HERE CODE TO DO INIT PLUGIN ACTIONS\r
+       debug(" Plugin $PluginName: InitParams=$InitParams",1);\r
+       my ($mode,$tmpdatafile)=split(/\s+/,$InitParams,2);\r
+       my ($datafile,$override)=split(/\+/,$tmpdatafile,2);\r
+       if (! $datafile) { $datafile="$PluginName.dat"; }\r
+    else { $datafile =~ s/%20/ /g; }\r
+       if ($type eq 'geoippureperl') {\r
+               if ($mode eq '' || $mode eq 'GEOIP_MEMORY_CACHE')  { $mode=Geo::IP::PurePerl::GEOIP_MEMORY_CACHE(); }\r
+               else { $mode=Geo::IP::PurePerl::GEOIP_STANDARD(); }\r
+       } else {\r
+               if ($mode eq '' || $mode eq 'GEOIP_MEMORY_CACHE')  { $mode=Geo::IP::GEOIP_MEMORY_CACHE(); }\r
+               else { $mode=Geo::IP::GEOIP_STANDARD(); }\r
+       }\r
+       if ($override){$OverrideFile=$override;}\r
+       %TmpDomainLookup=();\r
+       debug(" Plugin $PluginName: GeoIP initialized type=$type mode=$mode override=$override",1);\r
+       if ($type eq 'geoippureperl') {\r
+               $gi = Geo::IP::PurePerl->open($datafile, $mode);\r
+       } else {\r
+               $gi = Geo::IP->open($datafile, $mode);\r
+       }\r
+\r
+# Fails on some GeoIP version\r
+#      debug(" Plugin geoip6: GeoIP initialized database_info=".$gi->database_info());\r
+       # ----->\r
+\r
+       return ($checkversion?$checkversion:"$PluginHooksFunctions");\r
+}\r
+\r
+\r
+#-----------------------------------------------------------------------------\r
+# PLUGIN FUNCTION: GetCountryCodeByAddr_pluginname\r
+# UNIQUE: YES (Only one plugin using this function can be loaded)\r
+# GetCountryCodeByAddr is called to translate an ip into a country code in lower case.\r
+#-----------------------------------------------------------------------------\r
+sub GetCountryCodeByAddr_geoip6 {\r
+    my $param="$_[0]";\r
+       # <-----\r
+       if (! $param) { return ''; }\r
+       my $searchkey;\r
+       if ($param =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { # IPv4 address\r
+               $searchkey = '::'.$param;\r
+        } else {\r
+                $searchkey = $param;\r
+        }\r
+       my $res= TmpLookup_geoip6($param);\r
+       if (! $res) {\r
+               $res=lc($gi->country_code_by_addr_v6($searchkey)) || 'unknown';\r
+               $TmpDomainLookup{$param}=$res;\r
+               if ($Debug) { debug("  Plugin $PluginName: GetCountryCodeByAddr for $searchkey: [$res]",5); }\r
+       }\r
+       elsif ($Debug) { debug("  Plugin $PluginName: GetCountryCodeByAddr for $param: Already resolved to [$res]",5); }\r
+       # ----->\r
+       return $res;\r
+}\r
+\r
+\r
+#-----------------------------------------------------------------------------\r
+# PLUGIN FUNCTION: GetCountryCodeByName_pluginname\r
+# UNIQUE: YES (Only one plugin using this function can be loaded)\r
+# GetCountryCodeByName is called to translate a host name into a country code in lower case.\r
+#-----------------------------------------------------------------------------\r
+sub GetCountryCodeByName_geoip6 {\r
+    my $param="$_[0]";\r
+       # <-----\r
+       if (! $param) { return ''; }\r
+       my $res = TmpLookup_geoip6($param);\r
+       if (! $res) {\r
+               $res=lc($gi->country_code_by_name_v6($param)) || 'unknown';\r
+               $TmpDomainLookup{$param}=$res;\r
+               if ($Debug) { debug("  Plugin $PluginName: GetCountryCodeByName for $param: [$res]",5); }\r
+       }\r
+       elsif ($Debug) { debug("  Plugin $PluginName: GetCountryCodeByName for $param: Already resolved to [$res]",5); }\r
+       # ----->\r
+       return $res;\r
+}\r
+\r
+\r
+#-----------------------------------------------------------------------------\r
+# PLUGIN FUNCTION: ShowInfoHost_pluginname\r
+# UNIQUE: NO (Several plugins using this function can be loaded)\r
+# Function called to add additionnal columns to the Hosts report.\r
+# This function is called when building rows of the report (One call for each\r
+# row). So it allows you to add a column in report, for example with code :\r
+#   print "<TD>This is a new cell for $param</TD>";\r
+# Parameters: Host name or ip\r
+#-----------------------------------------------------------------------------\r
+sub ShowInfoHost_geoip6 {\r
+    my $param="$_[0]";\r
+       # <-----\r
+       if ($param eq '__title__') {\r
+       my $NewLinkParams=${QueryString};\r
+       $NewLinkParams =~ s/(^|&)update(=\w*|$)//i;\r
+       $NewLinkParams =~ s/(^|&)output(=\w*|$)//i;\r
+       $NewLinkParams =~ s/(^|&)staticlinks(=\w*|$)//i;\r
+       $NewLinkParams =~ s/(^|&)framename=[^&]*//i;\r
+       my $NewLinkTarget='';\r
+       if ($DetailedReportsOnNewWindows) { $NewLinkTarget=" target=\"awstatsbis\""; }\r
+       if (($FrameName eq 'mainleft' || $FrameName eq 'mainright') && $DetailedReportsOnNewWindows < 2) {\r
+               $NewLinkParams.="&framename=mainright";\r
+               $NewLinkTarget=" target=\"mainright\"";\r
+       }\r
+       $NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/^&//; $NewLinkParams =~ s/&$//;\r
+       if ($NewLinkParams) { $NewLinkParams="${NewLinkParams}&"; }\r
+\r
+               print "<th width=\"80\">";\r
+        print "<a href=\"#countries\">GeoIP<br />Country</a>";\r
+        print "</th>";\r
+       }\r
+       elsif ($param) {\r
+        my $ip=0;\r
+               my $key;\r
+               if ($param =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { # IPv4 address\r
+                   $ip=4;\r
+                       $key='::'.$param;\r
+               }\r
+               elsif ($param =~ /^[0-9A-F]*:/i) {                                              # IPv6 address\r
+                   $ip=6;\r
+                       $key=$param;\r
+               }\r
+               print "<td>";\r
+               if ($key) {\r
+                       my $res = TmpLookup_geoip6($param);\r
+               if (!$res && $gi) {\r
+                       $res=lc($gi->country_code_by_addr_v6($key));\r
+                }\r
+               if ($Debug) { debug("  Plugin $PluginName: GetCountryByIp for $key: [$res]",5); }\r
+                   if ($res) { print $DomainsHashIDLib{$res}?$DomainsHashIDLib{$res}:"<span style=\"color: #$color_other\">$Message[0]</span>"; }\r
+                   else { print "<span style=\"color: #$color_other\">$Message[0]</span>"; }\r
+               }\r
+               else {\r
+                       my $res = TmpLookup_geoip6($param);\r
+               if (!$res){$res=lc($gi->country_code_by_name_v6($param)) if $gi;}\r
+               if ($Debug) { debug("  Plugin $PluginName: GetCountryByHostname for $param: [$res]",5); }\r
+                   if ($res) { print $DomainsHashIDLib{$res}?$DomainsHashIDLib{$res}:"<span style=\"color: #$color_other\">$Message[0]</span>"; }\r
+                   else { print "<span style=\"color: #$color_other\">$Message[0]</span>"; }\r
+               }\r
+               print "</td>";\r
+       }\r
+       else {\r
+               print "<td>&nbsp;</td>";\r
+       }\r
+       return 1;\r
+       # ----->\r
+}\r
+\r
+#-----------------------------------------------------------------------------\r
+# PLUGIN FUNCTION: LoadOverrideFile\r
+# Attempts to load a comma delimited file that will override the GeoIP database\r
+# Useful for Intranet records\r
+# CSV format: IP,2-char Country code\r
+#-----------------------------------------------------------------------------\r
+sub LoadOverrideFile_geoip6{\r
+       my $filetoload="";\r
+       if ($OverrideFile){\r
+               if (!open(GEOIPFILE, $OverrideFile)){\r
+                       debug("Plugin $PluginName: Unable to open override file: $OverrideFile");\r
+                       $LoadedOverride = 1;\r
+                       return;\r
+               }\r
+       }else{\r
+               my $conf = (exists(&Get_Config_Name) ? Get_Config_Name() : $SiteConfig);\r
+               if ($conf && open(GEOIPFILE,"$DirData/$PluginName.$conf.txt"))  { $filetoload="$DirData/$PluginName.$conf.txt"; }\r
+               elsif (open(GEOIPFILE,"$DirData/$PluginName.txt"))      { $filetoload="$DirData/$PluginName.txt"; }\r
+               else { debug("No override file \"$DirData/$PluginName.txt\": $!"); }\r
+       }\r
+       if ($filetoload)\r
+       {\r
+               # This is the fastest way to load with regexp that I know\r
+               while (<GEOIPFILE>){\r
+                       chomp $_;\r
+                       s/\r//;\r
+                       my @record = split(",", $_);\r
+                       # replace quotes if they were used in the file\r
+                       foreach (@record){ $_ =~ s/"//g; }\r
+                       # store in hash\r
+                       $TmpDomainLookup{$record[0]} = $record[1];\r
+               }\r
+               close GEOIPFILE;\r
+        debug(" Plugin $PluginName: Overload file loaded: ".(scalar keys %TmpDomainLookup)." entries found.");\r
+       }\r
+       $LoadedOverride = 1;\r
+       return;\r
+}\r
+\r
+#-----------------------------------------------------------------------------\r
+# PLUGIN FUNCTION: TmpLookup\r
+# Searches the temporary hash for the parameter value and returns the corresponding\r
+# GEOIP entry\r
+#-----------------------------------------------------------------------------\r
+sub TmpLookup_geoip6(){\r
+       $param = shift;\r
+       if (!$LoadedOverride){&LoadOverrideFile_geoip6();}\r
+       #my $val;\r
+       #if ($gi &&\r
+       #(($type eq 'geoip' && $gi->VERSION >= 1.30) || \r
+       #  $type eq 'geoippureperl' && $gi->VERSION >= 1.17)){\r
+       #       $val = $TmpDomainLookup{$gi->get_ip_address($param)};\r
+       #}\r
+    #else {$val = $TmpDomainLookup{$param};}\r
+    #return $val || '';\r
+    return $TmpDomainLookup{$param}||'';\r
+}\r
+\r
+1;     # Do not remove this line\r