#!/usr/bin/perl use Carp; my $msg = shift; my (@ips); # CIDR code lifted from Net::CIDR sub _cidr2range8 { my @c=@_; my @r; while ($#c >= 0) { my $a=shift @c; my $b=shift @c; croak unless $a >= 0 && $a <= 255 && $a =~ /^[0-9]+$/; croak unless $b >= 0 && $b <= 8 && $b =~ /^[0-9]+$/; my $n= 1 << (8-$b); $a &= ($n-1) ^ 255; push @r, $a; push @r, $a + ($n-1); } return @r; } sub cidr2octets { my (@cidr) = @_; my (@r); while ($#cidr >= 0) { my $cidr = shift @cidr; $cidr =~ s/\s//g; croak unless ($cidr =~ m@(.+)/(.+)@); my ($ip, $pfix) = ($1, $2); my (@ips) = split (/\.+/, $ip); grep { croak unless $_ >= 0 && $_ <= 255 && $_ =~ /^\d+$/; } @ips; croak unless $pfix >= 0 && $pfix <= ($#ips+1) * 8 && $pfix =~ /^\d+$/; my $i; for ($i=0; $i <= $#ips; $i++) { last if $pfix - $i * 8 < 8; } my @msb=splice @ips, 0, $i; my $bitsleft= $pfix - $i * 8; if ($#ips < 0 || $bitsleft == 0) { push @r, join(".", @msb); next; } my @rr=_cidr2range8(($ips[0], $bitsleft)); while ($#rr >= 0) { my $a=shift @rr; my $b=shift @rr; grep { push @r, join(".", (@msb, $_)); } ($a .. $b); } } return @r; } $txt = ""; while (<>) { if (/^:(127.0.0.\d+):(.*)/) { # rbldnsd $a = $1; $txt = $2; } if (/:\d:\d{10} [^0-9\s]+ - (.*)/) { # AHBL $txt = $1; } next if (/^([#:\$]|$)/); $reject = 1; if (/^!/) { s/^!//; $reject = 0; } s/^= //; my $cidr = (split)[0]; if ($cidr =~ m@/@) { @ips = cidr2octets($cidr); } else { @ips = ($cidr); } foreach my $rule (@ips) { print $rule; print "." if ($rule !~ /^\d+\.\d+\.\d+\.\d+/); print ":allow"; if ($reject) { if (defined($msg)) { printf ",$msg" if ($msg); } else { $reason = $txt; # rbldnsd if (/see (.*)/) { # SPEWS $reason = $1; } if (/BLACKLISTED at (LEVEL \d)/) { # UCEPROTECT $reason = $1; } if (m@(http://www.spamhaus.*)@) { # SBL $reason = $1; } $reason = "Denied" if ($reason eq ""); $reason =~ s/"/'/g; printf ',RBLSMTPD="%s"', $reason; } } print "\n"; } }