DDNS updating of ranges

Kevin Darcy kcd at daimlerchrysler.com
Thu Dec 2 01:46:41 UTC 2004

James Baldwin wrote:

>	We are in the process of setting up Bind to act as a RBL internally. 
>As we have several hosts who will be updating the zones therein we will 
>be running with dynamic dns. One of the issues we've come across, 
>however, is how to efficiently update records for large CIDR ranges. We 
>can do some trickery if the CIDR range falls on an octet boundary (at 
>least I think we can), but we're having trouble coming up with an 
>elegant fashion to add non round numbers (!= /8, /16, /24, /32).
>	I looked through the nsupdate manpage and did not see anything that 
>suggested range updates are available. Are there any dynamic dns update 
>tools which allow actions similar to the $GENERATE directive and/or for 
>removal of records created in that fashion? Is there anything else that 
>might give a similar experience or am I left having to wrap nsupdate in 
>something else and call it repeatedly?
For an RBL, you should be able to use wildcards at each octet boundary. 
Between octet boundaries, you'll have to do several updates (which may 
themselves be wildcards), up to a maximum number of 128 updates. But 
doing multiple updates shouldn't always entail calling nsupdate 
repeatedly: you can make several updates in a single update transaction, 
as long as they are all for the same zone. E.g. to specify the 
192.168.16/22 range, you could do

zone 168.192.rbl.
update add *.16.168.192.rbl. 1d a
update add *.17.168.192.rbl. 1d a
update add *.18.168.192.rbl. 1d a
update add *.19.168.192.rbl. 1d a

Here's a quick-and-dirty (should do more input validation) piece of Perl 
code that will take a list of address prefixes on stdin, along with a 
domain suffix as a command-line parameter, and generate the appropriate 
nsupdate commands, including the "send", for adding A records 
and/or wildcards under that prefix in the reverse-octet convention, for 
the corresponding address range. It assumes each prefix given on stdin 
falls within a given RBL zone. If an address prefix spans RBL zones, 
then the input should be preprocessed accordingly. If, on the other 
hand, you only have one huge RBL zone, then you could move the "send" 
out of the loop to the very end of the script, since it will always be 
possible to do all of the updates in a single transaction.


use integer;

($domain = $ARGV[0]) =~ s/\.$//;

while (<STDIN>) {
($addr, $prefix) = split(m%/%);
die "prefix out of range" if (($prefix > 32) || ($prefix < 1));

@octet = split(/\./, $addr);

$wildcard = '*.' x ((32 - $prefix) / 8);

$fixed = "";
if ($prefix > 8) {
$fixed = ".".(join('.', reverse(@octet[0..(($prefix-9)/8)])));
$fixed .= ".$domain";

for ($i = 0; $i < (1 << ((32 - $prefix) % 8)); $i++) {
printf("update add %s%s%s. 1d a\n",
$wildcard, $octet[($prefix - 1)/8]++, $fixed);
print "send\n";

- Kevin

More information about the bind-users mailing list