#!/usr/local/bin/perl
# dn-cisco.pl
#
# Written 4/14/2000 by Keith Sinclair
#
# This PERL script will read in a Cisco router config and extract the addressing information
# it is then able to generate Host table extries, DNS IN A records, DNS IN PTR records and
# IN TXT records.  
# It uses 
# usage : dns-cisco.pl ( to see command line options )
#
# Note: The ARPA option will generate files automatically.
#
# Feedback : ksinclai@cisco.com
#
if ( $#ARGV < 0 ) {
	print "$0 generates address information from cisco config files\n";
	print "command line options are:\n";
	print "\tfile=<source cisco config file>\n";
	print "\t[host=true|false]\t(host style is the default option)\n";
	print "\t[head=true|false]\tDisplays a heading\n";
	print "\t[dns=true|false]\tSends IN A entries to STDOUT\n";
	print "\t[arpa=true|false]\tSends in-addr.arpa entries to STDOUT.\n";
	print "\t[savearpa=true|false]\tSaves in-addr.arpa entries into files.\n";
	print "\t[winarpa=true|false]\tGenerates WINDOWS in-addr.arpa entries.\n";
	print "\t[text=true|false]\tGenerates TEXT records which are the interface description.\n";
	
	exit(1);
}
# Command Line Arguments:
for ($i=0; $i <= $#ARGV; ++$i) {
        if ($ARGV[$i] =~ /.+=/) {
                $name = $ARGV[$i];
                $value = $name;
                $name =~ s/(.*)=.*/$1/;
                $value =~ s/(.*)=(.*)/$2/;
                $nvp{$name} = $value;
                if ($debug) {
                        print "$name=$value\n"
                }
        } else {
                print STDERR "Invalid command argument: $ARGV[$i]\n";
                # Log here
                exit -1;
        }
}
# all arguments are now stored in nvp (name value pairs)          
my $CiscoCFG=$nvp{file};
my $head=$nvp{head};
my $dns=$nvp{dns};
my $host=$nvp{host};
my $arpa=$nvp{arpa};
my $winarpa=$nvp{winarpa};
my $savearpa=$nvp{savearpa};
my $text=$nvp{text};

my %ipaddress;
my %ipmask;
my %description;
my %bandwidth;

my $hostname;
my $shortint;

if ( $host eq "" ) { $host="true"; }

if ( -d $CiscoCFG ) {

	# File is a directory

	opendir (DIR, "$CiscoCFG");
	@dirlist = readdir DIR;
	closedir DIR;
	
	@dirlist = sort @dirlist;
	
	for ( $i = 2 ; $i < $#dirlist ; ++$i ) 
	{
		if ( $dirlist[$i] !~ /^\./ and ! -d $dirlist[$i] ) {
			&ProcessCiscoFile("$CiscoCFG/$dirlist[$i]");
			&dnsEntries;
		}
	}
}
else {
	&ProcessCiscoFile($CiscoCFG);
	&dnsEntries;
}

sub dnsEntries {
	
	my $arpafile;
	my $bandstring;
		
	foreach $key (sort (keys %ipaddress)) {
		$interface = $key;
		$key =~ s/\//-/g;
		$key =~ s/:/-/g;
		$key = lc($key);
		$shortint = &shortInterface($key);

		if ( $head eq "true" ) { 
			print "$hostname, $interface, $ipaddress{$interface}\n";
		}
		if ( $host eq "true" ) {
			if ( $interface =~ /loopback0/i ) {
				print "$ipaddress{$interface}\t\t$hostname\t$hostname--$shortint\n";
			}
			else {
				print "$ipaddress{$interface}\t\t$hostname--$shortint\n";
			}
		}
		if ( $dns eq "true" ) {
			if ( $interface =~ /loopback0/i ) {
				print "$hostname\tIN\tA\t$ipaddress{$interface}\n";
				print "$hostname--$shortint\tIN\tCNAME\t$hostname.router.anz.\n";
			}
			else {
				print "$hostname--$shortint\tIN\tA\t$ipaddress{$interface}\n";
			}
		}
		if ( $arpa eq "true" ) {
			# ARPA Entries are in MS DNS format of octet4.octet3.octet2
			@octets = split (/\./,$ipaddress{$interface});


			if ( $interface =~ /loopback0/i ) {
				print "$octets[3].$octets[2].$octets[1].$octets[0].in-addr.arpa.\tIN\tPTR\t$hostname.anz.com.\n";
			}
			else {
				print "$octets[3].$octets[2].$octets[1].$octets[0].in-addr.arpa.\tIN\tPTR\t$hostname--$shortint.anz.com.\n";
			}
		}

		if ( $savearpa eq "true" ) {
			@octets = split (/\./,$ipaddress{$interface});
			if ( $octets[0] < 127 ) {
				$arpafile = "$octets[0].in-addr.arpa";
			}
			else {
				$arpafile = "$octets[1].$octets[0].in-addr.arpa";
			}

			#if ( ! -e $arpafile ) {
			#	open (ARPA, ">$arpafile.dns" ) || warn "Can't find Cisco config file $arpafile. $!\n";
			#	print ARPA "$arpafile\tIN\tSOA\thstibm9672-5-9.anz.\n";
			#	close (ARPA);
			#}

			open (ARPA, ">>$arpafile.dns" ) || warn "Can't find Cisco config file $arpafile. $!\n";
			if ( $interface =~ /loopback0/i ) {
				print ARPA "$octets[3].$octets[2].$octets[1].$octets[0].in-addr.arpa.\tIN\tPTR\t$hostname.router.anz.\n";
			}
			else {
				print ARPA "$octets[3].$octets[2].$octets[1].$octets[0].in-addr.arpa.\tIN\tPTR\t$hostname--$shortint.router.anz.\n";
			}
			close (ARPA);
		}

		if ( $winarpa eq "true" ) {
			# ARPA Entries are in MS DNS format of octet4.octet3.octet2
			@octets = split (/\./,$ipaddress{$interface});

			if ( $interface =~ /loopback0/i ) {
				print "$octets[3].$octets[2].$octets[1]\tIN\tPTR\t$hostname.router.anz.\n";
			}
			else {
				print "$octets[3].$octets[2].$octets[1]\tIN\tPTR\t$hostname--$shortint.router.anz.\n";
			}
		}

		if ( $text eq "true" and $description{$interface} ne "" ) {
			if ( $bandwidth{$interface} ne "" ) {
				$bandstring = " bandwidth=$bandwidth{$interface}";
			}
			else {
				$bandstring = "";
			}
			if ( $interface =~ /loopback0/i ) {
				print "$hostname\tIN\tTXT\t\"$description{$interface}$bandstring\"\n";
			}
			else {
				print "$hostname--$shortint\tIN\tTXT\t\"$description{$interface}$bandstring\"\n";
			}
		}
	}
}


#
# Read down the Cisco Router config file to find out info about each interface.
#
sub ProcessCiscoFile {
	
	$file = shift;

	undef %ipaddress;
	
	open (CiscoFile, $file ) || die "Can't find Cisco config file $file. $!\n";
	
	while(<CiscoFile>) {
		chomp;
		if ($_ =~ /hostname /)   { 
			@x=split " ", $_;
			$hostname = lc($x[1]);
		}
		if ($_ eq "no ip address") { next; }
		if ($_ eq "!") { $found="n"; }
		if ($_ =~ /interface /) {
			$_ =~ s/\./-/g;
			@x=split " ", $_;
			$found = "y";
			$interface = $x[1];
		}

		if ($found eq "y") {
			if ($_ =~ /description/) { $description{$interface} = substr($_,13); }
			if ($_ =~ /bandwidth/) { @x=split " ", $_; $bandwidth{$interface} = $x[1]; }
			if ($_ =~ /^ ip address/) { 
				@x=split " ", $_; 
				$ipaddress{$interface} = $x[2]; 
				$ipmask{$interface} = $x[3]; 
			}
		}
	}
	close CiscoFile;
}

sub shortInterface {
	$shortint = shift;
	
	# Change the Names of interfaces to shortnames
	$shortint =~ s/PortChannel/pc/gi;
	$shortint =~ s/TokenRing/tr/gi;
	$shortint =~ s/Ethernet/eth/gi;
	$shortint =~ s/FastEthernet/feth/gi;
	$shortint =~ s/GigabitEthernet/geth/gi;
	$shortint =~ s/Serial/ser/gi;
	$shortint =~ s/Loopback/lo/gi;
	$shortint =~ s/VLAN/vlan/gi;
	$shortint =~ s/BRI/bri/gi;
	$shortint =~ s/fddi/fddi/gi;
	$shortint =~ s/Async/as/gi;
	$shortint =~ s/ATM/atm/gi;
	$shortint =~ s/Port-channel/pchan/gi;
	
	return($shortint);
}