Brute force all known connection methods. A lot slower, but seems to

work better.

(cherry picked from commit a54e99feba)
This commit is contained in:
Ramon Novoa 2015-06-30 16:30:14 +02:00
parent e4c1a34e30
commit 18495a23e5
1 changed files with 70 additions and 6 deletions

View File

@ -89,6 +89,9 @@ my %SWITCH_TO_SWITCH;
# MAC addresses.
my %MAC;
# Parent-child relationships (in Pandora).
my %PARENTS;
# Entry router.
my $ROUTER;
@ -461,6 +464,8 @@ sub arp_cache_discovery {
foreach my $line (@output) {
next unless ($line =~ /^$IPNETTOMEDIAPHYSADDRESS.\d+.(\S+)\s+=\s+\S+:\s+(.*)$/);
my ($ip_addr, $mac_addr) = ($1, $2);
next if ($ip_addr =~ m/\.255$|\.0$|127\.0\.0\.1$/);
$mac_addr = parse_mac($mac_addr);
# Save the mac to connect hosts to switches/routers.
@ -497,6 +502,8 @@ sub find_synonyms($$$) {
# Get ARP cache.
my @ip_addresses = snmp_get_value_array($device, $community, $IPENTADDR);
foreach my $ip_address (@ip_addresses) {
next if ($ip_address =~ m/\.255$|\.0$|127\.0\.0\.1$/);
$VISITED_DEVICES{$device}->{'addr'}->{$ip_address} = '';
# Link the two addresses.
@ -737,7 +744,6 @@ sub host_connectivity($) {
next unless ($device_if_name ne '');
my $host_if_name = defined($COMMUNITIES{$host}) ? get_if_from_mac($host, $COMMUNITIES{$host}, $mac) : '';
if ($VISITED_DEVICES{$device}->{'type'} eq 'router') {
next if defined ($SWITCH_TO_SWITCH{"$device$device_if_name"}); # The switch is probably connected to another router/switch.
message("Host $host " . ($host_if_name ne '' ? "(if $host_if_name)" : '') . " is connected to router $device (if $device_if_name).");
}
elsif ($VISITED_DEVICES{$device}->{'type'} eq 'switch') {
@ -881,12 +887,34 @@ sub create_pandora_agent($) {
return $agent_id;
}
##########################################################################
# Check for switches that are connected to other switches/routers and show
# up in a switche/router's port.
##########################################################################
sub switch_already_connected ($$$$) {
my ($dev_1, $if_1, $dev_2, $if_2) = @_;
if ($VISITED_DEVICES{$dev_1}->{'type'} eq 'router' ||
$VISITED_DEVICES{$dev_1}->{'type'} eq 'switch') {
return 1 if defined ($SWITCH_TO_SWITCH{"$dev_1$if_1"}); # The switch is probably connected to another router/switch.
}
elsif ($VISITED_DEVICES{$dev_2}->{'type'} eq 'router' ||
$VISITED_DEVICES{$dev_2}->{'type'} eq 'switch') {
return 1 if defined ($SWITCH_TO_SWITCH{"$dev_2$if_2"}); # The switch is probably connected to another router/switch.
}
return 0;
}
##########################################################################
# Connect the given devices in the Pandora FMS database.
##########################################################################
sub connect_pandora_agents($$$$) {
my ($dev_1, $if_1, $dev_2, $if_2) = @_;
# Check switch connectivy.
return if (switch_already_connected($dev_1, $if_1, $dev_2, $if_2) == 1);
# Get the agent for the first device.
my $agent_1 = get_agent_from_addr($DBH, $dev_1);
if (!defined($agent_1)) {
@ -901,7 +929,7 @@ sub connect_pandora_agents($$$$) {
}
return unless defined($agent_2);
# Check wether the modules exists.
# Check whether the modules exists.
my $module_name_1 = safe_input($if_1 eq '' ? 'ping' : "ifOperStatus_$if_1");
my $module_name_2 = safe_input($if_2 eq '' ? 'ping' : "ifOperStatus_$if_2");
my $module_id_1 = get_agent_module_id($DBH, $module_name_1, $agent_1->{'id_agente'});
@ -915,6 +943,13 @@ sub connect_pandora_agents($$$$) {
return;
}
# Make sure the modules are not already connected.
if (defined($CONNECTIONS{"${module_id_1}_${module_id_2}"}) ||
defined($CONNECTIONS{"${module_id_2}_${module_id_1}"})) {
message("Devices $dev_1 and $dev_2 are already connected.");
return;
}
# Mark the two devices as connected.
$CONNECTIONS{"${module_id_1}_${module_id_2}"} = 1;
if (ref($VISITED_DEVICES{$dev_1}) eq 'HASH') {
@ -935,7 +970,13 @@ sub connect_pandora_agents($$$$) {
}
# Update parents.
db_do($DBH, 'UPDATE tagente SET id_parent=? WHERE id_agente=?', $agent_1->{'id_agente'}, $agent_2->{'id_agente'});
if (!defined($PARENTS{$agent_2->{'id_agente'}})) {
$PARENTS{$agent_2->{'id_agente'}} = $agent_1->{'id_agente'};
db_do($DBH, 'UPDATE tagente SET id_parent=? WHERE id_agente=?', $agent_1->{'id_agente'}, $agent_2->{'id_agente'});
} elsif (!defined($PARENTS{$agent_1->{'id_agente'}})) {
$PARENTS{$agent_1->{'id_agente'}} = $agent_2->{'id_agente'};
db_do($DBH, 'UPDATE tagente SET id_parent=? WHERE id_agente=?', $agent_2->{'id_agente'}, $agent_1->{'id_agente'});
}
}
@ -1131,12 +1172,35 @@ for (my $i = 0; defined($ROUTERS[$i]); $i++) {
update_recon_task($DBH, $TASK_ID, 75);
# Find switch/router to host connections.
my @hosts = (@ROUTERS, @SWITCHES, @HOSTS);
message("[6/6] Finding switch/router to end host connectivity...");
foreach my $device (@ROUTERS, @SWITCHES, @HOSTS) {
foreach my $device (@hosts) {
host_connectivity($device);
}
foreach my $host (@HOSTS) {
next unless (ref($VISITED_DEVICES{$host}) eq 'HASH'); # Skip aliases.
# Retry all known connectivity methods by brute force.
for (my $i = 0; defined($hosts[$i]); $i++) {
my $switch_1 = $hosts[$i];
for (my $j = $i + 1; defined($hosts[$j]); $j++) {
my $switch_2 = $hosts[$j];
switch_to_switch_connectivity($switch_1, $switch_2) if ($switch_1 ne $switch_2);
}
}
foreach my $router (@hosts) {
foreach my $switch (@hosts) {
router_to_switch_connectivity($router, $switch) if ($router ne $switch);
}
}
for (my $i = 0; defined($hosts[$i]); $i++) {
my $router_1 = $hosts[$i];
for (my $j = $i + 1; defined($hosts[$j]); $j++) {
my $router_2 = $hosts[$j];
router_to_router_connectivity($router_1, $router_2) if ($router_1 ne $router_2);
}
}
# Connect hosts that are still unconnected using traceroute.
foreach my $host (@hosts) {
next if ($VISITED_DEVICES{$host}->{'connected'} == 1); # Skip already connected hosts.
traceroute_connectivity($host);
}