#!/usr/local/bin/perl -w

# Convert a DNS zonefile into a hostdb.txt file.
#  It doesn't do 100% of the work, but certainly does the error-prone parts.
#  It strips out all MX records except for hosts with MX records pointing to
#	themself. Those become "ISMAILSERVER" hosts.
#  It makes a reasonable guess about what are ANAMEs.  The first time it
#	sees an A record for an IP address, it assumes this is the real name.
#	This could be improved by analyzing the PTR records too.

# TODO:
# o  If the in-addr.arpa files are included, use that information to
#	determine which hostname is canonical our of a set of ANAMEs.

# Copyright 2005 Thomas A. Limoncelli
# 
#     This program is free software; you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation; either version 2 of the License, or
#     (at your option) any later version.
#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.
# 
# 
#     You should have received a copy of the GNU General Public License
#     along with this program; if not, write to the Free Software
#     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA


use strict;

my ($name, $junk, $type, @opt);
my $ip;
my %ip2host; my %ip2anames; my %ipISMAILSERVER; my %cnamesOf;

while (<>) {
	chomp;
	($name, $junk, $type, @opt) = split;
	$name =~ s/\.$//g;

	if (/\tIN SOA\t/) {
		; # SOA: do nothing
	} elsif (/\tIN NS\t/) {
		; # do nothing
	} elsif (/\tIN A\t/) {
		# A: Record for later. If it is the second time we've seen
		# this IP, store it as an ANAMES.
		my $ip = $opt[0];
		if ($ip2host{$ip}) {
			if ($ip2anames{$ip}) {
				$ip2anames{$ip} .= ":" . $name;
			} else {
				$ip2anames{$ip} = $name;
			}
		} else {
			$ip2host{$ip} = $name;
		}
		#print "DEBUG: $ip = $name\n";
	} elsif (/\tIN CNAME\t/) {
		# CNAME: Accumulate for later.
		my $dst = $opt[0];
		$dst =~ s/\.$//g;
		#print "CNAME=$name to $dst\n";
		if ($cnamesOf{$dst}) {
			$cnamesOf{$dst} .= ":" . $name;
		} else {
			$cnamesOf{$dst} = $name;
		}
	} elsif (/\tIN MX\t/) {
		# If the MX points at itself, mark this as ISMAILSERVER.
		# Otherwise, do nothing.
		my ($pri, $dst) = @opt;
		$dst =~ s/\.$//g;
		#print "ISMAIL compare ", lc $dst, " AND ", lc $name, "\n";
		if ( (lc $dst) eq (lc $name) ) {
			$ipISMAILSERVER{ $name } = 1;
			#print "ISMAILSERVER=$name\n";
		}
	} else {
		print "OTHER: $_\n";
	}
}

foreach $ip ( keys %ip2host ) {
	$name = $ip2host{$ip};

	print $ip, "\t", $name;

	print " ISMAILSERVER" if $ipISMAILSERVER{ $name };

	if ($ip2anames{$ip}) {
		print " ANAMES=", $ip2anames{$ip};
	}

	if ($cnamesOf{$name}) {
		my @cnames = split(':', $cnamesOf{$name});
		print " CNAMES=", @cnames;
	}

	print "\n";
}
