You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by jm...@apache.org on 2005/08/19 01:44:58 UTC
svn commit: r233398 - in /spamassassin/trunk: INSTALL
lib/Mail/SpamAssassin/DnsResolver.pm
lib/Mail/SpamAssassin/Util/DependencyInfo.pm
Author: jm
Date: Thu Aug 18 16:44:56 2005
New Revision: 233398
URL: http://svn.apache.org/viewcvs?rev=233398&view=rev
Log:
bug 4412: DNS resolver fails with an IPv6 resolver address in /etc/resolv.conf; add IPv6 support code
Modified:
spamassassin/trunk/INSTALL
spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Util/DependencyInfo.pm
Modified: spamassassin/trunk/INSTALL
URL: http://svn.apache.org/viewcvs/spamassassin/trunk/INSTALL?rev=233398&r1=233397&r2=233398&view=diff
==============================================================================
--- spamassassin/trunk/INSTALL (original)
+++ spamassassin/trunk/INSTALL Thu Aug 18 16:44:56 2005
@@ -278,6 +278,13 @@
to install this module.
+ - IO::Socket::INET6 (from CPAN)
+
+ This is required if the first nameserver listed in your IP
+ configuration or /etc/resolv.conf file is available only via an IPv6
+ address.
+
+
- IO::Socket::SSL (from CPAN)
If you wish to use SSL encryption to communicate between spamc and
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm
URL: http://svn.apache.org/viewcvs/spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm?rev=233398&r1=233397&r2=233398&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm Thu Aug 18 16:44:56 2005
@@ -42,6 +42,9 @@
use Mail::SpamAssassin::Logger;
use IO::Socket::INET;
+use Errno qw(EINVAL EADDRINUSE);
+
+use constant HAS_SOCKET_INET6 => eval { require IO::Socket::INET6 };
our @ISA = qw();
@@ -144,21 +147,58 @@
$self->{sock}->close() if $self->{sock};
my $sock;
+ my $errno;
+
+ # IO::Socket::INET6 may choose wrong LocalAddr if family is unspecified,
+ # causing EINVAL failure when automatically assigned local IP address
+ # and remote address do not belong to the same address family:
+ use Mail::SpamAssassin::Constants qw(:ip);
+ my $ip64 = IP_ADDRESS;
+ my $ip4 = IPV4_ADDRESS;
+ my $ns = $self->{res}->{nameservers}[0];
+
+ # note: if the use of "AF_INET6" as a bare word here causes trouble
+ # on your platform, just comment the line and replace with
+ # "my $family = AF_INET;" instead
+ my $family = (HAS_SOCKET_INET6 && $ns=~/^${ip64}$/o && $ns!~/^${ip4}$/o)
+ ? AF_INET6 : AF_INET;
+
+ dbg("dns: name server: $ns, family: $family");
+
# find next available unprivileged port (1024 - 65535)
# starting at a random value to spread out use of ports
my $port_offset = int(rand(64511)); # 65535 - 1024
- for (my $i = 0; (!$sock && ($i<64511)); $i++) {
+ for (my $i = 0; $i<64511; $i++) {
my $lport = 1024 + (($port_offset + $i) % 64511);
- $sock = IO::Socket::INET->new (
- Proto => 'udp',
- LocalPort => $lport,
- Type => SOCK_DGRAM,
- );
+
+ my %args = (
+ PeerAddr => $ns,
+ PeerPort => $self->{res}->{port},
+ Proto => 'udp',
+ LocalPort => $lport,
+ Type => SOCK_DGRAM,
+ Domain => $family,
+ );
+
+ if (HAS_SOCKET_INET6) {
+ $sock = IO::Socket::INET6->new(%args);
+ } else {
+ $sock = IO::Socket::INET->new(%args);
+ }
+ $errno = $!;
+ if (defined $sock) { # ok, got it
+ last;
+ } elsif ($! == EADDRINUSE) { # in use, let's try another source port
+ dbg("dns: UDP port $lport already in use, trying another port");
+ } else {
+ # did we fail due to the attempted use of an IPv6 nameserver?
+ $self->_ipv6_ns_warning() if !HAS_SOCKET_INET6 && $errno==EINVAL;
+ die "Error creating a DNS resolver socket: $errno";
+ }
}
+ defined $sock or die "Can't create a DNS resolver socket: $errno";
$self->{sock} = $sock;
- $self->{dest} = sockaddr_in($self->{res}->{port},
- inet_aton($self->{res}->{nameservers}[0]));
$self->{sock_as_vec} = $self->fhs_to_vec($self->{sock});
}
@@ -269,9 +309,8 @@
my $pkt = $self->new_dns_packet($host, $type, $class);
my $data = $pkt->data;
- my $dest = $self->{dest};
$self->connect_sock() if !$self->{sock};
- if (!$self->{sock}->send ($pkt->data, 0, $self->{dest})) {
+ if (!$self->{sock}->send ($pkt->data, 0)) {
warn "dns: sendto() failed: $@";
return;
}
@@ -425,6 +464,26 @@
# and a new socket, so we don't have 5 spamds sharing the same
# socket
$self->connect_sock();
+}
+
+sub _ipv6_ns_warning {
+ my ($self) = @_;
+
+ # warn about the attempted use of an IPv6 nameserver without
+ # IO::Socket::INET6 installed (bug 4412)
+ my $firstns = $self->{res}->{nameservers}[0];
+
+ use Mail::SpamAssassin::Constants qw(:ip);
+ my $ip64 = IP_ADDRESS;
+ my $ip4 = IPV4_ADDRESS;
+
+ # was the nameserver in IPv6 format?
+ if ($firstns =~ /^${ip64}$/o && $firstns !~ /^${ip4}$/o) {
+ my $addr = inet_aton($firstns);
+ if (!defined $addr) {
+ die "IO::Socket::INET6 module is required to use IPv6 nameservers such as '$firstns': $@\n";
+ }
+ }
}
1;
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Util/DependencyInfo.pm
URL: http://svn.apache.org/viewcvs/spamassassin/trunk/lib/Mail/SpamAssassin/Util/DependencyInfo.pm?rev=233398&r1=233397&r2=233398&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Util/DependencyInfo.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Util/DependencyInfo.pm Thu Aug 18 16:44:56 2005
@@ -109,6 +109,13 @@
to install this module.',
},
{
+ module => 'IO::Socket::INET6',
+ version => '0.00',
+ desc => 'This is required if the first nameserver listed in your IP
+ configuration or /etc/resolv.conf file is available only via
+ an IPv6 address.',
+},
+{
module => 'IO::Socket::SSL',
version => '0.00',
desc => 'If you wish to use SSL encryption to communicate between spamc and