aboutsummaryrefslogtreecommitdiffstats
path: root/examples/historical/clients/build-linknets.pl
blob: 015e006f45b1705cda6e8f0144a16a574dab6ead (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#! /usr/bin/perl

# sesse testing

use strict;
use warnings;
use lib '../include';
use nms;
use Net::CIDR;

my $dbh = nms::db_connect();

my $coregws = $dbh->prepare("SELECT switch, ip, community, sysname FROM switches WHERE sysname NOT LIKE 'e%' and sysname NOT LIKE 'sw%creativia%' AND sysname NOT LIKE 'sw%crew'")
	or die "Can't prepare query: $!";
$coregws->execute;

my %switch_id = ();   # sysname -> switch database ID
my %loopbacks = ();   # sysname -> primary address
my %loop_ipv6 = ();   # sysname -> primary address
my %map = ();         # CIDR -> (sysname,ip)*
my %lldpneigh = ();   # sysname -> sysname -> 1

while (my $ref = $coregws->fetchrow_hashref) {
	my $sysname = $ref->{'sysname'};
	$switch_id{$sysname} = $ref->{'switch'};

	print "$sysname...\n";
	my $snmp;
	eval {
		$snmp = nms::snmp_open_session($ref->{'ip'}, $ref->{'community'});
	};
	warn $@ if $@;
	next if not $snmp;

	my $routes = $snmp->gettable('ipCidrRouteTable');
	my $ifs = $snmp->gettable('ifTable');
	my $addrs = $snmp->gettable('ipAddrTable');
	my $lldp = $snmp->gettable('lldpRemTable');
        my $ipaddresstable = $snmp->gettable('ipAddressTable');

	# Find all direct routes we have, and that we also have an address in.
	# These are our linknet candidates.
	for my $route (values %$routes) {
		next if ($route->{'ipCidrRouteMask'} eq '255.255.255.255');
		next if ($route->{'ipCidrRouteNextHop'} ne '0.0.0.0');
		my $cidr = Net::CIDR::addrandmask2cidr($route->{'ipCidrRouteDest'}, $route->{'ipCidrRouteMask'});
		
		for my $addr (values %$addrs) {
			my $ip = $addr->{'ipAdEntAddr'};
			if (Net::CIDR::cidrlookup($ip, $cidr)) {
				push @{$map{$cidr}}, [ $sysname, $ip ];
			}
		}
	}

	# Find the first loopback address.
	my %loopbacks_this_switch = ();
	for my $addr (values %$addrs) {
		my $ifdescr = $ifs->{$addr->{'ipAdEntIfIndex'}}->{'ifDescr'};
		next unless $ifdescr =~ /^Loop/;
		$loopbacks_this_switch{$ifdescr} = $addr->{'ipAdEntAddr'};
	}
	for my $if (sort keys %loopbacks_this_switch) {
		$loopbacks{$sysname} = $loopbacks_this_switch{$if};
		last;
	}

        my %loopbacks_ipv6_this_switch = ();
        for my $addr (values %$ipaddresstable) {
                next if not  $addr->{'ipAddressAddrType'} == 2; # Only IPv6 addresses please.
                my $ifdescr = $ifs->{$addr->{'ipAddressIfIndex'}}->{'ifDescr'};
                next unless $ifdescr =~ /^Loop/;
                $loopbacks_ipv6_this_switch{$ifdescr} = nms::convert_ipv6( $addr->{'ipAddressAddr'} );
        }
        for my $if (sort keys %loopbacks_ipv6_this_switch) {
                $loop_ipv6{$sysname} = $loopbacks_ipv6_this_switch{$if};
                last;
        }

	# Find all LLDP neighbors.
	for my $neigh (values %$lldp) {
		$lldpneigh{lc($sysname)}{lc($neigh->{'lldpRemSysName'})} = 1;
	}
}

# print Dumper(\%switch_id);
# print Dumper(\%map);
# print Dumper(\%loopbacks);
# print Dumper(\%lldpneigh);

$dbh->{AutoCommit} = 0;
$dbh->{RaiseError} = 1;

# Update the switches we have loopback addresses fora
while (my ($sysname, $ip) = each %loopbacks) {
	$dbh->do('UPDATE switches SET ip=? WHERE sysname=?',
		undef, $ip, $sysname);
}
while (my ($sysname, $ipv6) = each %loop_ipv6) {
	$dbh->do('UPDATE switches SET secondary_ip=? WHERE sysname=?',
		undef, $ipv6, $sysname);
}

# Now go through each linknet candidate, and see if we can find any
# direct LLDP neighbors.
my $qexist = $dbh->prepare('SELECT COUNT(*) AS cnt FROM linknets WHERE switch1=? AND switch2=?');
#$dbh->do('DELETE FROM linknets');
while (my ($cidr, $devices) = each %map) {
	for (my $i = 0; $i < scalar @$devices; ++$i) {
		my $device_a = $devices->[$i];
		for (my $j = $i + 1; $j < scalar @$devices; ++$j) {
			my $device_b = $devices->[$j];
			next if $device_a->[0] eq $device_b->[0];
			next unless exists($lldpneigh{lc($device_a->[0])}{lc($device_b->[0])});

			my $switch_a = $switch_id{$device_a->[0]};
			my $switch_b = $switch_id{$device_b->[0]};
			my $ref = $dbh->selectrow_hashref($qexist, undef, $switch_a, $switch_b);
			next if ($ref->{'cnt'} != 0);

			$dbh->do('INSERT INTO linknets (switch1, addr1, switch2, addr2) VALUES (?,?,?,?)',
				undef,
				$switch_a, $device_a->[1],
				$switch_b, $device_b->[1]);
		}
	}
}
$dbh->commit;