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/03/30 16:20:03 UTC

svn commit: r929150 - in /spamassassin/trunk/lib/Mail/SpamAssassin: Conf.pm DnsResolver.pm

Author: mmartinec
Date: Tue Mar 30 14:20:03 2010
New Revision: 929150

URL: http://svn.apache.org/viewvc?rev=929150&view=rev
Log:
Bug 6221: DnsResolver.pm attempts to bind ports at random:
make auxilliary data structures initializations more
self-contained to avoid undef warnings in t/dnsbl_subtests.t;
save about 10 kB when port allocation task is delegated to OS

Modified:
    spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm?rev=929150&r1=929149&r2=929150&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm Tue Mar 30 14:20:03 2010
@@ -1381,36 +1381,6 @@ directive, falling back to Net::DNS -sup
     }
   });
 
-=item dns_local_ports_none
-
-Is a comfortable and faster-to-execute shorthand for:
-
-  dns_local_ports_avoid 1-65535
-
-leaving the set of available DNS query local port numbers empty. In all
-respects (apart from speed) it is equivalent to the shown directive, and can
-be freely mixed with I<dns_local_ports_permit> and I<dns_local_ports_avoid>.
-
-If the resulting set of port numbers is empty, then SpamAssassin does not
-apply its ports randomization logic, but instead leaves the operating system
-to choose a suitable free local port number.
-
-See also directives I<dns_local_ports_permit> and I<dns_local_ports_avoid>.
-
-=cut
-
-  push (@cmds, {
-    setting => 'dns_local_ports_none',
-    type => $CONF_TYPE_NOARGS,
-    code => sub {
-      my ($self, $key, $value, $line) = @_;
-      unless (!defined $value || $value eq '') {
-        return $INVALID_VALUE;
-      }
-      wipe_ports_range(\$self->{dns_available_ports_bitset}, 0);
-    }
-  });
-
 =item dns_local_ports_permit ranges...
 
 Add the specified ports or ports ranges to the set of allowed port numbers
@@ -1460,6 +1430,7 @@ See also directives I<dns_local_ports_pe
         }
       }
       foreach my $p (@port_ranges) {
+        undef $self->{dns_available_portscount};  # invalidate derived data
         set_ports_range(\$self->{dns_available_ports_bitset},
                         $p->[0], $p->[1], 1);
       }
@@ -1494,12 +1465,44 @@ Please see directive I<dns_local_ports_p
         }
       }
       foreach my $p (@port_ranges) {
+        undef $self->{dns_available_portscount};  # invalidate derived data
         set_ports_range(\$self->{dns_available_ports_bitset},
                         $p->[0], $p->[1], 0);
       }
     }
   });
 
+=item dns_local_ports_none
+
+Is a fast shorthand for:
+
+  dns_local_ports_avoid 1-65535
+
+leaving the set of available DNS query local port numbers empty. In all
+respects (apart from speed) it is equivalent to the shown directive, and can
+be freely mixed with I<dns_local_ports_permit> and I<dns_local_ports_avoid>.
+
+If the resulting set of port numbers is empty, then SpamAssassin does not
+apply its ports randomization logic, but instead leaves the operating system
+to choose a suitable free local port number.
+
+See also directives I<dns_local_ports_permit> and I<dns_local_ports_avoid>.
+
+=cut
+
+  push (@cmds, {
+    setting => 'dns_local_ports_none',
+    type => $CONF_TYPE_NOARGS,
+    code => sub {
+      my ($self, $key, $value, $line) = @_;
+      unless (!defined $value || $value eq '') {
+        return $INVALID_VALUE;
+      }
+      undef $self->{dns_available_portscount};  # invalidate derived data
+      wipe_ports_range(\$self->{dns_available_ports_bitset}, 0);
+    }
+  });
+
 =item dns_test_interval n   (default: 600 seconds)
 
 If dns_available is set to 'test' (which is the default), the dns_test_interval
@@ -3730,9 +3733,6 @@ sub new {
 
   $self->{encapsulated_content_description} = 'original message before SpamAssassin';
 
-  # ensure the ports bitset is initialized
-  set_ports_range(\$self->{conf}->{dns_available_ports_bitset}, 0, 0, 0);
-
   $self;
 }
 
@@ -3941,6 +3941,8 @@ sub set_ports_range {
   if (!defined $$bitset_ref) {  # provide a sensible default
     wipe_ports_range($bitset_ref, 1);  # turn on all bits 0..65535
     vec($$bitset_ref,$_,1) = 0  for 0..1023;  # avoid 0 and privileged ports
+  } elsif ($$bitset_ref eq '') {  # repopulate the bitset (late configuration)
+    wipe_ports_range($bitset_ref, 0);  # turn off all bits 0..65535
   }
   $value = !$value ? 0 : 1;
   for (my $j = $port_range_lo; $j <= $port_range_hi; $j++) {

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm?rev=929150&r1=929149&r2=929150&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm Tue Mar 30 14:20:03 2010
@@ -203,7 +203,7 @@ sub disable_available_port {
   my($self, $lport) = @_;
   if ($lport >= 0 && $lport <= 65535) {
     my $conf = $self->{conf};
-    if (!$conf->{dns_available_portscount_buckets}) {
+    if (!defined $conf->{dns_available_portscount}) {
       $self->pick_random_available_port();  # initialize
     }
     if (vec($conf->{dns_available_ports_bitset}, $lport, 1)) {
@@ -220,11 +220,15 @@ sub pick_random_available_port {
   my $port_number;  # resulting port number, or undef if none available
 
   my $conf = $self->{conf};
-  my $ports_bitset = $conf->{dns_available_ports_bitset};
   my $available_portscount = $conf->{dns_available_portscount};
 
-  # initialize when here for the first time
+  # initialize when called for the first time or after a config change
   if (!defined $available_portscount) {
+    my $ports_bitset = $conf->{dns_available_ports_bitset};
+    if (!defined $ports_bitset) {  # ensure it is initialized
+      Mail::SpamAssassin::Conf::set_ports_range(\$ports_bitset, 0, 0, 0);
+      $conf->{dns_available_ports_bitset} = $ports_bitset;
+    }
     # prepare auxilliary data structure to speed up further free-port lookups;
     # 256 buckets, each accounting for 256 ports: 8+8 = 16 bit port numbers;
     # each bucket holds a count of available ports in its range
@@ -245,12 +249,18 @@ sub pick_random_available_port {
       $bucket_counts[$bucket] = $cnt;
     }
     $conf->{dns_available_portscount} = $available_portscount;
-    $conf->{dns_available_portscount_buckets} = \@bucket_counts;
+    if ($available_portscount) {
+      $conf->{dns_available_portscount_buckets} = \@bucket_counts;
+    } else {  # save some storage
+      $conf->{dns_available_portscount_buckets} = undef;
+      $conf->{dns_available_ports_bitset} = '';
+    }
   }
 
   # find the n-th port number from the ordered set of available port numbers
   dbg("dns: %d configured local ports for DNS queries", $available_portscount);
   if ($available_portscount > 0) {
+    my $ports_bitset = $conf->{dns_available_ports_bitset};
     my $n = int(rand($available_portscount));
     my $bucket_counts_ref = $conf->{dns_available_portscount_buckets};
     my $ind = 0;