Skip to content

Instantly share code, notes, and snippets.

@ollyg
Forked from bldewolf/netdisco-trapd.pl
Created September 27, 2013 22:44
Show Gist options
  • Save ollyg/6736269 to your computer and use it in GitHub Desktop.
Save ollyg/6736269 to your computer and use it in GitHub Desktop.
#!/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