--- mimedefang.pl.original 2010-01-31 23:10:14.000000000 +0100 +++ mimedefang.pl 2010-02-01 01:58:43.000000000 +0100 @@ -1487,6 +1487,104 @@ sub action_notify_administrator ($) { } #*********************************************************************** +# %PROCEDURE: ip_expand_address +# %ARGUMENTS: +# ip -- IPv6 / IPv4 address. +# ip_version -- what kind of ip is it ? 4 or 6 +# pad -- pad fully optional 1 or 0 (only for ip 6) defaul 0 +# %RETURNS: +# the fully expanded version of ipv6 +# %EXAMPLE: +# 2001:888:1f59::1:7d,6 => 2001:888:1f59:0:0:0:1:7d +# 2001:888:1f59::1:7d,6,1 => 2001:0888:1f59:0000:0000:0000:0001:007d +# ::ffff:192.168.89.9,6 => 0:0:0:0:0:ffff:c0a8:5909 +#*********************************************************************** +# taken from Net::IP, and converted to use no external, and handle no padding +sub ip_expand_address +{ + my $ip = shift; + my $ip_version = shift; + my $pad = shift || 0; + + unless( $ip_version ) { + return $ip; + } + + # v4 : add .0 for missing quads + if ($ip_version == 4) { + my @quads = split /\./, $ip; + my @clean_quads = (0, 0, 0, 0); + foreach my $q (reverse @quads) { + unshift(@clean_quads, $q + 1 - 1); + } + return (join '.', @clean_quads[ 0 .. 3 ]); + } + + # reuse our pad var. + if ( $pad ) { $pad = 4; } + else { $pad = 1; } + + # tag :: + $ip =~ s/::/:!:/; + my @ip = split(/:/,$ip); + my $num = scalar(@ip) - 1; + foreach( 0 .. (scalar(@ip) -1 )) { + if( $ip[$_] =~ /\./ ) { + # ipv4 mapped as ipv6 + my @extraOcts = unpack('H4H4', pack('C4C4C4C4', split(/\./, ip_expand_address($ip[$_], 4)))); + # remove leading 0's if not padding to 4 + if ( $pad eq 1 ) { + $extraOcts[0] =~ s/^0*(.+)$/$1/; + $extraOcts[1] =~ s/^0*(.+)$/$1/; + } + $ip[$_] = join(':', @extraOcts); + # converting creates one more octet increase to compensate + $num++; + next(); + } + $ip[$_] = ('0' x ($pad - length($ip[$_]))) . $ip[$_]; + } + $ip = join(':', @ip); + # handle the :: (now converted to 000! or stayed !) + my $search = '0' x ($pad - 1) . '!:'; + my $missing = ( ('0' x $pad . ':') x (8 - $num)); + $ip =~ s/$search/$missing/; + return $ip; +} + +#*********************************************************************** +# %PROCEDURE: reverse_addr +# %ARGUMENTS: +# addr -- IPv4 / IPv6 Address +# %RETURNS: +# the fully expanded reverse of addr suitable for rbl lookups +# %EXAMPLE: +# 2001:888:1f59::1:7d => +# 6.2.4.1.0.2.e.f.f.f.1.2.3.1.2.0.b.e.d.0.2.0.2.0.8.b.1.4.1.0.0.2 +# 127.0.0.1 => 1.0.0.127 +#*********************************************************************** +sub reverse_addr +{ + my ($addr) = @_; + my $type = 4; + if ( $Features{"Net::DNS"} && Net::DNS::Resolver::Base::_ip_is_ipv6($addr) ) { + $type = 6; + } + elsif ( !$Features{"Net::DNS"} && $addr =~ /:/) { + # no Net::DNS available guessed instead + $type = 6; + } + if ( $type eq 6 ) { + $addr = ip_expand_address($addr, 6, 1); + $addr =~ s/://g; + return join('.', split(//, reverse($addr))); + } + # ipv4 + my($a, $b, $c, $d) = split(/\./, $addr); + return "$d.$c.$b.$a"; +} + +#*********************************************************************** # %PROCEDURE: relay_is_blacklisted # %ARGUMENTS: # addr -- IP address of relay host. @@ -1497,8 +1595,7 @@ sub action_notify_administrator ($) { sub relay_is_blacklisted ($$) { my($addr, $domain) = @_; # Reverse IP address - my($a, $b, $c, $d) = split(/\./, $addr); - $addr = "$d.$c.$b.$a.$domain"; + $addr = reverse_addr( $addr ) . ".$domain"; my $hn; $hn = gethostbyname($addr); return 0 unless defined($hn); @@ -1543,8 +1640,7 @@ sub relay_is_blacklisted_multi ($$$$;$) my %sock_to_domain; # Reverse the address - my($a, $b, $c, $d) = split(/\./, $addr); - $addr = "$d.$c.$b.$a"; + $addr = reverse_addr($addr); # If user did not pass in a Net::DNS::Resolver object, generate one. unless (defined($res and (UNIVERSAL::isa($res, "Net::DNS::Resolver")))) {