#!/usr/bin/perl # a40404.pl 2007-9-27 by akebia # Rapid logresolve # http://nyan.co.uk/akebia/item/73 use threads; use Thread::Queue; $log_buffer_size = 65536; $dns_children = 128; $dns_cache_file = 'dns_cache.txt'; $dns_cache_ttl = 259200; $dns_show_state = 0; @log_buffer = (); %dns_cache = (); $dns_request = new Thread::Queue; $dns_result = new Thread::Queue; sub dns_thread { for(;;){ my $i = $dns_request->dequeue; if($i eq ''){$dns_request->enqueue(''); last;} my $a = gethostbyaddr(pack("C4", split(/\./, $i)), 2); if($a !~ /[^\.\s]+/){$a = $i;} $dns_result->enqueue("$i,$a"); if($dns_show_state){ print STDERR $dns_request->pending.' '.threads->self->tid()." $i $a \n"; } } } sub save_dns_cache_file { my $f, $w; unless(%dns_cache){return;} if(open($f, '>'.$dns_cache_file)){ foreach $w (keys(%dns_cache)){ if($dns_cache{$w}[0] eq '-'){next;} print $f "$w,$dns_cache{$w}[0],$dns_cache{$w}[1]\n"; } close($f);} } sub empty_log_buffer { my $i, $a, $t = time; for(;;){ $i = $dns_result->dequeue; ($i, $a) = split(/,/, $i); $dns_cache{$i}[0] = $a; $dns_cache{$i}[1] = $t; if($i eq $log_buffer[0][1]){last;} } for(;;){ print $a.$log_buffer[0][2]; shift(@log_buffer); unless(@log_buffer){last;} if($log_buffer[0][0]){$a = $log_buffer[0][1]; next;} $a = $dns_cache{$log_buffer[0][1]}[0]; if($a eq '' || $a eq '-'){last;} } } my $i, $f = ''; my %a = (); foreach(@ARGV){ if(substr($_, 0, 1) eq '-'){$f = $_; $a{$f} = []; next;} if($f ne ''){push(@{$a{$f}}, $_);} } if($a{'-b'}){$log_buffer_size = $a{'-b'}[0];} if($a{'-n'}){$dns_children = $a{'-n'}[0];} if($a{'-d'}){$dns_cache_file = $a{'-d'}[0];} if($a{'-t'}){$dns_cache_ttl = $a{'-t'}[0];} if($a{'-e'}){$dns_show_state = 1;} if($dns_children < 1){exit(-1);} for($i = 0; $i < $dns_children; $i++){threads->new(\&dns_thread);} if(open($f, $dns_cache_file)){ $i = time; while(<$f>){ if(/(.+),(.+),(.+)[,\n]/){ if($i - $3 > $dns_cache_ttl){next;} $dns_cache{$1}[0] = $2; $dns_cache{$1}[1] = $3; }} close($f);} $SIG{'INT'} = sub{save_dns_cache_file; exit(-1);}; while(){ my $a, $t = index($_, ' '); $i = substr($_, 0, $t); $f = substr($_, $t); if($i =~ /^\d+\.\d+\.\d+\.\d+$/){$a = $dns_cache{$i}[0];}else{$a = $i} if($a eq '-'){ $t = []; push(@log_buffer, $t); $$t[0] = 0; $$t[1] = $i; $$t[2] = $f; }elsif($a ne '' || $i eq ''){ unless(@log_buffer){print $a.$f; next;} $t = []; push(@log_buffer, $t); $$t[0] = 1; $$t[1] = $a; $$t[2] = $f; }else{ $dns_request->enqueue($i); $dns_cache{$i}[0] = '-'; $t = []; push(@log_buffer, $t); $$t[0] = 0; $$t[1] = $i; $$t[2] = $f; } if(@log_buffer < $log_buffer_size){next;} empty_log_buffer; } while(@log_buffer){empty_log_buffer;} save_dns_cache_file; $dns_request->enqueue(''); foreach(threads->list()){$_->join;}