#!/usr/bin/perl # # gen_check_snmp_if_services # # genereates a services file for a host # for use w/ check_snmp_serviecs # ## libraries use strict; use Net::SNMP; use Getopt::Long; &Getopt::Long::config('auto_abbrev'); ## variable declairations my $progname = "gen_check_snmp_if_services"; my $version = "0.5"; my $hostname; my $needhelp; my $templatefile = "services-check_snmp_if.template"; my $crctemplatefile = "services-check_snmp_if_crc.template"; my $servdeptemplatefile = "servicedep-check_snmp_if.template"; my $template; my $crctemplate; my $servdeptemplate; my $cmd = "check_snmp_if"; my $crccmd = "check_snmp_crc_int"; # snmp variables my $snmpcommunity = "public"; my $snmpport = "161"; my %snmpoid = ( sysDescr => ".1.3.6.1.2.1.1.1.0", sysUptime => ".1.3.6.1.2.1.1.3.0", ifAdminStatus => ".1.3.6.1.2.1.2.2.1.7", ifOperStatus => ".1.3.6.1.2.1.2.2.1.8", ifNumber => ".1.3.6.1.2.1.2.1.0", ifIndex => ".1.3.6.1.2.1.2.2.1.1", ifDescr => ".1.3.6.1.2.1.2.2.1.2", ifInErrors => ".1.3.6.1.2.1.2.2.1.14", ifName => ".1.3.6.1.2.1.31.1.1.1.1", ifAlias => ".1.3.6.1.2.1.31.1.1.1.18", wanLineName => ".1.3.6.1.4.1.529.4.21.1.2", wanLineState => ".1.3.6.1.4.1.529.4.21.1.5", slotIndex => ".1.3.6.1.4.1.529.2.2.1.1", slotName => ".1.3.6.1.4.1.529.2.2.1.2", ); my $indexmethod = "ifindex"; my $description = "ifdescr"; my $devicetype = "normal"; my %snmpcache = (); my $cmdoptions = ""; my $devicetypearg; ## forward declarations (prototypes) sub GetSNMPResult(%); sub usage(); sub GetSNMPArray(%); sub GetIfIndecies(); sub GetIfName($); sub GetIfDescr($); sub GetIfAlias($); sub GetWanLineName($); sub GetWanLineState($); sub GetSysDescr(); sub GetFileContents($); sub GetSNMPResult(%); sub GenSNMPCache(); sub GetIfIndexFromIfDescr($); sub PrintSNMPCache(); ## process command line options if (scalar(@ARGV) == 0) { usage(); } Getopt::Long::Configure("no_ignore_case"); my $getoptret = GetOptions( "H|hostname=s" => \$hostname, "C|community=s" => \$snmpcommunity, "p|port=i" => \$snmpport, "c|command=s" => \$cmd, "i|indexmethod=s" => \$indexmethod, "d|description=s" => \$description, "devicetype=s" => \$devicetypearg, "h|help" => \$needhelp, ); if ($getoptret == 0 || $needhelp) { usage(); } # end if no options or wants help if (!defined($hostname)) { print "Hostname not specified\n\n"; usage(); } # end if no hostname if (!defined($indexmethod) || !defined($description)) { print "Must specify index and description method\n\n"; usage(); } # end if no index or description method if ($indexmethod ne "ifindex" && $indexmethod ne "ifname" && $indexmethod ne "ifdescr" && $indexmethod ne "ifalias" && $indexmethod ne "wanlinename") { print "index method must be one of ifindex, ifname, ifdescr, ifalias, or wanlinename\n\n"; usage(); } # end if indexmethod is incorrect if ($description ne "ifindex" && $description ne "ifname" && $description ne "ifdescr" && $description ne "ifalias" && $description ne "wanlinename") { print "description must be one of ifindex, ifname, ifdescr, ifalias, or wanlinename\n\n"; usage(); } # end if indexmethod is incorrect ## see what type of device we are if (defined($devicetypearg)) { $devicetype = $devicetypearg; } # if devicetype was specified, use that else { my $sysdescr = GetSysDescr(); if ($sysdescr =~ /Max-TNT/) { $devicetype = "maxtnt"; } # end if maxtnt elsif ($sysdescr =~ /WS-C[(5\d\d\d))(2948)]/) { $devicetype = "catalyst"; } # end if device is a catalyst } # end else figure out the device type ## get the values we wanted GenSNMPCache(); exit(1) if (scalar(keys(%snmpcache)) == 0); ## setup any options we have if ($devicetype eq "catalyst") { $cmdoptions .= " --devicetype=catalyst"; $description = "ifname"; } # end if we have a catalyst elsif ($devicetype eq "maxtnt") { $cmdoptions .= " --devicetype=maxtnt"; } # end if we have a maxtnt $template = GetFileContents($templatefile); $crctemplate = GetFileContents($crctemplatefile); $servdeptemplate = GetFileContents($servdeptemplatefile); print "## Generated by $progname\n"; print "## ifNumber: ".GetSNMPResult(oid => $snmpoid{ifNumber})."\n"; print "## Uptime: ".GetSNMPResult(oid => $snmpoid{sysUptime}, translate => 0)."\n"; print "\n"; foreach my $ifIndex (keys(%snmpcache)) { if ($snmpcache{$ifIndex}{ifdescr} !~ /virtual/i && defined($snmpcache{$ifIndex}{$description})) { my $servicedef = $template; $servicedef =~ s/HOSTNAME/$hostname/; $servicedef =~ s/SERVDESCR/$snmpcache{$ifIndex}{$description}/; $servicedef =~ s/COMMAND/$cmd/; $servicedef =~ s/SNMPCOMMUNITY/$snmpcommunity/; $servicedef =~ s/OPT/-i $indexmethod -v $snmpcache{$ifIndex}{$indexmethod}$cmdoptions/; $servicedef =~ s/(notification_period\s+)24x7/$1crlsreboot/g if ($snmpcache{$ifIndex}{"ifalias"} =~ /crls/ || $hostname =~ /crls0/); $servicedef =~ s/CRCCMD/$crccmd/; $servicedef =~ s/CRCARGS/-o $snmpoid{ifInErrors}.$snmpcache{$ifIndex}{$indexmethod} -d $snmpoid{ifDescr}.$snmpcache{$ifIndex}{$indexmethod}/; print $servicedef; # do we want to monitor CRCs if ($snmpcache{$ifIndex}{ifdescr} !~ /ATM\d+/ && $snmpcache{$ifIndex}{ifdescr} !~ /Serial.*?\d+\.\d+/ && $snmpcache{$ifIndex}{ifdescr} !~ /^CPU$/ && $snmpcache{$ifIndex}{ifdescr} !~ /^VLAN/) { my $crcdef = $crctemplate; $crcdef =~ s/HOSTNAME/$hostname/; $crcdef =~ s/SERVDESCR/$snmpcache{$ifIndex}{$description}/; $crcdef =~ s/SNMPCOMMUNITY/$snmpcommunity/; $crcdef =~ s/CRCCMD/$crccmd/; $crcdef =~ s/CRCARGS/-o $snmpoid{ifInErrors}.$snmpcache{$ifIndex}{$indexmethod} -d $snmpoid{ifDescr}.$snmpcache{$ifIndex}{$indexmethod}/; print $crcdef; } # end if don't do CRCs # if ifDescr like 'ATM1/0/0.31-atm subif' or the like if ($snmpcache{$ifIndex}{ifdescr} =~ /(ATM\d+\/\d+\/\d+)\..+/) { my $servifdescr = $1; my $servifindex = GetIfIndexFromIfDescr($servifdescr); my $servdepdef = $servdeptemplate; $servdepdef =~ s/HOSTNAME/$hostname/g; $servdepdef =~ s/DEP_SERVDESC/$snmpcache{$ifIndex}{$description}/; $servdepdef =~ s/SERVDESC/$snmpcache{$servifindex}{$description}/; print $servdepdef; } # end if match atm } # end if the key isn't empty } # end foreach ifIndex we have # if this is a tnt, we need to check slots as well if ($devicetype eq "maxtnt") { print "## slots for maxtnt\n"; print "\n"; my @slots = GetSNMPArray(oid => "$snmpoid{slotIndex}"); foreach my $slotIndex (@slots) { my $slotName = GetSNMPResult(oid => "$snmpoid{slotName}.$slotIndex"); my $servicedef = $template; $servicedef =~ s/HOSTNAME/$hostname/; $servicedef =~ s/SERVDESCR/slot$slotIndex/; $servicedef =~ s/COMMAND/$cmd/; $servicedef =~ s/SNMPCOMMUNITY/$snmpcommunity/; $servicedef =~ s/OPT/-i maxtntslot -v $slotIndex$cmdoptions/; $servicedef =~ s/(notification_period\s+)24x7/$1mdmreset/ if ($slotName =~ /madd/); print $servicedef; } # end foreach slot } # end if maxtnt ## subroutines sub usage() { print < [-C|--community] [-p|--port] [-i|--indexmethod] [ifindex|ifname|ifdescr|ifAlias|wanlinename] [-d|--description] [ifindex|ifname|ifdescr|ifAlias|wanlinename] [--devicetype=normal|catalyst|maxtnt] [-h|--help] END exit(1); } # end usage; ## # GetSNMPArray(%) # # gets the array of items for an oid specified and returns it # sub GetSNMPArray(%) { my %input = @_; my $snmp_session; my $snmp_error; my $snmp_response; my @returnval; # check that we were passed an oid if (!defined($input{oid})) { return; } # end if no oid ## get the list of active users via snmp ($snmp_session, $snmp_error) = Net::SNMP->session( -hostname => $hostname, -community => $snmpcommunity, -port => $snmpport ); if (!defined($snmp_session)) { print(STDERR "ERROR: couldn't open snmp session\n"); return; } if (!defined($snmp_response = $snmp_session->get_table($input{oid}))) { $snmp_session->close; return; } foreach my $snmpkey (keys(%{$snmp_response})) { push(@returnval, $snmp_response->{$snmpkey}); } $snmp_session->close; return @returnval; } # end GetSNMPArray(); ## # GetIfIndecies() # # get all indecies for a device and return them as an array # sub GetIfIndecies() { return GetSNMPArray(oid => "$snmpoid{ifIndex}"); } # end GetIfIndecies(); ## # GetIfName($) # # gets the ifName for a specified index # sub GetIfName($) { my $ifIndex = shift(@_); return GetSNMPResult(oid => "$snmpoid{ifName}.$ifIndex"); } # end GetIfName; ## # GetIfDescr($) # # gets the ifDescr for a specified index # sub GetIfDescr($) { my $ifIndex = shift(@_); return GetSNMPResult(oid => "$snmpoid{ifDescr}.$ifIndex"); } # end GetIfDescr; ## # GetIfAlias($) # # gets the ifAlias for a specified index # sub GetIfAlias($) { my $ifIndex = shift(@_); return GetSNMPResult(oid => "$snmpoid{ifAlias}.$ifIndex"); } # end GetIfName; ## # GetWanLineName($) # # gets the WanLineName for a specified index # sub GetWanLineName($) { my $ifIndex = shift(@_); return GetSNMPResult(oid => "$snmpoid{wanLineName}.$ifIndex"); } # end GetWanLineName ## # GetWanLineState # # gets the WanLineState for the specified index and returns true if its # a real wan line # sub GetWanLineState($) { my $ifIndex = shift(@_); my $snmp_session; my $snmp_error; my $snmp_response; ## get the list of active users via snmp ($snmp_session, $snmp_error) = Net::SNMP->session( -hostname => $hostname, -community => $snmpcommunity, -port => $snmpport ); if (!defined($snmp_session)) { return(0); } if (!defined($snmp_response = $snmp_session->get_request("$snmpoid{wanLineState}.$ifIndex"))) { $snmp_session->close; return(0); } $snmp_session->close; return (1); } # end GetWanLineState; ## # GetSysDescr # # returns the system description for a device # sub GetSysDescr() { return GetSNMPResult(oid => "$snmpoid{sysDescr}"); } # end GetSysDescr; sub GetFileContents($) { my $filename = shift(@_); my $output = ""; open (F, $filename); while (my $line = ) { $output .= $line; } close(F); return $output; } # end GetFileContents; ## # GetSNMPResult(%) # # oid => oid to get/return # sub GetSNMPResult(%) { my %input = @_; my $snmp_session; my $snmp_error; my $snmp_response; # check that we were passed an oid if (!defined($input{oid})) { return; } # end if no oid ## get the list of active users via snmp ($snmp_session, $snmp_error) = Net::SNMP->session( -hostname => $hostname, -community => $snmpcommunity, -port => $snmpport ); ## if we don't want to translate if (defined($input{translate}) && !$input{translate}) { $snmp_session->translate( [-timeticks => 0x0] ); } # end if don't translate if (!defined($snmp_session)) { $snmp_session->close; return; } if (!defined($snmp_response = $snmp_session->get_request($input{oid}))) { $snmp_session->close; return; } $snmp_session->close; return $snmp_response->{$input{oid}}; } # end GetSNMPResult(); ## # GenSNMPCache() # # creates this nifty hash of ifindex and its other elements # sub GenSNMPCache() { my @snmpindecies = GetIfIndecies(); foreach my $ifIndex (@snmpindecies) { if ($devicetype eq "maxtnt") { if (GetWanLineState($ifIndex)) { $snmpcache{$ifIndex}{"ifindex"} = $ifIndex; $snmpcache{$ifIndex}{"ifname"} = GetIfName($ifIndex); $snmpcache{$ifIndex}{"ifdescr"} = GetIfDescr($ifIndex); $snmpcache{$ifIndex}{"ifalias"} = GetIfAlias($ifIndex); $snmpcache{$ifIndex}{"wanlinename"} = GetWanLineName($ifIndex); } # end if the WanLineState exists } # end if device is a maxtnt and the line exists else { $snmpcache{$ifIndex}{"ifindex"} = $ifIndex; $snmpcache{$ifIndex}{"ifname"} = GetIfName($ifIndex); $snmpcache{$ifIndex}{"ifdescr"} = GetIfDescr($ifIndex); $snmpcache{$ifIndex}{"ifalias"} = GetIfAlias($ifIndex); } } # end foreach ifIndex; } # end GenSNMPCache(); ## # GetIfIndexFromIfDescr($) # # returns the ifindex that the ifdescr belongs to # sub GetIfIndexFromIfDescr($) { my $ifDescr = shift(@_); foreach my $ifIndex (keys(%snmpcache)) { if ($snmpcache{$ifIndex}{ifdescr} eq $ifDescr) { return $ifIndex; } # end if this ifdescr matches } # end foreach ifindex return ""; } # end GetIfIndexFromIfDescr(); ## # PrintSNMPCache() # # prints out what we have cached about a device # sub PrintSNMPCache() { foreach my $ifIndex (keys(%snmpcache)) { print "ifIndex: $ifIndex\n"; print " ifIndex: ".$snmpcache{$ifIndex}{ifindex}."\n"; print " ifName : ".$snmpcache{$ifIndex}{ifname}."\n"; print " ifDescr: ".$snmpcache{$ifIndex}{ifdescr}."\n"; print " ifAlias: ".$snmpcache{$ifIndex}{ifalias}."\n"; if ($devicetype eq "maxtnt") { print " WanLineType: ".$snmpcache{$ifIndex}{wanlinetype}."\n"; } # end if device is a maxtnt } # end foreach ifindex } # end PrintSNMPCache();