# Release version number $VERSION = "0.20"; $g_version = $VERSION; ## ## Common Functions ## sub number_format { local $_ = shift; 1 while s/^(-?\d+)(\d{3})/$1,$2/; return $_; } sub date_format { my $timestamp = shift; return sprintf('%dd %02d:%02d:%02dh', $timestamp / 86400, $timestamp / 3600 % 24, $timestamp / 60 % 60, $timestamp % 60 ); } # # void error (string errormsg) # # Dies, and optionally mails error messages to $g_mailto. # sub error { my $errormsg = $_[0]; if ($g_mailto && $g_mailpath) { system("echo \"$errormsg\" | $g_mailpath -s \"Perl crashed `date`\" $g_mailto"); } die("$errormsg\n"); } # # string quoteSQL (string varQuote) # # Escapes all quote characters in a variable, making it suitable for use in an # SQL query. Returns the escaped version. # sub quoteSQL { my $varQuote = $_[0]; $varQuote =~ s/\\/\\\\/g; # replace \ with \\ $varQuote =~ s/'/\\'/g; # replace ' with \' return $varQuote; } # # result doQuery (string query) # # Executes the SQL query 'query' and returns the result identifier. # sub doQuery { my ($query, $callref) = @_; my $result = $db_conn->prepare($query) or die("Unable to prepare query:\n$query\n$DBI::errstr\n$callref"); $result->execute or die("Unable to execute query:\n$query\n$DBI::errstr\n$callref"); return $result; } sub doQuery2 { my ($query, $callref) = @_; my $result = $db_conn2->prepare($query) or die("Unable to prepare query:\n$query\n$DBI::errstr\n$callref"); $result->execute or die("Unable to execute query:\n$query\n$DBI::errstr\n$callref"); return $result; } # # string resolveIp (string ip, boolean quiet) # # Do a DNS reverse-lookup on an IP address and return the hostname, or empty # string on error. # sub resolveIp { my ($ip, $quiet) = @_; my ($host) = ""; unless ($g_dns_resolveip) { return ""; } eval { $SIG{ALRM} = sub { die "DNS Timeout\n" }; alarm $g_dns_timeout; # timeout after $g_dns_timeout sec $host = gethostbyaddr(inet_aton($ip), AF_INET); alarm 0; }; if ($@) { my $error = $@; chomp($error); printEvent("DNS", "Resolving hostname (timeout $g_dns_timeout sec) for IP \"$ip\" - $error ", 1); $host = ""; # some error occurred } elsif (!defined($host)) { printEvent("DNS", "Resolving hostname (timeout $g_dns_timeout sec) for IP \"$ip\" - No Host ", 1); $host = ""; # ip did not resolve to any host } else { $host = lc($host); # lowercase printEvent("DNS", "Resolving hostname (timeout $g_dns_timeout sec) for IP \"$ip\" - $host ", 1); } chomp($host); return $host; } # # object queryHostGroups () # # Returns result identifier. # sub queryHostGroups { return &doQuery(" SELECT pattern, name, LENGTH(pattern) AS patternlength FROM hlstats_HostGroups ORDER BY patternlength DESC, pattern ASC "); } # # string getHostGroup (string hostname[, object result]) # # Return host group name if any match, or last 2 or 3 parts of hostname. # sub getHostGroup { my ($hostname, $result) = @_; my $hostgroup = ""; # User can define special named hostgroups in hlstats_HostGroups, i.e. # '.adsl.someisp.net' => 'SomeISP ADSL' $result = &queryHostGroups() unless ($result); $result->execute(); while (my($pattern, $name) = $result->fetchrow_array()) { $pattern = quotemeta($pattern); $pattern =~ s/\\\*/[^.]*/g; # allow basic shell-style globbing in pattern if ($hostname =~ /$pattern$/) { $hostgroup = $name; last; } } if (!$hostgroup) { # # Group by last 2 or 3 parts of hostname, i.e. 'max1.xyz.someisp.net' as # 'someisp.net', and 'max1.xyz.someisp.net.nz' as 'someisp.net.nz'. # Unfortunately some countries do not have categorical SLDs, so this # becomes more complicated. The dom_nosld array below contains a list of # known country codes that do not use categorical second level domains. # If a country uses SLDs and is not listed below, then it will be # incorrectly grouped, i.e. 'max1.xyz.someisp.yz' will become # 'xyz.someisp.yz', instead of just 'someisp.yz'. # # Please mail sgarner@hlstats.org with any additions. # my @dom_nosld = ( "ca", # Canada "ch", # Switzerland "be", # Belgium "de", # Germany "ee", # Estonia "es", # Spain "fi", # Finland "fr", # France "ie", # Ireland "nl", # Netherlands "no", # Norway "ru", # Russia "se", # Sweden ); my $dom_nosld = join("|", @dom_nosld); if ($hostname =~ /([\w-]+\.(?:$dom_nosld|\w\w\w))$/) { $hostgroup = $1; } elsif ($hostname =~ /([\w-]+\.[\w-]+\.\w\w)$/) { $hostgroup = $1; } else { $hostgroup = $hostname; } } return $hostgroup; } # # void doConf (object conf, hash directives) # # Walk through configuration directives, setting values of global variables. #