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 2011/09/16 18:44:01 UTC
svn commit: r1171657 - in /spamassassin/trunk: sa-update.raw spamd/spamd.raw
Author: mmartinec
Date: Fri Sep 16 16:44:01 2011
New Revision: 1171657
URL: http://svn.apache.org/viewvc?rev=1171657&view=rev
Log:
Bug 6654: Make sa-update and its infrastructure usable over IPv6
- let sa-update check whether it has inet and inet6 capabilities;
- add command line options -4 and -6 to be able to overrule a
default (which is to use whatever is available or both);
these options are modelled after their nameseke options
in telnet, ssh, curl, ...
- for consistency add an alias option -4 to spamd too
(alias for --ipv4);
- as the LWP module does not understand IPv6, trick it by
hotpatching IO::Socket::INET6 over IO::Socket::INET,
as sugested by the Net::INET6Glue::INET_is_INET6 module;
- btw, slightly generalize a do_txt_query into do_dns_query,
we may decide to do additional tests on host addresses
in URLs to avoid some ugly warnings from LWP;
- btw, do not treat user data as perl booleans;
- improved debugging messages a bit
Modified:
spamassassin/trunk/sa-update.raw
spamassassin/trunk/spamd/spamd.raw
Modified: spamassassin/trunk/sa-update.raw
URL: http://svn.apache.org/viewvc/spamassassin/trunk/sa-update.raw?rev=1171657&r1=1171656&r2=1171657&view=diff
==============================================================================
--- spamassassin/trunk/sa-update.raw (original)
+++ spamassassin/trunk/sa-update.raw Fri Sep 16 16:44:01 2011
@@ -128,6 +128,20 @@ my @channels = ( 'updates.spamassassin.o
my $IGNORE_MIRBY_OLDER_THAN = (24 * 60 * 60 * 7); # 1 week
+my $have_inet4 = eval {
+ require IO::Socket::INET;
+ my $sock = IO::Socket::INET->new(LocalAddr => '0.0.0.0', Proto => 'udp');
+ $sock->close or die "error closing inet socket: $!" if $sock;
+ $sock ? 1 : undef;
+};
+
+my $have_inet6 = eval {
+ require IO::Socket::INET6;
+ my $sock = IO::Socket::INET6->new(LocalAddr => '::', Proto => 'udp');
+ $sock->close or die "error closing inet6 socket: $!" if $sock;
+ $sock ? 1 : undef;
+};
+
##############################################################################
use constant MIRBY_DOWNLOADED => -1;
@@ -162,6 +176,9 @@ GetOptions(
'updatedir=s' => \$opt{'updatedir'},
'gpg!' => \$GPG_ENABLED,
+ '4' => sub { $opt{'force_pf'} = 'inet' },
+ '6' => sub { $opt{'force_pf'} = 'inet6' },
+
# backward compatibility
'usegpg' => \$GPG_ENABLED,
@@ -175,6 +192,15 @@ if ( defined $opt{'version'} ) {
exit(0);
}
+if ( $opt{'force_pf'} && $opt{'force_pf'} eq 'inet' && !$have_inet4 ) {
+ warn "Option -4 specified but support for the ".
+ "INET protocol family is not available.\n";
+}
+if ( $opt{'force_pf'} && $opt{'force_pf'} eq 'inet6' && !$have_inet6 ) {
+ warn "Option -6 specified but support for the ".
+ "INET6 protocol family is not available.\n";
+}
+
# Figure out what version of SpamAssassin we're using, and also figure out the
# reverse of it for the DNS query. Handle x.yyyzzz as well as x.yz.
my $SAVersion = $Mail::SpamAssassin::VERSION;
@@ -274,7 +300,7 @@ if (defined $opt{'gpgkeyfile'}) {
$key =~ s/#.*$//; # remove comments
$key =~ s/^\s+//; # remove leading whitespace
$key =~ s/\s+$//; # remove tailing whitespace
- next unless ($key); # skip empty lines
+ next if $key eq ''; # skip empty lines
unless (is_valid_gpg_key_id($key)) {
dbg("gpg: invalid key id $key");
@@ -349,7 +375,7 @@ if (defined $opt{'channelfile'}) {
$chan =~ s/#.*$//; # remove comments
$chan =~ s/^\s+//; # remove leading whitespace
$chan =~ s/\s+$//; # remove tailing whitespace
- next unless ($chan); # skip empty lines
+ next if $chan eq ''; # skip empty lines
$chan = lc $chan;
dbg("channel: adding $chan");
@@ -380,11 +406,20 @@ if ($opt{'install'}) {
} else {
$res = Net::DNS::Resolver->new();
-
+ $res->force_v4(1) if $have_inet4 &&
+ $opt{'force_pf'} && $opt{'force_pf'} eq 'inet';
$ua = LWP::UserAgent->new();
$ua->agent("sa-update/$VERSION/$SAVersion");
$ua->timeout(60); # a good long timeout; 10 is too short for Coral!
$ua->env_proxy;
+
+ if ($opt{'force_pf'}) {
+ if ($have_inet4 && $opt{'force_pf'} eq 'inet') {
+ $ua->local_address('0.0.0.0');
+ } elsif ($have_inet6 && $opt{'force_pf'} eq 'inet6') {
+ $ua->local_address('::');
+ }
+ }
}
# Generate a temporary file to put channel content in for later use ...
@@ -453,7 +488,7 @@ foreach my $channel (@channels) {
# Setup the channel version DNS query
my $DNSQ = "$RevSAVersion.$channel";
- my $dnsV = join(' ', do_txt_query($DNSQ));
+ my $dnsV = join(' ', do_dns_query($DNSQ));
local($1);
if (defined $dnsV && $dnsV =~ /^(\d+)/) {
$newV = $1 if (!defined $newV || $1 > $newV);
@@ -463,7 +498,7 @@ foreach my $channel (@channels) {
# Not getting a response isn't a failure, there may just not be any updates
# for this SA version yet.
if (!defined $newV) {
- my @mirs = do_txt_query("mirrors.$channel");
+ my @mirs = do_dns_query("mirrors.$channel");
if (defined shift @mirs) {
dbg("channel: no updates available, skipping channel");
} else {
@@ -534,8 +569,29 @@ foreach my $channel (@channels) {
my $SHA1;
my $GPG;
if (!$instfile) {
+
+ dbg("channel: protocol family available: %s%s",
+ join(',', $have_inet4 ? 'inet' : (),
+ $have_inet6 ? 'inet6' : ()),
+ $opt{'force_pf'} ? '; force '.$opt{'force_pf'} : '' );
+
+ if ($have_inet6 && (!$opt{'force_pf'} || $opt{'force_pf'} eq 'inet6')) {
+ # LWP module has no support yet for IPv6.
+ # Use hotpatching, copying IO::Socket::INET6 to IO::Socket::INET.
+ # 'Borrowed' from Net::INET6Glue::INET_is_INET6 :
+ $INC{'IO/Socket/INET.pm'} = $INC{'IO/Socket/INET6.pm'};
+ no strict 'refs';
+ no warnings 'redefine';
+ for ( keys %{IO::Socket::INET6::} ) {
+ ref(my $v = $IO::Socket::INET6::{$_}) and next;
+ *{ 'IO::Socket::INET::'.$_ } =
+ \&{ 'IO::Socket::INET6::'.$_ } if *{$v}{CODE};
+ }
+ }
+
# Read in the MIRRORED.BY file if it exists
if (open(MIRBY, $mirby_path)) {
+ dbg("channel: reading MIRRORED.BY file $mirby_path");
$mirby_time = (stat $mirby_path)[9];
if ($opt{'refreshmirrors'}) {
@@ -555,7 +611,7 @@ foreach my $channel (@channels) {
if (!defined $mirby) {
# We don't currently have the list of mirrors, so go grab it.
dbg("channel: no MIRRORED.BY file available");
- my @mirrors = do_txt_query("mirrors.$channel");
+ my @mirrors = do_dns_query("mirrors.$channel");
unless (@mirrors) {
warn "error: no mirror data available for channel $channel\n";
channel_failed("channel: MIRRORED.BY file location was not in DNS");
@@ -580,7 +636,7 @@ foreach my $channel (@channels) {
}
# Read in the list of mirrors
- dbg("channel: reading MIRRORED.BY file");
+ dbg("channel: parsing MIRRORED.BY file");
my %mirrors;
my @mirrors = split(/^/, $mirby);
while(my $mirror = shift @mirrors) {
@@ -589,7 +645,7 @@ foreach my $channel (@channels) {
$mirror =~ s/#.*$//; # remove comments
$mirror =~ s/^\s+//; # remove leading whitespace
$mirror =~ s/\s+$//; # remove tailing whitespace
- next unless ($mirror); # skip empty lines
+ next if $mirror eq ''; # skip empty lines
# We only support HTTP right now
if ($mirror !~ m@^http://@i) {
@@ -597,10 +653,9 @@ foreach my $channel (@channels) {
next;
}
- my @data;
-
dbg("channel: found mirror $mirror");
+ my @data;
($mirror,@data) = split(/\s+/, $mirror);
$mirror =~ s@/+$@@; # http://example.com/updates/ -> .../updates
$mirrors{$mirror}->{weight} = 1;
@@ -610,7 +665,7 @@ foreach my $channel (@channels) {
}
}
- unless (keys %mirrors) {
+ unless (%mirrors) {
warn "error: no mirrors available for channel $channel\n";
channel_failed("channel: no mirrors available");
next;
@@ -1160,28 +1215,28 @@ failed:
##############################################################################
-# Do a generic TXT query
-sub do_txt_query {
- my($query) = shift;
+# Do a generic DNS query
+sub do_dns_query {
+ my($query, $rr_type) = @_;
+ $rr_type = 'TXT' if !defined $rr_type;
- my $RR = $res->query($query, 'TXT');
+ my $RR = $res->query($query, $rr_type);
my @result;
if ($RR) {
foreach my $rr ($RR->answer) {
next if !$rr; # no answer records, only rcode
- next if $rr->type ne 'TXT'; # only interested in TXT fields
+ next if $rr->type ne $rr_type;
my $text = $rr->rdatastr;
local($1);
- $text =~ /^"(.*)"$/;
- push @result, $1;
+ push(@result,$1) if $text =~ /^"(.*)"$/;
}
- printf("DNS TXT query: %s -> %s\n", $query, join(", ",@result))
+ printf("DNS %s query: %s -> %s\n", $rr_type, $query, join(", ",@result))
if $opt{'verbose'} && $opt{'verbose'} > 1;
}
else {
dbg("dns: query failed: $query => " . $res->errorstring);
- printf("DNS TXT query %s failed: %s\n", $query, $res->errorstring)
+ printf("DNS %s query %s failed: %s\n", $rr_type, $query, $res->errorstring)
if $opt{'verbose'} && $opt{'verbose'} > 1;
}
@@ -1229,6 +1284,10 @@ sub http_get {
if ($ims && $response->status_line =~ /^3/) {
return;
}
+ if ($response->status_line =~ /^[45]/) {
+ # client error or server error, makes no sense retrying
+ return;
+ }
# include the text in the debug output; it's useful in some cases,
# e.g. proxies that require authentication, diagnosing fascist
@@ -1494,6 +1553,8 @@ Options:
For more verbosity specify multiple times
-V, --version Print version
-h, --help Print usage message
+ -4 Force using the inet protocol (IPv4), not inet6
+ -6 Force using the inet6 protocol (IPv6), not inet
=head1 DESCRIPTION
Modified: spamassassin/trunk/spamd/spamd.raw
URL: http://svn.apache.org/viewvc/spamassassin/trunk/spamd/spamd.raw?rev=1171657&r1=1171656&r2=1171657&view=diff
==============================================================================
--- spamassassin/trunk/spamd/spamd.raw (original)
+++ spamassassin/trunk/spamd/spamd.raw Fri Sep 16 16:44:01 2011
@@ -227,7 +227,7 @@ GetOptions(
'helper-home-dir|H:s' => \$opt{'home_dir_for_helpers'},
'help|h' => \$opt{'help'},
'ident-timeout=f' => \$opt{'ident-timeout'},
- 'ipv4only|ipv4-only|ipv4' => \$opt{'force_ipv4'},
+ '4|ipv4only|ipv4-only|ipv4'=> \$opt{'force_ipv4'},
'ldap-config!' => \$opt{'ldap-config'},
'listen-ip|ip-address|i:s' => \$opt{'listen-ip'},
'local!' => \$opt{'local'},
@@ -2849,7 +2849,7 @@ Options:
-d, --daemonize Daemonize
-h, --help Print usage message
-i [ipaddr], --listen-ip=ipaddr Listen on the IP ipaddr
- --ipv4only, --ipv4-only, --ipv4 Disable attempted use of ipv6 for DNS
+ -4, --ipv4only, --ipv4-only, --ipv4 Disable attempted use of ipv6 for DNS
-p port, --port=port Listen on specified port
-m num, --max-children=num Allow maximum num children
--min-children=num Allow minimum num children
@@ -3235,7 +3235,7 @@ please see the documentation at:
C<http://wiki.apache.org/spamassassin/DebugChannels>
-=item B< --ipv4only>, B<--ipv4-only>, B<--ipv4>
+=item B<-4>, B<--ipv4only>, B<--ipv4-only>, B<--ipv4>
Do not use IPv6 for DNS tests. Use if the existing tests
for IPv6 availability produce incorrect results or crashes.