Imported Upstream version 1.14
This commit is contained in:
		
							parent
							
								
									b5012c41b3
								
							
						
					
					
						commit
						2357dc9ae5
					
				
					 9 changed files with 1178 additions and 202 deletions
				
			
		
							
								
								
									
										160
									
								
								tools/postfwd-client.pl
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										160
									
								
								tools/postfwd-client.pl
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,160 @@
 | 
			
		|||
#!/usr/bin/perl -w
 | 
			
		||||
 | 
			
		||||
## MODULES
 | 
			
		||||
#use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
use IO::Socket;
 | 
			
		||||
use IO::Pipe;
 | 
			
		||||
use Getopt::Long 2.25 qw(:config no_ignore_case bundling);
 | 
			
		||||
BEGIN {
 | 
			
		||||
    eval { require Time::HiRes };
 | 
			
		||||
    if ($@) {
 | 
			
		||||
        warn "$@";
 | 
			
		||||
        warn "Failed to include optional module Time::HiRes.";
 | 
			
		||||
    } else {
 | 
			
		||||
        Time::HiRes->import( qw(time) );
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## PARAMETERS
 | 
			
		||||
my $syntax = "USAGE: client.pl [ OPTIONS ] <addr>:<port>";
 | 
			
		||||
my $sendstr = 'ccert_fingerprint=
 | 
			
		||||
size=64063
 | 
			
		||||
helo_name=english-breakfast.cloud9.net
 | 
			
		||||
reverse_client_name=english-breakfast.cloud9.net
 | 
			
		||||
queue_id=
 | 
			
		||||
encryption_cipher=
 | 
			
		||||
encryption_protocol=
 | 
			
		||||
etrn_domain=
 | 
			
		||||
ccert_subject=
 | 
			
		||||
request=smtpd_access_policy
 | 
			
		||||
protocol_state=RCPT
 | 
			
		||||
recipient=someone@domain.local
 | 
			
		||||
instance=6748.46adf3f8.62156.0
 | 
			
		||||
protocol_name=ESMTP
 | 
			
		||||
encryption_keysize=0
 | 
			
		||||
recipient_count=0
 | 
			
		||||
ccert_issuer=
 | 
			
		||||
sender=owner-postfix-users@postfix.org
 | 
			
		||||
client_name=english-breakfast.cloud9.net
 | 
			
		||||
client_address=168.100.1.7
 | 
			
		||||
 | 
			
		||||
';
 | 
			
		||||
my $delay = 0.5;
 | 
			
		||||
our $pipe = new IO::Pipe;
 | 
			
		||||
use vars qw( %options %kinder $kind $wait );
 | 
			
		||||
 | 
			
		||||
## COMMAND LINE
 | 
			
		||||
GetOptions( \%options,
 | 
			
		||||
  'verbose|v+',
 | 
			
		||||
  'quiet|q+',
 | 
			
		||||
  'process|p=i',
 | 
			
		||||
  'count|c=i',
 | 
			
		||||
  'timeout|t=i',
 | 
			
		||||
  'file|f=s',
 | 
			
		||||
) or die "$syntax\n";
 | 
			
		||||
die "$syntax\n" unless $ARGV[0];
 | 
			
		||||
map { $options{$_} ||= 1 } qw(count process);
 | 
			
		||||
$options{verbose} ||= 0;
 | 
			
		||||
$options{timeout} ||= 3;
 | 
			
		||||
if (defined $options{file}) {
 | 
			
		||||
  (-f $options{file}) || die "can not find file '".$options{file}."'\n";
 | 
			
		||||
  open (REQUEST, "<".$options{file}) || die "can not open file '".$options{file}."'\n";
 | 
			
		||||
  $sendstr = join "", <REQUEST>;
 | 
			
		||||
  close (REQUEST);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
## FORK
 | 
			
		||||
$| = 1;
 | 
			
		||||
my $starttime = time();
 | 
			
		||||
FORK: for (my $i=0;$i<$options{process};$i++) {
 | 
			
		||||
	$kind = fork();
 | 
			
		||||
	last FORK unless $kind;
 | 
			
		||||
	$kinder{$kind} = 1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
## WHO AM I?
 | 
			
		||||
($kind) ? parent_process() : child_process() ;
 | 
			
		||||
die "should never see me\n";
 | 
			
		||||
exit(1);
 | 
			
		||||
 | 
			
		||||
## PARENT CODE
 | 
			
		||||
sub parent_process {
 | 
			
		||||
  $pipe->reader();
 | 
			
		||||
  use POSIX ":sys_wait_h";
 | 
			
		||||
  undef my @status;
 | 
			
		||||
  # wait until children have finished
 | 
			
		||||
  print ("parent process waiting for ".(scalar keys %kinder)." pids ".(join ' ', (keys %kinder))."\n") unless $options{quiet};
 | 
			
		||||
  PARENT: do {
 | 
			
		||||
    # check pipe for finished children
 | 
			
		||||
    push @status, <$pipe>;
 | 
			
		||||
    # check children
 | 
			
		||||
    CHILD: foreach (keys %kinder) {
 | 
			
		||||
	$wait = waitpid($_,&WNOHANG);
 | 
			
		||||
	last CHILD unless ($wait == -1);
 | 
			
		||||
	delete $kinder{$_};
 | 
			
		||||
    };
 | 
			
		||||
    # sleep a while to reduce cpu usage
 | 
			
		||||
    select(undef, undef, undef, $delay);
 | 
			
		||||
    print ("parent process waiting for ".(scalar keys %kinder)." pids ".(join ' ', (keys %kinder))."\n") if ($options{verbose} > 1);
 | 
			
		||||
  } until (($wait == -1) or (($#status + 1) >= $options{process}));
 | 
			
		||||
  printf ("parent process finished after %.2f seconds.\n", (time() - $starttime)) unless $options{quiet};
 | 
			
		||||
  # display results
 | 
			
		||||
  my $parent_requests = my $parent_errors = my $parent_valid = my $parent_invalid = my $parent_time = 0;
 | 
			
		||||
  foreach (@status) {
 | 
			
		||||
	my($child_requests,$child_errors,$child_valid,$child_invalid,$child_time) = split ';', $_;
 | 
			
		||||
	$parent_requests += $child_requests;
 | 
			
		||||
	$parent_errors += $child_errors;
 | 
			
		||||
	$parent_valid += $child_valid;
 | 
			
		||||
	$parent_invalid += $child_invalid;
 | 
			
		||||
	$parent_time = $child_time if ($child_time > $parent_time);
 | 
			
		||||
  };
 | 
			
		||||
  $parent_time = $parent_time - $starttime;
 | 
			
		||||
  my $parent_rps = ($parent_time) ? ($parent_requests / $parent_time) : 0;
 | 
			
		||||
  printf "%d requests, %d errors, %d valid, %d invalid, %.2fs total time, %.2f requests per second\n",
 | 
			
		||||
	$parent_requests,$parent_errors,$parent_valid,$parent_invalid,$parent_time,$parent_rps;
 | 
			
		||||
  exit (0);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
## CHILD CODE
 | 
			
		||||
sub child_process {
 | 
			
		||||
  $pipe->writer();
 | 
			
		||||
  my $ok = my $nok = 0;
 | 
			
		||||
  undef my $getstr;
 | 
			
		||||
  # open socket
 | 
			
		||||
  my($addr,$port) = split ':', $ARGV[0];
 | 
			
		||||
  if ( ($addr and $port) and my $socket = new IO::Socket::INET (
 | 
			
		||||
    PeerAddr => $addr,
 | 
			
		||||
    PeerPort => $port,
 | 
			
		||||
    Proto    => 'tcp',
 | 
			
		||||
    Timeout  => $options{timeout},
 | 
			
		||||
    Type     => SOCK_STREAM ) ) {
 | 
			
		||||
    # submit requests
 | 
			
		||||
    for (my $i=0; $i<$options{count}; $i++) {
 | 
			
		||||
           printf ("CHILD-$$: asking service $addr:$port\n") if $options{verbose};
 | 
			
		||||
           print $socket "$sendstr";
 | 
			
		||||
           $getstr = <$socket>; <$socket>;
 | 
			
		||||
           chomp($getstr);
 | 
			
		||||
           printf ("CHILD-$$: answer from $addr:$port -> '$getstr'\n") if $options{verbose};
 | 
			
		||||
           $getstr =~ s/^(action=)//;
 | 
			
		||||
           # check answer
 | 
			
		||||
           if ($1 and $getstr) {
 | 
			
		||||
                   $ok++;
 | 
			
		||||
                   printf ("CHILD-$$: OK: answer from $addr:$port -> '$getstr'\n") unless ( $options{quiet} or (($options{count} * $options{process}) > 50) );
 | 
			
		||||
           } else {
 | 
			
		||||
                   $nok++;
 | 
			
		||||
                   warn ("CHILD-$$: FAIL: invalid answer from $addr:$port -> '$getstr'\n");
 | 
			
		||||
           };
 | 
			
		||||
    };
 | 
			
		||||
  } else {
 | 
			
		||||
    warn ("CHILD-$$: can not open socket to $addr:$port\n");
 | 
			
		||||
  };
 | 
			
		||||
  # create summary
 | 
			
		||||
  my $summary = $options{count}.';'.($options{count} - ($ok + $nok)).';'.$ok.';'.$nok.';'.time()."\n";
 | 
			
		||||
  print ("CHILD-$$: child summary: $summary") if ($options{verbose} > 1);
 | 
			
		||||
  # send summary to parent
 | 
			
		||||
  print $pipe "$summary";
 | 
			
		||||
  exit (0);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										297
									
								
								tools/rblcheck.pl
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										297
									
								
								tools/rblcheck.pl
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,297 @@
 | 
			
		|||
#!/usr/bin/perl -T -w
 | 
			
		||||
 | 
			
		||||
# includes
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
use Getopt::Long 2.25 qw(:config no_ignore_case bundling);
 | 
			
		||||
use Net::DNS;
 | 
			
		||||
# include Time::HiRes if available
 | 
			
		||||
BEGIN {
 | 
			
		||||
	eval { require Time::HiRes };
 | 
			
		||||
	Time::HiRes->import( qw(time) ) unless $@;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
# RBLs (ip based)
 | 
			
		||||
our @rbls = qw(
 | 
			
		||||
        zz.countries.nerd.dk
 | 
			
		||||
        query.bondedsender.org
 | 
			
		||||
        exemptions.ahbl.org
 | 
			
		||||
        spf.trusted-forwarder.org
 | 
			
		||||
        list.dnswl.org
 | 
			
		||||
        zen.spamhaus.org
 | 
			
		||||
        b.barracudacentral.org
 | 
			
		||||
        bl.spamcop.net
 | 
			
		||||
        list.dsbl.org
 | 
			
		||||
        multihop.dsbl.org
 | 
			
		||||
        unconfirmed.dsbl.org
 | 
			
		||||
        combined.njabl.org
 | 
			
		||||
        dnsbl.sorbs.net
 | 
			
		||||
        dnsbl.ahbl.org
 | 
			
		||||
        ix.dnsbl.manitu.net
 | 
			
		||||
        dnsbl-1.uceprotect.net
 | 
			
		||||
        dnsbl-2.uceprotect.net
 | 
			
		||||
        dnsbl-3.uceprotect.net
 | 
			
		||||
        ips.backscatterer.org
 | 
			
		||||
        sorbs.dnsbl.net.au
 | 
			
		||||
	t1.dnsbl.net.au
 | 
			
		||||
        korea.services.net
 | 
			
		||||
        blackholes.five-ten-sg.com
 | 
			
		||||
        cbl.anti-spam.org.cn
 | 
			
		||||
        cblplus.anti-spam.org.cn
 | 
			
		||||
        cblless.anti-spam.org.cn
 | 
			
		||||
        bogons.cymru.com
 | 
			
		||||
        dynamic.tqmrbl.com
 | 
			
		||||
        relays.tqmrbl.com
 | 
			
		||||
        clients.tqmrbl.com
 | 
			
		||||
	hostkarma.junkemailfilter.com
 | 
			
		||||
	sip.invaluement.com
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
# RHSBLs (domain based)
 | 
			
		||||
our @rhsbls = qw(
 | 
			
		||||
	rhsbl.sorbs.net
 | 
			
		||||
	rhsbl.ahbl.org
 | 
			
		||||
	multi.surbl.org
 | 
			
		||||
	dsn.rfc-ignorant.org
 | 
			
		||||
	abuse.rfc-ignorant.org
 | 
			
		||||
	whois.rfc-ignorant.org
 | 
			
		||||
	bogusmx.rfc-ignorant.org
 | 
			
		||||
	blackhole.securitysage.com
 | 
			
		||||
	ex.dnsbl.org
 | 
			
		||||
	rddn.dnsbl.net.au
 | 
			
		||||
	block.rhs.mailpolice.com
 | 
			
		||||
	dynamic.rhs.mailpolice.com
 | 
			
		||||
	dnsbl.cyberlogic.net
 | 
			
		||||
	hostkarma.junkemailfilter.com
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
# commandline syntax
 | 
			
		||||
our $syntax = <<__SYNTAX__;
 | 
			
		||||
Usage:	rblcheck3.pl [OPTIONS] <objects>
 | 
			
		||||
 | 
			
		||||
	-h, --help		manual
 | 
			
		||||
	-s, --short		short output
 | 
			
		||||
	-v, --verbose		show dns nxdomain answers (not listed)
 | 
			
		||||
	-n, --noerror		do not show dns query timeouts
 | 
			
		||||
	-t, --timeout=10	dns query timeout setting in seconds
 | 
			
		||||
	    --dnsstats		show dns statistics
 | 
			
		||||
	    --rbls=<list>	override builtin rbls with <list>
 | 
			
		||||
	    --rhsbls=<list>	override builtin rhsbls with <list>
 | 
			
		||||
 | 
			
		||||
	<objects>	list of ips, hostnames and e-mail addresses
 | 
			
		||||
__SYNTAX__
 | 
			
		||||
 | 
			
		||||
# manual
 | 
			
		||||
our $examples = <<__EXAMPLES__;
 | 
			
		||||
Examples:
 | 
			
		||||
 | 
			
		||||
	# check builtin rbls for 192.168.0.1 and rhsbls for host.example.com
 | 
			
		||||
	rblcheck3.pl 192.168.0.1 host.example.com
 | 
			
		||||
 | 
			
		||||
	# same as above
 | 
			
		||||
	rblcheck3.pl host.example.com[192.168.0.1]
 | 
			
		||||
 | 
			
		||||
	# check builtin rhsbls for the domain part "example.com",
 | 
			
		||||
	# set dns timeout to 15 seconds
 | 
			
		||||
	rblcheck3.pl -t 15 john.doe\@example.com
 | 
			
		||||
 | 
			
		||||
	# check spamhaus and spamcop for 192.168.0.1
 | 
			
		||||
	# short output without dns timeout information
 | 
			
		||||
	rblcheck3.pl -ns --rbls=zen.spamhaus.org,bl.spamcop.net 192.168.0.1
 | 
			
		||||
__EXAMPLES__
 | 
			
		||||
 | 
			
		||||
# save current time
 | 
			
		||||
our $starttime = time();
 | 
			
		||||
 | 
			
		||||
# variables
 | 
			
		||||
use vars qw(
 | 
			
		||||
	%dnshits %dnscache %options
 | 
			
		||||
	@queries @lookups @timedout
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
# parse commandline switches
 | 
			
		||||
GetOptions( \%options,
 | 
			
		||||
	"timeout|t=i",
 | 
			
		||||
	"noerror|n",
 | 
			
		||||
	"verbose|v",
 | 
			
		||||
	"short|s+",
 | 
			
		||||
	"dnsstats",
 | 
			
		||||
	"rbls|rbl=s"	 => sub { push @{$options{rbls}},   (split /[,\s]+/, $_[1]) },
 | 
			
		||||
	"rhsbls|rhsbl=s" => sub { push @{$options{rhsbls}}, (split /[,\s]+/, $_[1]) },
 | 
			
		||||
	"help|h"	 => sub { print "\n$syntax\n$examples\n"; exit(1) },
 | 
			
		||||
) or die "\n$syntax\n";
 | 
			
		||||
 | 
			
		||||
# unbuffered output
 | 
			
		||||
#select STDERR; $| = 1;
 | 
			
		||||
#select STDOUT; $| = 1;
 | 
			
		||||
 | 
			
		||||
# optional: override dnsbl lists
 | 
			
		||||
@rbls   = @{$options{rbls}}   if defined $options{rbls};
 | 
			
		||||
@rhsbls = @{$options{rhsbls}} if defined $options{rhsbls};
 | 
			
		||||
 | 
			
		||||
# split client[ip] in two queries
 | 
			
		||||
map { push @queries, (/^([^\]]+)\[(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\]$/) ? ($1, $2) : $_ } @ARGV;
 | 
			
		||||
 | 
			
		||||
# parse queries and create lookup list
 | 
			
		||||
foreach my $query (@queries) {
 | 
			
		||||
	undef my $addr;
 | 
			
		||||
 | 
			
		||||
	# prepare rbls
 | 
			
		||||
	if ($query =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
 | 
			
		||||
		$addr = join ".", reverse split /\./, $query;
 | 
			
		||||
		foreach my $rbl (@rbls) {
 | 
			
		||||
			$dnscache{$addr.".".$rbl}{type}  = 'RBL';
 | 
			
		||||
			$dnscache{$addr.".".$rbl}{query} = $query;
 | 
			
		||||
			$dnscache{$addr.".".$rbl}{list}  = $rbl;
 | 
			
		||||
			push @lookups, $addr.".".$rbl;
 | 
			
		||||
		};
 | 
			
		||||
	# prepare rhsbls
 | 
			
		||||
	} else {
 | 
			
		||||
		# remove localpart if email address
 | 
			
		||||
		$addr = ($query =~ /@([^@]+)$/) ? $1 : $query;
 | 
			
		||||
		foreach my $rbl (@rhsbls) {
 | 
			
		||||
			$dnscache{$addr.".".$rbl}{type}  = 'RHSBL';
 | 
			
		||||
			$dnscache{$addr.".".$rbl}{query} = $query;
 | 
			
		||||
			$dnscache{$addr.".".$rbl}{list}  = $rbl;
 | 
			
		||||
			push @lookups, $addr.".".$rbl;
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
# main: process lookups
 | 
			
		||||
if ( @lookups ) {
 | 
			
		||||
	my $ownres   = Net::DNS::Resolver->new;
 | 
			
		||||
	my $ownsel   = IO::Select->new;
 | 
			
		||||
	my %ownsock  = ();
 | 
			
		||||
	my @ownready = ();
 | 
			
		||||
	my $bgsock   = undef;
 | 
			
		||||
 | 
			
		||||
	# send queries
 | 
			
		||||
	QUERY: foreach my $query (@lookups) {
 | 
			
		||||
		next QUERY unless $query;
 | 
			
		||||
		# send A query
 | 
			
		||||
		$dnscache{$query}{start} = time();
 | 
			
		||||
		$bgsock = $ownres->bgsend($query, 'A');
 | 
			
		||||
		$ownsel->add($bgsock);
 | 
			
		||||
		$ownsock{$bgsock} = 'A:'.$query;
 | 
			
		||||
		# send TXT query
 | 
			
		||||
		$bgsock = $ownres->bgsend($query, 'TXT');
 | 
			
		||||
		$ownsel->add($bgsock);
 | 
			
		||||
		$ownsock{$bgsock} = 'TXT:'.$query;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	# get answers
 | 
			
		||||
        while ((scalar keys %ownsock) and (@ownready = $ownsel->can_read($options{timeout} || 10))) {
 | 
			
		||||
                foreach my $sock (@ownready) {
 | 
			
		||||
                        if (defined $ownsock{$sock}) {
 | 
			
		||||
                                my $packet = $ownres->bgread($sock);
 | 
			
		||||
                                rbl_read_dns ($packet);
 | 
			
		||||
                                delete $ownsock{$sock};
 | 
			
		||||
                        } else {
 | 
			
		||||
                                $ownsel->remove($sock);
 | 
			
		||||
                                $sock = undef;
 | 
			
		||||
                        };
 | 
			
		||||
                };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
	# timeout handling
 | 
			
		||||
	my $now = time();
 | 
			
		||||
	map { push @timedout, (split ':', $ownsock{$_})[1] } (keys %ownsock);
 | 
			
		||||
	map { @{$dnscache{$_}{A}} = '**timeout**'; $dnscache{$_}{end} = $now; delete $dnscache{$_}{log} } (sort @timedout) if @timedout;
 | 
			
		||||
 | 
			
		||||
	# print results
 | 
			
		||||
	map {	# timeout
 | 
			
		||||
		unless (defined $dnscache{$_}{log}) {
 | 
			
		||||
			$dnshits{timeouts}{$dnscache{$_}{list}}++;
 | 
			
		||||
			show_dns ($_) unless $options{noerror};
 | 
			
		||||
		# a-record
 | 
			
		||||
		} elsif ($dnscache{$_}{log}) {
 | 
			
		||||
			$dnshits{hits}{$dnscache{$_}{list}}++;
 | 
			
		||||
			show_dns ($_);
 | 
			
		||||
		# nxdomain
 | 
			
		||||
		} else {
 | 
			
		||||
			$dnshits{nxdomain}{$dnscache{$_}{list}}++;
 | 
			
		||||
			show_dns ($_) if $options{verbose};
 | 
			
		||||
		};
 | 
			
		||||
	} @lookups;
 | 
			
		||||
	printf STDOUT "\n # Finished %d lookups (%d items, %d rbls, %d rhsbls, %.1f%% timeouts) after %.2f seconds\n",
 | 
			
		||||
		($#lookups + 1),
 | 
			
		||||
		($#queries + 1),
 | 
			
		||||
		($#rbls + 1), ($#rhsbls + 1),
 | 
			
		||||
		(($#timedout + 1) / (($#lookups + 1) * 2)) * 100,
 | 
			
		||||
		(time() - $starttime) unless defined $options{short};
 | 
			
		||||
	if ($options{verbose} or $options{dnsstats}) {
 | 
			
		||||
		printf "\n # DNS statistics\n";
 | 
			
		||||
		if (defined $dnshits{hits}) {
 | 
			
		||||
			print " #\n";
 | 
			
		||||
			map { printf STDOUT " # ".$dnshits{hits}{$_}." hits for $_\n" } (sort {($dnshits{hits}{$b} || 0) <=> ($dnshits{hits}{$a} || 0)} keys %{$dnshits{hits}});
 | 
			
		||||
		};
 | 
			
		||||
		if (defined $dnshits{timeouts}) {
 | 
			
		||||
			print " #\n";
 | 
			
		||||
			map { printf STDOUT " # ".$dnshits{timeouts}{$_}." timeouts for $_\n" } (sort {($dnshits{timeouts}{$b} || 0) <=> ($dnshits{timeouts}{$a} || 0)} keys %{$dnshits{timeouts}});
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
	print "\n";
 | 
			
		||||
};
 | 
			
		||||
exit(0);
 | 
			
		||||
 | 
			
		||||
# prints DNS result
 | 
			
		||||
sub show_dns {
 | 
			
		||||
	my $que = shift;
 | 
			
		||||
	my $out = "";
 | 
			
		||||
	if (defined $options{short}) {
 | 
			
		||||
		$out .= $dnscache{$que}{query}
 | 
			
		||||
			."; ".$dnscache{$que}{list}
 | 
			
		||||
			."; ".(join ', ', @{$dnscache{$que}{A}});
 | 
			
		||||
		$out .=  "; ".(join '. ', @{$dnscache{$que}{TXT}}) if defined $dnscache{$que}{TXT} and ($options{verbose} or ($options{short} < 2));
 | 
			
		||||
	} else {
 | 
			
		||||
		$out .= "\n  ".sprintf ("%15s", $dnscache{$que}{query})."  ".$dnscache{$que}{type}.": ".$dnscache{$que}{list};
 | 
			
		||||
		$out .= "  (cname: ".(join ', ', (keys %{$dnscache{$que}{CNAME}})).")" if defined $dnscache{$que}{CNAME};
 | 
			
		||||
		$out .= "\n  ".sprintf ("%15s", $dnscache{$que}{query})."  ".(join ', ', @{$dnscache{$que}{A}});
 | 
			
		||||
		$out .= "  (time: ".sprintf ("%.1fs)", ($dnscache{$que}{end} - $dnscache{$que}{start}));
 | 
			
		||||
		$out .= "  (ttl: ".$dnscache{$que}{ttl}."s)" if defined $dnscache{$que}{ttl};
 | 
			
		||||
		$out .= "\n  ".sprintf ("%15s", $dnscache{$que}{query})."  ".(join '. ', @{$dnscache{$que}{TXT}}) if defined $dnscache{$que}{TXT};
 | 
			
		||||
	};
 | 
			
		||||
	print STDOUT "$out\n";
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
# reads DNS answer
 | 
			
		||||
sub rbl_read_dns {
 | 
			
		||||
    my($myresult) = shift;
 | 
			
		||||
    my($now)      = time();
 | 
			
		||||
    my($que,$typ) = undef;
 | 
			
		||||
 | 
			
		||||
    if ( defined $myresult ) {
 | 
			
		||||
        # read question, for dns cache id
 | 
			
		||||
        foreach ($myresult->question) {
 | 
			
		||||
                $typ = ($_->qtype || '') unless $typ;
 | 
			
		||||
		$que = ($_->qname || '') unless $que;
 | 
			
		||||
	};
 | 
			
		||||
        # not listed
 | 
			
		||||
	unless ($myresult->answer) {
 | 
			
		||||
		@{$dnscache{$que}{A}} = '<nxdomain>';
 | 
			
		||||
		$dnscache{$que}{end} = $now;
 | 
			
		||||
		$dnscache{$que}{log} = 0;
 | 
			
		||||
        # parse answers
 | 
			
		||||
	} else {
 | 
			
		||||
	        foreach ($myresult->answer) {
 | 
			
		||||
                        if ($_->type =~ /^(A|CNAME|TXT)$/) {
 | 
			
		||||
                        	if ($_->type eq 'A') {
 | 
			
		||||
                	                push @{$dnscache{$que}{A}}, ($_->address || '');
 | 
			
		||||
				} elsif ($_->type eq 'TXT') {
 | 
			
		||||
                                	my $res = (join(' ', $_->char_str_list()) || '');
 | 
			
		||||
	               	                push @{$dnscache{$que}{TXT}}, $res if $res;
 | 
			
		||||
				} elsif ($_->type eq 'CNAME') {
 | 
			
		||||
                	                $dnscache{$que}{CNAME}{$_->cname} = 1 if $_->cname;
 | 
			
		||||
				};
 | 
			
		||||
                       	        $dnscache{$que}{ttl} = ($_->ttl || 0) unless defined $dnscache{$que}{ttl};
 | 
			
		||||
				$dnscache{$que}{end} = $now;
 | 
			
		||||
				$dnscache{$que}{log} = 1;
 | 
			
		||||
			} else {
 | 
			
		||||
				print STDERR "IGNORING query: $que, TYPE: '".($_->type || '')."'\n";
 | 
			
		||||
			};
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue