--- /dev/null
+#!/usr/bin/perl -w
+#
+# Convert -- A Tool for Conversion of Zone Files to NSC Format
+#
+# (c) 1999 Martin Mares <mj@ucw.cz>
+#
+
+use lib "/home/mj/perl/lib/site_perl";
+
+use Getopt::Std;
+use Net::DNS::Resolver;
+
+getopts('v', \%opts) && @ARGV == 1 || do {
+ print "Usage: convert [-v] <domain>\n";
+ exit 1;
+};
+$domain = norm_name($ARGV[0]);
+
+$verbose = $opts{"v"};
+
+$res = new Net::DNS::Resolver;
+$res->defnames(0);
+$res->dnsrch(0);
+$res->debug(0);
+
+$verbose && print "; Fetching zone data for $domain\n";
+@zone = $res->axfr($domain) or failed("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 "HH($n)\n"; }
+ if (defined $mx{$n}) { print "MX($mx{$n})\n"; }
+ if (defined $cn{$n}) { print "CNAME($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."; }
+}