#!/usr/bin/perl -w # # Convert -- A Tool for Conversion of Zone Files to NSC Format # # (c) 1999--2003 Martin Mares # use Getopt::Std; use Net::DNS::Resolver; getopts('v', \%opts) && @ARGV == 2 || do { print "Usage: convert [-v] \n"; exit 1; }; $domain = norm_name($ARGV[0]); $verbose = $opts{"v"}; $res = new Net::DNS::Resolver; $res->nameservers($ARGV[1]); $res->defnames(0); $res->dnsrch(0); $res->debug(0); $verbose && print "; Fetching zone data for $domain\n"; @zone = $res->axfr($domain) or die("Zone transfer failed"); foreach $r (@zone) { if ($verbose) { $name = $r->string; print "; $name\n"; } $type = $r->type; $n = fix($r->name); if ($type eq "A") { $have{$n} = 1; $ips{$n} = (defined $ips{$n} ? $ips{$n} : "") . ", " . $r->address; } elsif ($type eq "SOA") { print "SOA($domain)\n"; } elsif ($type eq "MX") { $have{$n} = 1; $mx{$n} = ((defined $mx{$n}) ? $mx{$n} . ", " : "") . $r->preference . " " . fix($r->exchange); } elsif ($type eq "CNAME") { $cn = fix($r->cname); $have{$cn} = 1; $cn{$cn} = ((defined $cn{$cn}) ? $cn{$cn} . ", " : "") . $n; } elsif ($type eq "NS") { if ($n ne "@") { $sub{$n} = 1; $subd{$n} .= "NS(" . fix($r->nsdname) . ")\n"; } } else { print "; FIXME: ", $r->string, "\n"; } } go("@", 0); delete $have{"@"}; foreach $n (sort keys %have) { go($n, 1); } foreach $n (sort keys %sub) { print "\nD($n)\n"; print $subd{$n}; } exit 0; sub go { my $n = shift @_; my $flag = shift @_; if (defined $ips{$n}) { print "H($n$ips{$n})\n"; } elsif ($flag) { print "H($n)\n"; } if (defined $mx{$n}) { print "MX($mx{$n})\n"; } if (defined $cn{$n}) { print "ALIAS($cn{$n})\n"; } } sub norm_name { my $n = shift @_; $n =~ s/\.$//; $n =~ tr[A-Z][a-z]; return $n; } sub fix { my $n = shift @_; if ($n eq $domain) { return "@"; } elsif ($n =~ /^(.*)\.$domain$/) { return $1; } else { return "$n."; } }