You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by mm...@apache.org on 2010/04/06 01:54:42 UTC

svn commit: r930986 - /spamassassin/trunk/t/dnsbl_subtests.t

Author: mmartinec
Date: Mon Apr  5 23:54:41 2010
New Revision: 930986

URL: http://svn.apache.org/viewvc?rev=930986&view=rev
Log:
Bug 6362: let t/dnsbl_subtests.t choose a random free port
instead of using a fixed preconfigured port number for the
spawned test DNS server

Modified:
    spamassassin/trunk/t/dnsbl_subtests.t

Modified: spamassassin/trunk/t/dnsbl_subtests.t
URL: http://svn.apache.org/viewvc/spamassassin/trunk/t/dnsbl_subtests.t?rev=930986&r1=930985&r2=930986&view=diff
==============================================================================
--- spamassassin/trunk/t/dnsbl_subtests.t (original)
+++ spamassassin/trunk/t/dnsbl_subtests.t Mon Apr  5 23:54:41 2010
@@ -25,12 +25,23 @@ if (-e 'test_dir') {            # runnin
   $prefix = '..';
 }
 
+use Errno qw(EADDRINUSE EACCES);
+use IO::Socket::INET;
+use Net::DNS::Nameserver;
+use Mail::SpamAssassin;
+
 # Bug 5761 (no 127.0.0.1 in jail, use SPAMD_LOCALHOST if specified)
 my $dns_server_localaddr = $ENV{'SPAMD_LOCALHOST'};
 $dns_server_localaddr = '127.0.0.1'  if !$dns_server_localaddr;
-$dns_server_localaddr = '::1'        if !$dns_server_localaddr;
 
-my $dns_server_localport = '5353';  # some port (mdns), hopefully free
+sub find_free_port($);  # prototype
+my($dns_server_localport, $sock_udp, $sock_tcp) =
+  find_free_port($dns_server_localaddr);
+
+$dns_server_localport  or die "Failed to obtain a free port number";
+
+printf("Using [%s]:%s for a spawned test DNS server\n",
+       $dns_server_localaddr, $dns_server_localport);
 
 # test zones
 my $z  = 'sa1-dbl-test.spamassassin.org';
@@ -170,8 +181,6 @@ EOD
 
 # ---------------------------------------------------------------------------
 
-use Net::DNS::Nameserver;
-
 sub reply_handler {
   my($qname, $qclass, $qtype, $peerhost,$query,$conn) = @_;
   my($rcode, @ans, @auth, @add);
@@ -215,9 +224,26 @@ sub dns_server($$) {
   $ns->main_loop;
 }
 
+sub find_free_port($) {
+  my($addr) = @_;
+  my($port, $sock_udp, $sock_tcp);
+  for (1..20) {  # choose a pair of free tcp & udp ports
+    $port = 11001 + int(rand(65536-11001));
+    my %args = (LocalAddr => $addr, LocalPort => $port);
+    $sock_udp = IO::Socket::INET->new(%args, Proto => 'udp');
+    $sock_udp || $! == EADDRINUSE || $! == EACCES
+      or printf("Error creating UDP socket [%s]:%s: %s\n", $addr, $port, $!);
+    $sock_tcp = IO::Socket::INET->new(%args, Proto => 'tcp');
+    $sock_tcp || $! == EADDRINUSE || $! == EACCES
+      or printf("Error creating TCP socket [%s]:%s: %s\n", $addr, $port, $!);
+    last if $sock_tcp && $sock_udp;
+  }
+  undef $port if !$sock_tcp || !$sock_udp;
+  return ($port, $sock_udp, $sock_tcp);
+}
+
 # ---------------------------------------------------------------------------
 
-use Mail::SpamAssassin;
 my $spamassassin_obj;
 
 sub process_sample_urls(@) {
@@ -267,6 +293,18 @@ sub test_samples($$) {
          join(', ',@$url_list_ref), $spam_report)  if !$status;
 }
 
+
+# there is a time gap between closing sockets and reusing them by a spawned
+# DNS server - if we are very unlucky and the port is acquired by some other
+# process during this short interval, our spawned DNS server will fail to start
+#
+if ($sock_udp) {
+  $sock_udp->close()  or die "Error closing UDP socket: $!";
+}
+if ($sock_tcp) {
+  $sock_tcp->close()  or die "Error closing TCP socket: $!";
+}
+
 # detach a DNS server process
 my $pid = fork();
 defined $pid or die "Cannot fork: $!";