aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristian Lyngstol <kly@kly.no>2016-06-04 22:27:56 +0200
committerKristian Lyngstol <kly@kly.no>2016-06-04 22:27:56 +0200
commit655a124a658ddc27c720d529b146995a127d0ca7 (patch)
treeaf716a12aa95f7d4b9e1ef6f57723bd0307ce784
parenta55a4a59c05993a159b1f1f659f3a42d9569ab29 (diff)
lolwhat: Further improve accuracy and do lldp-only map
The lldp-only map ensures we aren't fooled by vlans and other logical links, but if lldp is disabled it obviously doesn't tell the whole story.
-rwxr-xr-xextras/tools/lldp/dotnet.sh1
-rwxr-xr-xextras/tools/lldp/draw-neighbors.pl41
-rwxr-xr-xextras/tools/lldp/lolwhat.pl68
3 files changed, 91 insertions, 19 deletions
diff --git a/extras/tools/lldp/dotnet.sh b/extras/tools/lldp/dotnet.sh
index 66c384c..a3f5623 100755
--- a/extras/tools/lldp/dotnet.sh
+++ b/extras/tools/lldp/dotnet.sh
@@ -7,4 +7,5 @@ JSON=${OUT}lolwhat-${DATE}.json
./lolwhat.pl $* > ${JSON}
./draw-neighbors.pl < ${JSON} | dot -Tpng > ${OUT}lolwhat-${DATE}.png
./draw-neighbors.pl full < ${JSON} | dot -Tpng > ${OUT}lolwhat-${DATE}-full.png
+./draw-neighbors.pl lldp < ${JSON} | dot -Tpng > ${OUT}lolwhat-${DATE}-lldp.png
echo File name: ${OUT}lolwhat-${DATE}*png
diff --git a/extras/tools/lldp/draw-neighbors.pl b/extras/tools/lldp/draw-neighbors.pl
index 0a3f9d0..562e34e 100755
--- a/extras/tools/lldp/draw-neighbors.pl
+++ b/extras/tools/lldp/draw-neighbors.pl
@@ -12,17 +12,46 @@ while (<STDIN>) {
my %assets = %{JSON::XS::decode_json($in)};
my %map = %{$assets{hood}};
my %map2 = %{$assets{extended}};
+my %map3 = %{$assets{lldpmap}};
print "strict graph network {\n";
-while (my ($key, $value) = each %map) {
- print_tree ($key,0,undef);
+if ($full ne "lldp") {
+ while (my ($key, $value) = each %map) {
+ print_tree ($key,0,undef);
+ }
+ if ($full eq "full") {
+ while (my ($key, $value) = each %map2) {
+ print_tree2 ($key,0,undef);
+ }
+ }
+} else {
+ while (my ($key, $value) = each %map3) {
+ print_tree3 ($key, 0, undef);
+ }
}
-if ($full eq "full") {
-while (my ($key, $value) = each %map2) {
- print_tree2 ($key,0,undef);
-}}
print "}\n";
+sub print_tree3
+{
+ my ($id,$indent,$parent,$max) = @_;
+ my $name = $id;
+ if (defined($map3{$id}{sysName}) and $map3{$id}{sysName} ne "") {
+ $name = $map3{$id}{sysName};
+ }
+ if ($indent > 50) {
+ die "Possible loop detected.";
+ }
+ print " \"$name\" -- {";
+ my @n;
+ while (my ($key, $value) = each %{$map3{$id}{peers}}) {
+ my $peer = $key;
+ if (defined($map3{$key}{sysName}) and $map3{$key}{sysName} ne "") {
+ $peer = $map3{$key}{sysName};
+ }
+ push @n, "\"$peer\"";
+ }
+ print join(",",@n) . "};\n";
+}
sub print_tree
{
my ($name,$indent,$parent,$max) = @_;
diff --git a/extras/tools/lldp/lolwhat.pl b/extras/tools/lldp/lolwhat.pl
index a763be2..873899f 100755
--- a/extras/tools/lldp/lolwhat.pl
+++ b/extras/tools/lldp/lolwhat.pl
@@ -34,6 +34,8 @@ my @ips_to_check;
my $cmdline_community = shift;
my @ips = @ARGV;
+my %lldpmap = ();
+
sub mylog {
my $msg = shift;
my $time = POSIX::ctime(time);
@@ -45,9 +47,12 @@ sub mylog {
my %ipmap = ();
my %peermap = ();
+my %snmpresults = ();
foreach my $target (@ips) {
my $snmp = get_snmp_data($target, $cmdline_community);
my $parsed = parse_snmp($snmp);
+ $snmpresults{$target} = $parsed;
+
#print Dumper(\$parsed);
}
#print Dumper(\%ipmap);
@@ -71,7 +76,7 @@ while (my ($ip, $value) = each %peermap) {
#print Dumper(\%hood);
#print Dumper(\%extended);
-my %result = ( hood => \%hood, extended => \%extended, ipmap => \%ipmap, peermap => \%peermap);
+my %result = ( snmpresults => \%snmpresults, hood => \%hood, extended => \%extended, ipmap => \%ipmap, peermap => \%peermap, lldpmap => \%lldpmap);
print JSON::XS::encode_json(\%result);
exit;
@@ -177,6 +182,7 @@ sub get_snmp_data {
my $session = nms::snmp::snmp_open_session($ip, $community);
$ret{'sysName'} = $session->get('sysName.0');
$ret{'sysDescr'} = $session->get('sysDescr.0');
+ $ret{'lldpLocChassisId'} = $session->get('lldpLocChassisId.0');
$ret{'lldpRemManAddrTable'} = $session->gettable("lldpRemManAddrTable");
$ret{'lldpRemTable'} = $session->gettable("lldpRemTable");
$ret{'ipNetToMediaTable'} = $session->gettable('ipNetToMediaTable');
@@ -203,24 +209,62 @@ sub parse_snmp
my %result = ();
my %lol = ();
$result{sysName} = $snmp->{sysName};
+ my $sysname = $snmp->{sysName};
$result{sysDescr} = $snmp->{sysDescr};
+ $result{lldpLocChassisId} = nms::convert_mac($snmp->{lldpLocChassisId});
+ my $chassis_id = $result{lldpLocChassisId};
+ mylog("$sysname: $chassis_id");
+ my $bad_chassis_id = 0;
+ if (defined($chassis_id) and defined($lldpmap{$chassis_id}{sysName})) {
+ mylog("Spottet twin");
+ if ($lldpmap{$chassis_id}{sysName} ne $sysname) {
+ mylog("Spotted broken chassis id collision wtf omg lol");
+ mylog("stored $lldpmap{$chassis_id}{sysName} ne $sysname");
+ $bad_chassis_id = 1;
+ }
+ } else {
+ if (defined($chassis_id)) {
+ $lldpmap{$chassis_id}{sysName} = $sysname;
+ } else {
+ $bad_chassis_id = 1;
+ }
+ }
@{$result{ips}} = ();
@{$result{peers}} = ();
+ @{$result{lldppeers}} = ();
while (my ($key, $value) = each %{$snmp->{lldpRemTable}}) {
- my $chassis_id = nms::convert_mac($value->{'lldpRemChassisId'});
+ my $idx = $value->{lldpRemLocalPortNum};
+ my $rem_chassis_id = nms::convert_mac($value->{'lldpRemChassisId'});
+ my $remname = $value->{lldpRemSysName};
foreach my $key2 (keys %$value) {
- $lol{$value->{lldpRemIndex}}{$key2} = $value->{$key2};
+ $lol{$idx}{$key2} = $value->{$key2};
}
- $lol{$value->{lldpRemIndex}}{'lldpRemChassisId'} = $chassis_id;
+ $lol{$idx}{key} = $key;
+ $lol{$idx}{'lldpRemChassisId'} = $rem_chassis_id;
my %caps = ();
nms::convert_lldp_caps($value->{'lldpRemSysCapEnabled'}, \%caps);
- $lol{$value->{lldpRemIndex}}{'lldpRemSysCapEnabled'} = \%caps;
+ $lol{$idx}{'lldpRemSysCapEnabled'} = \%caps;
+ if ($bad_chassis_id == 1) {
+ mylog("Skipping lldp-coupling due to broken/nonexistent lldpLocChassisId");
+ next;
+ }
+ $lldpmap{$chassis_id}{peers}{$rem_chassis_id} = 1;
+ $lldpmap{$rem_chassis_id}{peers}{$chassis_id} = 1;
+ if (defined($lldpmap{$rem_chassis_id}{sysName})) {
+ if ($lldpmap{$rem_chassis_id}{sysName} ne $remname) {
+ mylog("Collision .... $rem_chassis_id: $remname vs $lldpmap{$rem_chassis_id}{sysName}");
+ }
+ } else {
+ $lldpmap{$rem_chassis_id}{sysName} = $remname;
+ }
}
while (my ($key, $value) = each %{$snmp->{lldpRemManAddrTable}}) {
my $old = 0;
- if (defined($lol{$value->{lldpRemIndex}}{lldpRemManAddr})) {
- mylog("\t\tFound existing address: $lol{$value->{lldpRemIndex}}{lldpRemManAddr}");
- $old = $lol{$value->{lldpRemIndex}}{lldpRemManAddrSubtype};
+ my $idx = $value->{lldpRemLocalPortNum};
+ my $remname = $lol{$idx}{lldpRemSysName};
+ if (defined($lol{$idx}{lldpRemManAddr})) {
+ mylog("\t\tFound existing address: $lol{$idx}{lldpRemManAddr}");
+ $old = $lol{$idx}{lldpRemManAddrSubtype};
}
my $addr = $value->{'lldpRemManAddr'};
my $addrtype = $value->{'lldpRemManAddrSubtype'};
@@ -228,20 +272,18 @@ sub parse_snmp
if ($key2 eq 'lldpRemManAddr') {
next;
}
- $lol{$value->{lldpRemIndex}}{$key2} = $value->{$key2};
+ $lol{$idx}{$key2} = $value->{$key2};
}
my $remip;
if ($addrtype == 1) {
$remip = nms::convert_ipv4($addr);
- $lol{$value->{lldpRemIndex}}{lldpRemManAddr} = nms::convert_ipv4($addr);
+ $lol{$idx}{lldpRemManAddr} = nms::convert_ipv4($addr);
} elsif ($addrtype == 2 && $old == 0) {
$remip = nms::convert_ipv6($addr);
- $lol{$value->{lldpRemIndex}}{lldpRemManAddr} = nms::convert_ipv6($addr);
+ $lol{$idx}{lldpRemManAddr} = nms::convert_ipv6($addr);
} else {
next;
}
- my $idx = $value->{lldpRemIndex};
- my $remname = $lol{$idx}{lldpRemSysName};
if (!defined($ipmap{$remip})) {
$ipmap{$remip} = $remname;
}