#!/usr/bin/perl use v5.10; use strict; use DBI; use experimental qw( switch ); our $FUNC_STATEMENT_HANDLE; my @entry; my %conf; #read_config ("config.txt"); $conf{'DB_TYPE'}="mysql"; $conf{'DB_NAME'}="routes"; $conf{'DB_HOST'}="10.99.0.199"; $conf{'DB_PORT'}="3306"; $conf{'DB_USER'}="conetadm"; $conf{'DB_PASS'}="Conet12#"; my @hostnames = read_hostnames (); my %hostname; foreach my $entry (@hostnames) { $hostname{"$entry->[1]"} = "$entry->[0]"; } my @protocols = read_protocols (); my %protocol; foreach my $entry (@protocols) { $protocol{"$entry->[1]"} = "$entry->[0]"; } # flush all routes from db flush_routes (); # Zeilen lesen # wenn Hostname nicht in DB, hinzufügen #my @files=`ls /home/rancid/var/rancid/network/configs | egrep "(asa|router|switch.*sp.*).*"`; #my @files=`cat /home/rancid/var/rancid/network/router.db | awk -F';' '{print $1}' | egrep "(asa|router|switch.*sp.*).*"`; #my @files=`ls /home/rancid/var/rancid/network/configs | egrep "switch-sp-1"`; my @files=`cat /home/rancid/var/rancid/network/router.db | awk -F';' '{print \$1}' | egrep "^(asa|router|switch.*sp.*).*"`; foreach my $host (@files) { chomp $host; print "$host\n"; add_router_db($host); # get routes from asa if ($host =~ /^asa-/) { my $ol; # oldline for EIGRP, multiple entries for same dest possible my @routing = `clogin -u $ENV{'SSHUSER'} -p $ENV{'SSHPASS'} -c "sh route" $host | egrep '^(S |B |D |E |O |I |C | )'`; foreach my $route (@routing) { chomp $route; $route =~ tr/\r//d; # check which protocol D, S, B if ($route =~ /^B/) { print "B"; $ol=""; my $prot = "BGP"; #B 192.168.50.0 255.255.255.248 [200/0] via 10.120.1.187, 7w0d my ($n,$m,$g) = $route =~ /^B\s+([0-9.]*) ([0-9.]*) .*via ([0-9.]*),.*$/; #print "host: $host ($hostname{$host}) net: $n, mask: $m, gw: $g, proto: $prot ($protocol{$prot})\n"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,'na',''); } elsif ($route =~ /^C/) { print "C"; $ol=""; my $prot = "CONNECTED"; #C 10.127.12.0 255.255.255.128 is directly connected, LCH_CPS my ($n,$m,$i) = $route =~ /^C\s+([0-9.]*) ([0-9.]*) .*is directly connected, (.*)$/; #print "###\n host: $host ($hostname{$host}), net: $n, mask: $m, gw: 'na', int: $i, proto: $prot ($protocol{$prot})\n####\n"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,'na',$i,''); } elsif ($route =~ /^D/) { print "D"; $ol=""; # can be shown on two or more lines, therefore myn routes lost ($n ne "") my $prot = "EIGRP"; #D EX 100.65.0.0 255.255.0.0 [170/537856] via 10.120.1.242, 7w0d, FITS my (undef,$n,$m,$g,$i) = $route =~ /^D([EX ]*) ([0-9.]*) ([0-9.]*) .*via ([0-9.]*),.*, (.*)$/; #print "###\n$route\n host: $host ($hostname{$host}), net: $n, mask: $m, gw: $g, int: $i, proto: $prot ($protocol{$prot})\n####\n"; if ($n ne "") { print "+"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,$i,''); } else { print "."; $ol=$route; } } elsif ($route =~ /^S/) { print "S"; $ol=""; my $prot = "STATIC"; #S 92.1.253.131 255.255.255.255 [1/0] via 92.254.20.22, DBS_ZOS my ($n,$m,$g,$i) = $route =~ /^S\s+([0-9.]*) ([0-9.]*) .*via ([0-9.]*),\s+(.*)$/; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,$i,''); } elsif ($route =~ /^ *\[/) { print "!"; # here we are, now $ol needed my $line = $ol . $route; my $prot = "EIGRP"; #D EX 10.1.1.0 255.255.255.0 [170/28416] via 172.31.254.11, 7w0d, OFFICE_XFER my (undef,$n,$m,$g,$i) = $line =~ /^D([EX ]*) ([0-9.]*) ([0-9.]*) .*via ([0-9.]*),.*, (.*)$/; #print "###\n$line\n host: $host ($hostname{$host}), net: $n, mask: $m, gw: $g, int: $i, proto: $prot ($protocol{$prot})\n####\n"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,$i,''); } } print "\n\n"; } if ($host =~ /^router/) { my @routing = `clogin -u $ENV{'SSHUSER'} -p $ENV{'SSHPASS'} -c "sh ip route" $host | egrep '^(S |B |D |E |O |I |C | )'`; my $ol; # oldline for EIGRP, multiple entries for same dest possible foreach my $route (@routing) { chomp $route; $route =~ tr/\r//d; # check which protocol D, S, B if ($route =~ /^B/) { print "B"; $ol=""; my $prot = "BGP"; #B 192.168.50.0 255.255.255.248 [200/0] via 10.120.1.187, 7w0d my ($n,$m,$g) = $route =~ /^B\s+([0-9.]*)(\/[0-9]*| ).*via ([0-9.]*),.*$/; #print "host: $host ($hostname{$host}) net: $n, mask: $m, gw: $g, proto: $prot ($protocol{$prot})\n"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,'na',''); } elsif ($route =~ /^C/) { print "C"; $ol=""; my $prot = "CONNECTED"; #C 10.127.12.0 255.255.255.128 is directly connected, LCH_CPS my ($n,$m,$i) = $route =~ /^C\s+([0-9.]*)(\/[0-9]*| ).*is directly connected, (.*)$/; #print "###\n host: $host ($hostname{$host}), net: $n, mask: $m, gw: 'na', int: $i, proto: $prot ($protocol{$prot})\n####\n"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,'na',$i,''); } elsif ($route =~ /^D/) { print "D"; $ol=""; # can be shown on two or more lines, therefore myn routes lost ($n ne "") my $prot = "EIGRP"; #D EX 2.104.55.0 [170/538112] via 10.127.12.126, 7w0d, Vlan2027 my (undef,$n,$m,$g,$i) = $route =~ /^D([EX ]*) ([0-9.]*)(\/[0-9]*| ).*via ([0-9.]*),.*, (.*)$/; #print "###\n$route\n host: $host ($hostname{$host}), net: $n, mask: $m, gw: $g, int: $i, proto: $prot ($protocol{$prot})\n####\n"; if ($n ne "") { print "+"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,$i,''); } else { print "."; $ol=$route; } } elsif ($route =~ /^S/) { print "S"; $ol=""; my $prot = "STATIC"; #S 208.134.161.0/24 [1/0] via 10.101.2.1 my ($n,$m,$g,$i) = $route =~ /^S\s+([0-9.]*)(\/[0-9]*| ).*via ([0-9.]*)$/; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,$i,''); } elsif ($route =~ /^ *\[/) { print "!"; # here we are, now $ol needed my $line = $ol . $route; my $prot = "EIGRP"; #D EX 10.1.1.0 255.255.255.0 [170/28416] via 172.31.254.11, 7w0d, OFFICE_XFER my (undef,$n,$m,$g,$i) = $line =~ /^D([EX ]*) ([0-9.]*)(\/[0-9]*| ).*via ([0-9.]*),.*, (.*)$/; #print "###\n$line\n host: $host ($hostname{$host}), net: $n, mask: $m, gw: $g, int: $i, proto: $prot ($protocol{$prot})\n####\n"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,$i,'') if ($n ne ""); } } print "\n\n"; } if ($host =~ /^switch-/) { my @vrfs = `clogin -u $ENV{'SSHUSER'} -p $ENV{'SSHPASS'} -c "sh run" $host | egrep "^ip vrf|vrf definition" | awk '{print \$3}'`; push @vrfs, "NONE"; foreach my $vrf (@vrfs) { chomp $vrf; $vrf =~ tr/\r//d; my $str; $str = "sh ip route vrf $vrf" if ($vrf ne "NONE"); $str = "sh ip route" if ($vrf eq "NONE"); my @routing = `clogin -u $ENV{'SSHUSER'} -p $ENV{'SSHPASS'} -c "$str" $host | egrep '^(S |B |D |E |O |I |C | )'`; my $ol; # oldline for EIGRP, multiple entries for same dest possible foreach my $route (@routing) { chomp $route; $route =~ tr/\r//d; # check which protocol D, S, B if ($route =~ /^B/) { print "B"; $ol=""; my $prot = "BGP"; #B 192.168.50.0 255.255.255.248 [200/0] via 10.120.1.187, 7w0d my ($n,$m,$g) = $route =~ /^B\s+([0-9.]*)(\/[0-9]*| ).*via ([0-9.]*),.*$/; #print "host: $host ($hostname{$host}) net: $n, mask: $m, gw: $g, proto: $prot ($protocol{$prot})\n"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,'na',$vrf); } elsif ($route =~ /^C/) { print "C"; $ol=""; my $prot = "CONNECTED"; #C 10.127.12.0 255.255.255.128 is directly connected, LCH_CPS my ($n,$m,$i) = $route =~ /^C\s+([0-9.]*)(\/[0-9]*| ).*is directly connected, (.*)$/; #print "###\n host: $host ($hostname{$host}), net: $n, mask: $m, gw: 'na', int: $i, proto: $prot ($protocol{$prot})\n####\n"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,'na',$i,$vrf); } elsif ($route =~ /^D/) { print "D"; $ol=""; # can be shown on two or more lines, therefore myn routes lost ($n ne "") my $prot = "EIGRP"; #D EX 2.104.55.0 [170/538112] via 10.127.12.126, 7w0d, Vlan2027 #my (undef,$n,$m,$g,$i) = $route =~ /^D([EX ]*) ([0-9.]*)(\/[0-9]*| )\[.*via ([0-9.]*),.*, (.*)$/; my (undef,$n,$m,$g,$i) = $route =~ /^D ([XIANE12]*) *([0-9.]*[0-9.]*[0-9.]*[0-9])(\/[0-9]*|) .*via ([0-9.]*[0-9.]*[0-9.]*[0-9]),.*, (.*)$/; #print "###\n$route\n host: $host ($hostname{$host}), net: $n, mask: $m, gw: $g, int: $i, proto: $prot ($protocol{$prot})\n####\n"; if ($n ne "") { print "+"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,$i,$vrf); $ol=$route; } else { print "."; $ol=$route; } } elsif ($route =~ /^O/) { print "O"; #O E2 2.104.55.0 [110/20] via 172.17.157.21, 2w1d, Vlan3 #O E2 192.168.213.0/24 [110/10000] via 10.120.1.241, 7w0d, Vlan2006 my $prot = "OSPF"; #my (undef,$n,$m,$g,$i) = $route =~ /^O([IANE12 ]*) ([0-9.]*)(\/[0-9]*| )\[.*via ([0-9.]*),.*, (.*)$/; my (undef,$n,$m,$g,$i) = $route =~ /^O ([XIANE12]*) *([0-9.]*[0-9.]*[0-9.]*[0-9])(\/[0-9]*|) .*via ([0-9.]*[0-9.]*[0-9.]*[0-9]),.*, (.*)$/; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,$i,$vrf); } elsif ($route =~ /^S/) { print "S"; $ol=""; my $prot = "STATIC"; #S 208.134.161.0/24 [1/0] via 10.101.2.1 my ($n,$m,$g,$i) = $route =~ /^S\s+([0-9.]*)(\/[0-9]*| ).*via ([0-9.]*)$/; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,$i,$vrf); } elsif ($route =~ /^ *\[/) { print "!"; # here we are, now $ol needed my $prot = "EIGRP"; #D EX 160.92.34.32/27 [170/768256] via 10.127.12.130, 1w2d, Vlan2028 # [170/768256] via 10.127.12.2, 1w2d, Vlan2027 my (undef,$n,$m,$g,$i) = $ol =~ /^D([EX ]*) ([0-9.]*)(\/[0-9]*| ).*via ([0-9.]*),.*, (.*)$/; ($g,$i) = $route =~ /via ([0-9.]*),.*, (.*)$/; #print "###\n$line\n host: $host ($hostname{$host}), net: $n, mask: $m, gw: $g, int: $i, proto: $prot ($protocol{$prot})\n####\n"; insert_route ($hostname{$host},$protocol{$prot},$n,$m,$g,$i,$vrf); } } print "\n\n"; } } } print "\nende\n"; sub insert_route () { my ($h,$p,$n,$m,$g,$i,$v) = @_; return 1 if ($n eq ""); my $DBH; db_connect($DBH, $conf{'DB_TYPE'}, $conf{'DB_NAME'}, $conf{'DB_HOST'}, $conf{'DB_PORT'}, $conf{'DB_USER'}, $conf{'DB_PASS'}); db_exec($DBH, "insert into routes set hostname_id='$h', destination='$n', netmask='$m', gateway='$g', interface='$i', protocol_id='$p', vrf='$v'"); db_disconnect($DBH); } sub flush_routes () { my $DBH; db_connect($DBH, $conf{'DB_TYPE'}, $conf{'DB_NAME'}, $conf{'DB_HOST'}, $conf{'DB_PORT'}, $conf{'DB_USER'}, $conf{'DB_PASS'}); db_exec($DBH, "delete from routes"); db_disconnect($DBH); } sub add_router_db () { my $rtr = $_[0]; my $DBH; db_connect($DBH, $conf{'DB_TYPE'}, $conf{'DB_NAME'}, $conf{'DB_HOST'}, $conf{'DB_PORT'}, $conf{'DB_USER'}, $conf{'DB_PASS'}); my @res = db_select($DBH, "select id from hostnames where hostname = '$rtr'"); if ($res[0][0] eq "") { my @res = db_exec($DBH, "insert into hostnames set hostname = '$rtr'"); } db_disconnect($DBH); } sub read_hostnames { my $DBH; db_connect($DBH, $conf{'DB_TYPE'}, $conf{'DB_NAME'}, $conf{'DB_HOST'}, $conf{'DB_PORT'}, $conf{'DB_USER'}, $conf{'DB_PASS'}); my @res = db_select($DBH, "select id,hostname from hostnames"); db_disconnect($DBH); return @res; } sub read_protocols { my $DBH; db_connect($DBH, $conf{'DB_TYPE'}, $conf{'DB_NAME'}, $conf{'DB_HOST'}, $conf{'DB_PORT'}, $conf{'DB_USER'}, $conf{'DB_PASS'}); my @res = db_select($DBH, "select id,protocol from protocols"); db_disconnect($DBH); return @res; } sub db_connect (@) { my $ok = eval { $_[0] = DBI->connect("dbi:$_[1]:$_[2]:$_[3]:$_[4]", "$_[5]", "$_[6]"); return 0 if (!$_[0]); return 1; }; return $ok; } sub db_disconnect (@) { $_[0]->disconnect(); } sub db_exec (@) { $FUNC_STATEMENT_HANDLE = $_[0]->prepare ("$_[1]"); $FUNC_STATEMENT_HANDLE->execute(); $FUNC_STATEMENT_HANDLE->finish(); } sub db_select (@) { my @data; my $i; my $j; my @ret; $FUNC_STATEMENT_HANDLE = $_[0]->prepare ("$_[1]"); $FUNC_STATEMENT_HANDLE->execute(); $i=0; while (@data = $FUNC_STATEMENT_HANDLE->fetchrow_array()) { $j=0; foreach (@data) { $ret[$i][$j]=$_; $j++; } $i++; } return @ret; } sub read_config { my $configfile=shift; my $vd=':'; # trennt var von wert my $ad=';'; # trennt werte im array bzw. wertpaare im hash my $hd='#'; # trennt wert von key im hash open CF,"$configfile"; foreach () { chomp; if ($_ =~ /require/) { my ($f) = $_ =~ /require "(.*)"/; read_config($f); } else { my ($k,$v) = split /$vd/,$_; # trennung zwischen var-name und werten if ($k =~ /^@/) { # array variable my @val=split /$ad/,$v; foreach (@val) { push @{$conf{"$k"}},$_; } } if ($k =~ /^%/) { # hash variable my @val=split /$ad/,$v; foreach my $vp (@val) { my ($k1,$v1) = split /$hd/,$vp; $conf{"$k"}{"$k1"}=$v1; } } else { $conf{"$k"} = $v; } } } close CF; }