#! /usr/bin/perl -w

# $Id: check-router-conf,v 1.26 2005/03/25 05:50:18 facq Exp $

# quick and dirty script to check for unused or undefined acl in cisco configs.

# usage: check-router-conf <config>

# http://facq.reaumur.net/OutilsEnVrac/check-router-conf

# 199? - Laurent FACQ - facq@u-bordeaux.fr - REAUMUR - Universite de Bordeaux

## @TODO@ regarder si recursicvement, ce qui est defini est vraiment
## utilise ex: interface shut, route-map non utilisee, etc...  =>
## utiliser un mecanisme utilisant l'indentation pour savoir dans qeul
## paragraph on se trouve

$aclalwaysdef{50}= "!default rip - permit 0.0.0.0 only (default root)\n";
$aclalwaysdef{51}= "!default rip - deny all\n";
$aclalwaysdef{97}= "!default snmp access\n";
$aclalwaysdef{190}= "!default routeur/vty protection\n";
$aclalwaysdef{'etudiant'}= "!special a5st3 dynamic acl via radius\n";
$aclalwaysdef{'test'}= "!special a5st3 dynamic acl via radius\n";

$mapalwaysdef{'class-default'}= "!map par defaut\n";

$aaa_auth_enable_defined= 
    $tacacs_host_defined= 
    $tacacs_last_ressort_defined=
    $tacacs_extended_defined= 0;

while ($l=<>)
{

    # le "match..." n'est pas toujours present suivant les version
    # pas de blanc pour nouvelle version.... @TODO@ pas tres fiables tout ca !
    if (($map)= ($l =~ m/^\s*class-map\s+match\S+\s+(\S+)/))
    {
	$mapdef{$map}= "no class-map $map\n";
    }
    elsif (($map)= ($l =~ m/^\s*class-map\s+(\S+)/))
    {
	$mapdef{$map}= "no class-map $map\n";
    }
    elsif (($map)= ($l =~ m/^ip\s+dhcp\s+class\s+(\S+)/))
    {
	$mapdef{$map}= "no ip dhcp class $map\n";
    }
    elsif (($map)= ($l =~ m/^\s+class\s+(\S+)/))
    {
	$mapuse{$map}= "! class-map $map\n";
    }
    elsif (($pmap)= ($l =~ m/^\s*policy-map\s+(\S+)/))
    {
	$pmapdef{$pmap}= "no policy-map $pmap\n";
    }
    elsif (($pmap)= ($l =~ m/^\s+service-policy\s+\S+\s+(\S+)/))
    {
	$pmapuse{$pmap}= "! policy-map $pmap\n";
    }
    elsif ($l =~ m/\s*access-list\s+compiled\s*$/) 
    { 
	next; 
    }
    elsif (($acl)= ($l =~ m/^ip\s+access-list\s+extended\s+(\S+)/))
    {
	$acldef{$acl}= "no ip access-list extended $acl\n";
    }
    elsif (($acl)= ($l =~ m/^ip\s+access-list\s+standard\s+(\S+)/))
    {
	$acldef{$acl}= "no ip access-list standard $acl\n";
    }
    elsif (($acl)= ($l =~ m/^access-list\s+(\S+)/))
    {
	$acldef{$acl}= "no access-list $acl\n";
    }
    elsif (($acl)= ($l =~ m/^\s+ip\s+access-group\s+(\S+)/))
    {
	$acluse{$acl}= "!ip access-group $acl\n";
    }
    elsif (($acl)= ($l =~ m/^ip\s+pim\s+rp-address\s+\S+\s+(\S+)/))
    {
	$acluse{$acl}= "!ip pim rp-address -ip- $acl\n";
    }
    elsif (($acl)= ($l =~ m/^ip\s+msdp\s+redistribute\s+list\s+(\S+)/))
    {
	$acluse{$acl}= "!ip msdp redistribute list msdp-filter $acl\n";
    }
    elsif (($acl)= ($l =~ m/^\s+bridge-group\s+\S+\s+input-type-list\s+(\S+)\s+/))
    {
	$acluse{$acl}= "!bridge-group ... input-type-list $acl ...\n";
    }
    elsif (($acl)= ($l =~ m/^\s+distribute-list\s+(\S+)/))
    {
	$acluse{$acl}= "!distribute-list $acl\n";
    }
    elsif (($acl)= ($l =~ m/^\s+access-class\s+(\S+)/))
    {
	$acluse{$acl}= "!access-class $acl\n";
    }
    elsif (($acl)= ($l =~ m/^\s+traffic-shape\s+group\s+(\S+)/))
    {
	$acluse{$acl}= "!traffic-shape group $acl\n";
    }
    elsif (($z,$acl)= ($l =~ m/^\s+rate-limit\s+(input|output)\s+access-group\s+(\S+)/))
    {
	$acluse{$acl}= "!rate-limit in/out access-group $acl\n";
    }
    elsif (($acl)= ($l =~ m/^\s+appletalk\s+getzonelist-filter\s+(\S+)/))
    {
	$acluse{$acl}= "!appletalk getzonelist-filters $acl\n";
    }
    elsif (($acl)= ($l =~ m/^\s+match\s+ip\s+address\s+prefix-list\s+(\S+)/))
    {
	$prefixlistuse{$acl}= "!match ip address prefix-list $acl\n";
    }
    elsif (($acl)= ($l =~ m/^ip\s+prefix-list\s+(\S+)/))
    {
	$prefixlistdef{$acl}= "!no ip prefix-list $acl\n";
    }
    elsif (($acl)= ($l =~ m/^\s+match\s+ip\s+address\s+(\S+)/))
    {
	$acluse{$acl}= "!match ip address $acl\n";
    }
    elsif (($acl)= ($l =~ m/^\s+match\s+access-group\s+name\s+(\S+)/))
    {
	$acluse{$acl}= "!match access-group name $acl\n";
    }
    elsif (($acl)= ($l =~ m/^\s+match\s+access-group\s+(\S+)/))
    {
	$acluse{$acl}= "!match access-group $acl\n";
    }
    elsif (($acl)= ($l =~ m/^priority-list\s+.*\s+list\s+(\S+)/))
    {
	$acluse{$acl}= "!priority-list ... list $acl\n";
    }
    elsif (($acl)= ($l =~ m/^snmp-server\s+community\s+\S+\s+\S+\s+(\S+)/))
    {
	$acluse{$acl}= "!snmp-server community ... $acl\n";
    }
    elsif (($acl)= ($l =~ m/^ip\s+nat\s+\S+\s+source\s+list\s+(\S+)/))
    {
	$acluse{$acl}= "!ip nat ... source list $acl\n";
    }
    elsif (($acl)= ($l =~ m/^dialer-list\s+\S+\s+protocol\s+ip\s+list\s+(\S+)/))
    {
	$acluse{$acl}= "!dialer-list ... protocol ip list $acl\n";
    }
    elsif ($l =~ m/^aaa\s+authentication\s+.*enable/)
    {
	$aaa_auth_enable_defined= 1;
    }
    elsif ($l =~ m/^tacacs-server host/)
    {
	$tacacs_host_defined= 1;
    }
    elsif ($l =~ m/^tacacs-server last-resort password/)
    {
	$tacacs_last_ressort_defined= 1;
    }
    elsif ($l =~ m/^tacacs-server extended/)
    {
	$tacacs_extended_defined= 1;
    }
}


if ($tacacs_host_defined && !$aaa_auth_enable_defined)
{
    if (!$tacacs_extended_defined)
    {
	print "Tacacs server host defined but missing : tacacs-server extended\n";
    }
    
    if (!$tacacs_last_ressort_defined)
    {	
	print "Tacacs server host defined missing : tacacs-server last-resort password\n";
    }
}

#### acl
foreach $acl (sort keys %acldef)
{
    if (!defined($acluse{$acl}) && !defined($aclalwaysdef{$acl}))
    {
	print "!Unused acl $acl : try \n$acldef{$acl}";
    }
}

foreach $acl (sort keys %acluse)
{
    if (!defined($acldef{$acl})  && !defined($aclalwaysdef{$acl}))
    {
	print "!Undef acl $acl : check \n$acluse{$acl}";
    }
}



#### map
foreach $map (sort keys %mapdef)
{
    if (!defined($mapuse{$map}) && !defined($mapalwaysdef{$map}))
    {
	print "!Unused map $map : try \n$mapdef{$map}";
    }
}

foreach $map (sort keys %mapuse)
{
    if (!defined($mapdef{$map})  && !defined($mapalwaysdef{$map}))
    {
	print "!Undef map $map : check \n$mapuse{$map}";
    }
}


#### pmap
foreach $pmap (sort keys %pmapdef)
{
    if (!defined($pmapuse{$pmap}) && !defined($pmapalwaysdef{$pmap}))
    {
	print "!Unused pmap $pmap : try \n$pmapdef{$pmap}";
    }
}

foreach $pmap (sort keys %pmapuse)
{
    if (!defined($pmapdef{$pmap}) && !defined($pmapalwaysdef{$pmap}))
    {
	print "!Undef policy-map $pmap : check \n$pmapuse{$pmap}";
    }
}

#### prefixlist
foreach $prefixlist (sort keys %prefixlistdef)
{
    if (!defined($prefixlistuse{$prefixlist}) && !defined($prefixlistalwaysdef{$prefixlist}))
    {
	print "!Unused prefixlist $prefixlist : try \n$prefixlistdef{$prefixlist}";
    }
}

foreach $prefixlist (sort keys %prefixlistuse)
{
    if (!defined($prefixlistdef{$prefixlist}) && !defined($prefixlistalwaysdef{$prefixlist}))
    {
	print "!Undef policy-map $prefixlist : check \n$prefixlistuse{$prefixlist}";
    }
}


$z=1; # -w happy
    


