#!/usr/bin/perl BEGIN { my $x = $0; $x =~ s/\/[^\/]+$//; if ($x eq $0 || $x eq '') { $x = `pwd`;chomp $x; }; require "$x/config.pl"; }; use Net::DNS; sub usage { print "usage: transfer_zone ns zone ...\n"; exit 1; } my $ns1ip = $ENV{IP}; my @local_ns = (); warn "IP not set; won't force creation of working nameserver records" if (!defined($ns1ip) && $ARGV[1] ne '.'); # root zones... if ($ns1ip && $ns1ip ne '') { my $x = $ENV{LOCAL_NS}; if ($x && $x ne '') { @local_ns = split /\s*,\s*/, $x; } if ($ns1ip =~ /,/) { # tada my @x = split /\s*\,\s*/, $ns1ip; $ns1ip = \@x; } } my $ns = shift @ARGV; &usage if (!defined($ns)); my @zone = shift @ARGV; &usage if (scalar(@zone) < 1); if ($zone[0] eq '-') { @zone = (); while () { chomp; push(@zone, $_); } } my $ldap = &get_ldap_conn; my $res = new Net::DNS::Resolver; $res->nameservers($ns); read_zone: foreach my $zonename (@zone) { print $zonename . ' ' . ('=' x (79 - length($zonename))) . "\n\n"; my @records = $res->axfr($zonename); while (!@records) { if ($res->errorstring eq "couldn't connect") { sleep(10); @records = $res->axfr($zonename); } else { next read_zone; } } foreach my $rr (@records) { $rr->print; if ($rr->type eq 'SOA') { die "Invalid SOA(1) record for ", $rr->name, " " unless ($rr->string =~ /^(\*?[0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-]+)\s+([0-9a-zA-Z_.+-]+)\s+\((.*)\)/s); die "Corrupt SOA record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type); my $zn = $1; my $soa = $7; die "Invalid SOA fields for ", $zonename, " " unless ($soa =~ /\s*(\d+)\D*(\d+)\D*(\d+)\D*(\d+)\D*(\d+)\s*/s); my $soarecord = "$1 $2 $3 $4 $5"; set_record($ldap, &fix_domain($zonename, $zn), [ dc => &dc_domain($zn), objectClass => 'dnsDomain', objectClass => 'dcObject', objectClass => 'domain', sOARecord => $soarecord, ], { sOARecord => $soarecord }); } elsif ($rr->type eq "A") { die "Invalid A record for ", $rr->name, " " unless ($rr->string =~ /^(\*?[0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9.]+)/); die "Corrupt A record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type && $5 eq $rr->address); next if lc($1) eq lc("localhost.$zonename"); add_record($ldap, &fix_domain($zonename, $1), [ dc => &dc_domain($1), objectClass => 'dnsDomain', objectClass => 'dcObject', objectClass => 'domain', aRecord => $5, ], { aRecord => $5 }); } elsif ($rr->type eq "MX") { die "Invalid MX record for ", $rr->name, " " unless ($rr->string =~ /^(\*?[0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+([0-9a-zA-Z_.+-]+)/); die "Corrupt MX record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type); my $zn = $1; my $pref = $5; my $name = lc $6; $name =~ s/\.$//; $name .= '.'; add_record($ldap, &fix_domain($zonename, $zn), [ dc => &dc_domain($zn), objectClass => 'dnsDomain', objectClass => 'dcObject', objectClass => 'domain', mXRecord => "$pref $name", ], { mXRecord => "$pref $name" }); } elsif ($rr->type eq "NS") { die "Invalid NS record for ", $rr->name, " " unless ($rr->string =~ /^(\*?[0-9a-zA-Z_.+-]*)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-]+)/); die "Corrupt NS record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type); my $zn = $1; $zn = '*' if ($zn eq ''); my $name = lc $5; $name =~ s/\.$//; $name .= '.'; # nameserver records for PTR's? next if ($zn =~ /\.in-addr\.arpa\.?$/ && $ns1ip && $ns1ip ne ''); if ($ns1ip && $ns1ip ne '') { # we want $name to be fudged to be # ns.$zn $name = 'ns.' . $zn; } add_record($ldap, &fix_domain($zonename, $zn), [ dc => &dc_domain($zn), objectClass => 'dnsDomain', objectClass => 'dcObject', objectClass => 'domain', nSRecord => $name, ], { nSRecord => $name }); if ($ns1ip && $ns1ip ne '') { set_record($ldap, &fix_domain($zonename, $name), [ dc => &dc_domain($name), objectClass => 'dnsDomain', objectClass => 'dcObject', objectClass => 'domain', aRecord => $ns1ip, ], { nSRecord => $name }); } } elsif ($rr->type eq "CNAME") { die "Invalid ", $rr->type, " record for ", $rr->name, " " unless ($rr->string =~ /^(\*?[0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-]+)/); die "Corrupt ", $rr->type, " record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type); my $zn = $1; my $name = lc $5; $name =~ s/\.$//; $name .= '.'; add_record($ldap, &fix_domain($zonename, $zn), [ dc => &dc_domain($zn), objectClass => 'dnsDomain', objectClass => 'dcObject', objectClass => 'domain', cNAMERecord => $name, ], { cNAMERecord => $name }); } elsif ($rr->type eq "TXT") { die "Invalid ", $rr->type, " record for ", $rr->name, " " unless ($rr->string =~ /^(\*?[0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+(.*)/); die "Corrupt ", $rr->type, " record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type); # displays as "doo" "doo" "" my $arg = join('|', (split /\" \"/, substr($5, 1, -1))); $arg =~ s/\|$//; my $zn = $1; add_record($ldap, &fix_domain($zonename, $zn), [ dc => &dc_domain($zn), objectClass => 'dnsDomain', objectClass => 'dcObject', objectClass => 'domain', description => $arg, ], { description => $arg }); } elsif ($rr->type eq "PTR") { die "Invalid PTR record for ", $rr->name, " " unless ($rr->string =~ /^([0-9.]+\.in-addr\.arpa)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-]+)/i || $rr->string =~ /^([\w\/.+-]+\.$zonename)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([\w\/.+-]+)/i); die "Corrupt PTR record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type); my $zn = $1; my $name = lc $5; $name =~ s/\.$//; $name .= '.'; if ($ns1ip && $ns1ip ne '') { set_record($ldap, &fix_domain($zonename, $zn), [ dc => &dc_domain($zn), objectClass => 'dnsDomain', objectClass => 'dcObject', objectClass => 'domain', cNAMERecord => $name, nSRecord => \@local_ns, ], { cNAMERecord => $name }); } else { # let the "old" record keep it's NS... set_record($ldap, &fix_domain($zonename, $zn), [ dc => &dc_domain($zn), objectClass => 'dnsDomain', objectClass => 'dcObject', objectClass => 'domain', cNAMERecord => $name, ], { cNAMERecord => $name }); } } } } sub fix_domain { my ($base, $zn)=(@_); return $base if ($zn eq ''); return $zn; }