Make it work with badip system active
[spider.git] / perl / DXCIDR.pm
index 7cb13df0bf4ef7e7f870e99e1a785aa6dc0e0dc7..a91d13967cf7c3db845e6e49df1c954c9fd1ba53 100644 (file)
@@ -26,50 +26,44 @@ my $ipv6;
 my $count4 = 0;
 my $count6 = 0;
 
-# load the badip file
-sub load
-{
-       if ($active) {
-               _load();
-       }
-       LogDbg('DXProt', "DXCIDR: loaded $count4 IPV4 addresses and $count6 IPV6 addresses");
-       return $count4 + $count6;
-}
-
 sub _fn
 {
        return localdata($badipfn);
 }
 
-sub _load
+sub _read
 {
+       my $suffix = shift;
        my $fn = _fn();
+       $fn .= ".$suffix" if $suffix;
        my $fh = IO::File->new($fn);
-       my $count = 0;
+       my @out;
 
-       new();
-       
        if ($fh) {
                while (<$fh>) {
                        chomp;
                        next if /^\s*\#/;
                        next unless /[\.:]/;
-                       add($_);
-                       ++$count;
+                       push @out, $_;
                }
                $fh->close;
-       } elsif (-r $fn) {
-               LogDbg('err', "DXCIDR: $fn not found ($!)");
+       } else {
+               LogDbg('err', "DXCIDR: $fn read error ($!)");
        }
+       return @out;
+}
 
-       clean_prep();
-       
-       return $count;
+sub _load
+{
+       my $suffix = shift;
+       my @in = _read($suffix);
+       return scalar add(@in);
 }
 
 sub _put
 {
-       my $fn = _fn();
+       my $suffix = shift;
+       my $fn = _fn() . ".$suffix";
        my $r = rand;
        my $fh = IO::File->new (">$fn.$r");
        my $count = 0;
@@ -79,29 +73,56 @@ sub _put
                        ++$count;
                }
                move "$fn.$r", $fn;
+               LogDbg('cmd', "DXCIDR: put (re-)written $fn");
        } else {
                LogDbg('err', "DXCIDR: cannot write $fn.$r $!");
        }
        return $count;
 }
 
+sub append
+{
+       return 0 unless $active;
+       
+       my $suffix = shift;
+       my @in = @_;
+       my @out;
+       
+       if ($suffix) {
+               my $fn = _fn() . ".$suffix";
+               my $fh = IO::File->new;
+               if ($fh->open("$fn", "a+")) {
+                       $fh->seek(0, 2);        # belt and braces !!
+                       print $fh "$_\n" for @in;
+                       $fh->close;
+               } else {
+                       LogDbg('err', "DXCIDR::append error appending to $fn $!");
+               }
+       } else {
+               LogDbg('err', "DXCIDR::append require badip suffix");
+       }
+       return scalar @in;
+}
+
 sub add
 {
+       return 0 unless $active;
        my $count = 0;
        
        for my $ip (@_) {
                # protect against stupid or malicious
-               next if /^127\./;
-               next if /^::1$/;
-               if (/\./) {
+               next if $ip =~ /^127\./;
+               next if $ip =~ /^::1$/;
+               if ($ip =~ /\./) {
                        $ipv4->add_any($ip);
                        ++$count;
                        ++$count4;
-               } elsif (/:/) {
+               } elsif ($ip =~ /:/) {
                        $ipv6->add_any($ip);
                        ++$count;
                        ++$count6;
-                       LogDbg('DXProt', "DXCIDR: Added IPV6 $ip address");
+               } else {
+                       LogDbg('err', "DXCIDR::add non-ip address '$ip' read");
                }
        }
        return $count;
@@ -109,6 +130,8 @@ sub add
 
 sub clean_prep
 {
+       return unless $active;
+
        if ($ipv4 && $count4) {
                $ipv4->clean;
                $ipv4->prep_find;
@@ -119,12 +142,6 @@ sub clean_prep
        }
 }
 
-sub save
-{
-       return 0 unless $active;
-       _put() if $count4 || $count6;
-}
-
 sub _sort
 {
        my @in;
@@ -138,6 +155,7 @@ sub _sort
 
 sub list
 {
+       return () unless $active;
        my @out;
        push @out, $ipv4->list if $count4;
        push @out, $ipv6->list if $count6;
@@ -166,13 +184,56 @@ sub init
        import Net::CIDR::Lite;
        $active = 1;
 
+       my $fn = _fn();
+       if (-e $fn) {
+               move $fn, "$fn.base";
+       }
+
+       _touch("$fn.local");
+       
+       reload();
+
+}
+
+sub _touch
+{
+       my $fn = shift;
+       my $now = time;
+       local (*TMP);
+       utime ($now, $now, $fn) || open (TMP, ">>$fn") || LogDbg('err', "DXCIDR::touch: Couldn't touch $fn: $!");
+}
+
+sub reload
+{
+       return 0 unless $active;
+
        new();
 
-       load();
+       my $count = 0;
+       my $files = 0;
+
+       LogDbg('DXProt', "DXCIDR::reload reload database" );
+
+       my $dir;
+       opendir($dir, $main::local_data);
+       while (my $fn = readdir $dir) {
+               next unless my ($suffix) = $fn =~ /^badip\.(\w+)$/;
+               my $c = _load($suffix);
+               LogDbg('DXProt', "DXCIDR::reload: $fn read containing $c ip addresses" );
+               $count += $c;
+               $files++;
+       }
+       closedir $dir;
+       
+       LogDbg('DXProt', "DXCIDR::reload $count ip addresses found (IPV4: $count4 IPV6: $count6) in $files badip files" );
+
+       return $count;
 }
 
 sub new
 {
+       return 0 unless $active;
+
        $ipv4 = Net::CIDR::Lite->new;
        $ipv6 = Net::CIDR::Lite->new;
        $count4 = $count6 = 0;