Hey,

IPv6 is probably of little to no concern to most people, but I've seen at 
least one domains I can't accept mail from because of IPv6.
nl.linux.org has 2 IPv6 MXs, and that makes require_resolvable_fromhost barf.

So, I made the attached modifications.
I borrowed the has_ipv6 stuff from Net::DNS::Resolver::Base.pm, when IPv6 
support is added to qpsmtpd (yes, when :P) that should move somewhere global.
Ages ago I did briefly look into adding full IPv6 support, but fell over due 
to a general lack of perl knowledge, and failling to find a nice method to 
fall back on IPv4, with that stuff from DNS::Resolver I might start to look 
at it again soon.

I thought about just doing an ANY search, but in mx_valid that fails if a host 
has a CNAME in their MX, and the CEOs personal email account provider do, so 
I had to make it work another way.

One thing I have left out, is is_valid.
Currently it'll spit out a couple of these on IPv6 IPs:
"Use of uninitialized value in bitwise and (&) 
at ./plugins/require_resolvable_fromhost line 104."
I have no idea how is_valid works, so haven't touched it :)

-- 
Mike Williams
--- require_resolvable_fromhost.orig	2006-08-21 11:53:21.000000000 +0100
+++ require_resolvable_fromhost	2006-08-21 11:55:18.000000000 +0100
@@ -3,6 +3,18 @@
 use Socket;
 
 my %invalid = ();
+my $has_ipv6;
+
+if (
+   eval {require Socket6;} &&
+   # INET6 prior to 2.01 will not work; sorry.
+   eval {require IO::Socket::INET6; IO::Socket::INET6->VERSION("2.00");}
+   ) {
+  import Socket6;
+  $has_ipv6=1;
+}else{
+  $has_ipv6=0;
+}
 
 sub hook_mail {
   my ($self, $transaction, $sender) = @_;
@@ -38,6 +50,7 @@
 
 sub check_dns {
   my ($self, $host) = @_;
+  my @host_answers;
 
   # for stuff where we can't even parse a hostname out of the address
   return 0 unless $host;
@@ -53,15 +66,24 @@
   }
   my $query = $res->search($host);
   if ($query) {
-    foreach my $rr ($query->answer) {
-      if ($rr->type eq "A") {
-        return is_valid($rr->address);
-      }
-      elsif ($rr->type eq "MX") {
-        return mx_valid($self, $rr->exchange, $host);
+    foreach my $rrA ($query->answer) {
+      push(@host_answers, $rrA);
+    }
+  }
+  if($has_ipv6){
+    my $query = $res->search($host, 'AAAA');
+    if ($query) {
+      foreach my $rrAAAA ($query->answer) {
+        push(@host_answers, $rrAAAA);
       }
     }
   } 
+  if(@host_answers){
+    foreach my $rr (@host_answers) {
+      return is_valid($rr->address) if $rr->type eq "A" or $rr->type eq "AAAA";
+      return mx_valid($self, $rr->exchange, $host) if $rr->type eq "MX";
+    }
+  }
   else {
     $self->log(LOGWARN, "$$ query for $host failed: ", $res->errorstring)
       unless $res->errorstring eq "NXDOMAIN";
@@ -88,10 +110,24 @@
 sub mx_valid {
   my ($self, $name, $host) = @_;
   my $res   = new Net::DNS::Resolver;
-  my $query = $res->search($name);
+  my @mx_answers;
+  my $query = $res->search($name, 'A');
   if ($query) {
-    foreach my $rr ($query->answer) {
-      next unless $rr->type eq "A";
+    foreach my $rrA ($query->answer) {
+      push(@mx_answers, $rrA);
+    }
+  }
+  if($has_ipv6){
+    my $query = $res->search($name, 'AAAA');
+    if ($query) {
+      foreach my $rrAAAA ($query->answer) {
+        push(@mx_answers, $rrAAAA);
+      }
+    }
+  }
+  if(@mx_answers){
+    foreach my $rr (@mx_answers) {
+      next unless $rr->type eq "A" or $rr->type eq "AAAA";
       return is_valid($rr->address);
     }
   }

Reply via email to