-
-
Save ollyg/6736269 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
use warnings; | |
use strict; | |
use lib '/var/lib/netdisco'; | |
use netdisco qw/:all/; | |
config("/var/lib/netdisco/netdisco.conf"); | |
use NetSNMP::TrapReceiver; | |
my $nagios_cmd = "/var/nagios/rw/nagios.cmd"; | |
sub unwrap_value { | |
my $orig = shift; | |
my ($type, $blob) = split(/: /, $orig, 2); | |
if($type eq "STRING") { | |
# eat quotes | |
$blob =~ s/^"//; | |
$blob =~ s/"$//; | |
return $blob; | |
} else { | |
return $blob; | |
} | |
} | |
sub get_neighbor { | |
my ($host, $port) = @_; | |
# Get the DNS name by going from device_port, through device_ip, to | |
# device (device_port.remote_ip might be an alias) | |
return sql_scalar('device d, device_port p, device_ip i', | |
['d.dns'], | |
{'p.ip' => $host, 'p.port' => $port, | |
'i.alias' => \'p.remote_ip', 'i.ip' => \'d.ip' }); | |
} | |
sub get_name { | |
my $host = shift; | |
return sql_scalar('device d, device_ip i', | |
['d.dns'], | |
{'i.alias' => $host, | |
'i.ip' => \'d.ip' }); | |
} | |
sub poke_nagios { | |
my $name = shift; | |
# Chop off domain | |
$name =~ s/\..*//; | |
local $SIG{ALRM} = sub { warn "Leaked an alarm when poking Nagios\n" }; | |
eval { | |
local $SIG{ALRM} = sub { die "timed out on Nagios poke\n" }; | |
alarm 1; | |
-w $nagios_cmd or | |
die "$nagios_cmd not writable"; | |
open(NAGIOS, ">>", $nagios_cmd) | |
or die "Failed to open $nagios_cmd\n"; | |
printf NAGIOS "[%lu] SCHEDULE_FORCED_HOST_CHECK;%s;%lu\n", time, $name, time | |
or die "Failed to write to $nagios_cmd\n"; | |
close(NAGIOS) | |
or die "Failed to close $nagios_cmd\n"; | |
print STDERR "Scheduled re-check in Nagios for $name\n"; | |
}; | |
alarm 0; | |
if ($@) { | |
print STDERR "Failed while trying to poke Nagios\n"; | |
} | |
} | |
sub default_recv { | |
print "Unhandled trap:\n"; | |
# print the PDU info (a hash reference) | |
print "PDU INFO:\n"; | |
foreach my $k(keys(%{$_[0]})) { | |
printf " %-30s %s\n", $k, $_[0]{$k}; | |
} | |
# print the variable bindings: | |
print "VARBINDS:\n"; | |
foreach my $x (@{$_[1]}) { | |
printf " %-30s type=%-2d value=%s\n", $x->[0], $x->[2], $x->[1]; | |
} | |
return NETSNMPTRAPD_HANDLER_OK; | |
} | |
sub linkdown_recv { | |
my $host; | |
my $port; | |
my $type; | |
foreach my $x (@{$_[1]}) { | |
if($x->[0] =~ /^IF-MIB::ifDescr/) { | |
$port = unwrap_value($x->[1]); | |
} elsif($x->[0] =~ /^SNMP-COMMUNITY-MIB::snmpTrapAddress.0$/) { | |
$host = unwrap_value($x->[1]); | |
} elsif($x->[0] =~ /^IF-MIB::ifType/) { | |
$type = unwrap_value($x->[1]); | |
} | |
} | |
if(!$host or !$port or !$type) { | |
print STDERR "Missing field in trap\n"; | |
return NETSNMPTRAPD_HANDLER_OK; | |
} | |
# This bit isn't helpful | |
# if($type == 53) { | |
# print STDERR "Vlan interface change. Skipping trap\n"; | |
# } | |
print STDERR "Got link down from $host for $port\n"; | |
my $downed = get_neighbor($host, $port); | |
if($downed) { | |
print STDERR "$downed might be down\n"; | |
poke_nagios($downed); | |
} else { | |
print STDERR "Not sure what device went down\n"; | |
} | |
return NETSNMPTRAPD_HANDLER_OK; | |
} | |
sub linkup_recv { | |
my $host; | |
my $port; | |
my $type; | |
foreach my $x (@{$_[1]}) { | |
if($x->[0] =~ /^IF-MIB::ifDescr/) { | |
$port = unwrap_value($x->[1]); | |
} elsif($x->[0] =~ /^SNMP-COMMUNITY-MIB::snmpTrapAddress.0$/) { | |
$host = unwrap_value($x->[1]); | |
} elsif($x->[0] =~ /^IF-MIB::ifType/) { | |
$type = unwrap_value($x->[1]); | |
} | |
} | |
if(!$host or !$port or !$type) { | |
print STDERR "Missing field in trap\n"; | |
return NETSNMPTRAPD_HANDLER_OK; | |
} | |
# This bit isn't helpful | |
# if($type == 53) { | |
# print STDERR "Vlan interface change. Skipping trap\n"; | |
# } | |
print STDERR "Got link up from $host for $port\n"; | |
my $uped = get_neighbor($host, $port); | |
if($uped) { | |
print STDERR "$uped might be up\n"; | |
poke_nagios($uped); | |
} else { | |
print STDERR "Not sure what device went up\n"; | |
} | |
return NETSNMPTRAPD_HANDLER_OK; | |
} | |
sub coldstart_recv { | |
my $type; | |
my $host; | |
foreach my $x (@{$_[1]}) { | |
if($x->[0] =~ /^SNMPv2-SMI::enterprises.9.2.1.2.0$/) { | |
$type = unwrap_value($x->[1]); | |
} elsif($x->[0] =~ /^SNMP-COMMUNITY-MIB::snmpTrapAddress.0$/) { | |
$host = unwrap_value($x->[1]); | |
} | |
} | |
if(!$type) { | |
print STDERR "Missing field in trap\n"; | |
return NETSNMPTRAPD_HANDLER_OK; | |
} | |
my $name = get_name($host); | |
print STDERR "$name sent coldStart with reason: $type\n"; | |
poke_nagios($name); | |
return NETSNMPTRAPD_HANDLER_OK; | |
} | |
sub ignore_recv { | |
return NETSNMPTRAPD_HANDLER_OK; | |
} | |
NetSNMP::TrapReceiver::register("default", \&default_recv) || | |
warn "failed to register our perl trap handler\n"; | |
NetSNMP::TrapReceiver::register("IF-MIB::linkDown", \&linkdown_recv) || | |
warn "failed to register our perl trap handler\n"; | |
NetSNMP::TrapReceiver::register("IF-MIB::linkUp", \&linkup_recv) || | |
warn "failed to register our perl trap handler\n"; | |
NetSNMP::TrapReceiver::register("SNMPv2-MIB::coldStart", \&coldstart_recv) || | |
warn "failed to register our perl trap handler\n"; | |
my @ignore = ( | |
"SNMPv2-MIB::authenticationFailure", # SNMP Auth failures | |
"SNMPv2-SMI::enterprises.9.0.1", # tcpConnectionClose | |
"SNMPv2-SMI::enterprises.9.10.62.2.0.1",# CISCO-IPSEC-MIB::cipsIsakmpPolicyAdded | |
"SNMPv2-SMI::enterprises.9.10.62.2.0.3",# CISCO-IPSEC-MIB::cipsCryptomapAdded | |
"SNMPv2-SMI::enterprises.9.10.62.2.0.4",# CISCO-IPSEC-MIB::cipsCryptomapDeleted | |
"SNMPv2-SMI::enterprises.9.9.161.2.0.2",# CISCO-SLB-MIB::ciscoSlbRealStateChange | |
"SNMPv2-SMI::enterprises.9.9.171.2.0.1",# CISCO-IPSEC-FLOW-MONITOR-MIB::cikeTunnelStart | |
"SNMPv2-SMI::enterprises.9.9.171.2.0.2",# CISCO-IPSEC-FLOW-MONITOR-MIB::cikeTunnelStop | |
"SNMPv2-SMI::enterprises.9.9.171.2.0.7",# CISCO-IPSEC-FLOW-MONITOR-MIB::cipSecTunnelStart | |
"SNMPv2-SMI::enterprises.9.9.171.2.0.8",# CISCO-IPSEC-FLOW-MONITOR-MIB::cipSecTunnelStop | |
"SNMPv2-SMI::enterprises.9.9.315.0.1", # CISCO-PORT-SECURITY-MIB::ciscoPortSecurityMIBNotifs.1 | |
"SNMPv2-SMI::enterprises.9.9.41.2.0.1", # CISCO-SYSLOG-MIB::clogMessageGenerated | |
"SNMPv2-SMI::enterprises.9.9.43.2.0.1", # ciscoConfigManEvent | |
"SNMPv2-SMI::enterprises.9.9.46.2.0.10",# vtpVlanCreated | |
"SNMPv2-SMI::enterprises.9.9.46.2.0.2", # vtpConfigDigestError | |
"SNMPv2-SMI::enterprises.9.9.46.2.0.7", # vlanTrunkPortDynamicStatusChange | |
"SNMPv2-SMI::enterprises.9.9.82.2.0.3", # CISCO-STP-EXTENSIONS-MIB::stpxLoopInconsistencyUpdate | |
"SNMPv2-SMI::enterprises.9.9.87.2.0.1", # CISCO-C2900-MIB::c2900AddressViolation | |
"SNMPv2-SMI::mib-2.14.16.2.0.10", # OSPF-TRAP-MIB::ospfTraps.0.10 | |
"SNMPv2-SMI::mib-2.17.0.1", # BRIDGE-MIB::newRoot | |
"SNMPv2-SMI::mib-2.17.0.2", # BRIDGE-MIB::topologyChange | |
"SNMPv2-SMI::mib-2.47.2.0.1", # ENTITY-MIB::entConfigChange | |
); | |
foreach my $oid (@ignore) { | |
NetSNMP::TrapReceiver::register($oid, \&ignore_recv) || | |
warn "failed to register our perl trap handler for $oid\n"; | |
} | |
print STDERR "Loaded the netdisco trap handler\n"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment