diff --git a/ChangeLog b/ChangeLog index 0816ffb2..f573c905 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,8 @@ SNMP::Info - Friendly OO-style interface to Network devices using SNMP. ChangeLog $Id$ version 2.01 () + + [2020353] Added L3::Altiga for Cisco (Altiga) VPN3000 Concentrators + (Jeroen van Ingen) * Updated test_class.pl for better debug info and relative path * Add cisco vendor detection by OID in Layer3.pm (Sam Stickland) * Fix CaSe of EtherLike-MIB in EtherLike.pm (Alexander Hartmaier) diff --git a/DeviceMatrix.txt b/DeviceMatrix.txt index 4f7f80a5..fed9475d 100644 --- a/DeviceMatrix.txt +++ b/DeviceMatrix.txt @@ -91,6 +91,17 @@ note: Aironet based device device: AP350, AP340, CAP350, CAP340, 1200, AP4800 note: Aironet based device +device-family: Altiga +class: Layer3::Altiga + +device: VPN3000 +note: The Cisco 3000 device can return duplicate interface names, while +note: Netdisco expects unique interface names. To ensure unique device names, I took a different approach than +note: the Microsoft class; while the Microsoft class prepends the iid to each +note: interface, I chose to append numbers only when an interface name would +note: not be unique without one. Interfaces with unique names keer their +note: ifDescr name. + device-family: 1000 duplex: no ver: 1 diff --git a/Info.pm b/Info.pm index 2bcd9cd4..bd559cc7 100644 --- a/Info.pm +++ b/Info.pm @@ -1199,6 +1199,7 @@ sub device_type { 2272 => 'SNMP::Info::Layer3::Passport', 2636 => 'SNMP::Info::Layer3::Juniper', 2925 => 'SNMP::Info::Layer1::Cyclades', + 3076 => 'SNMP::Info::Layer3::Altiga', 5624 => 'SNMP::Info::Layer3::Enterasys', 6486 => 'SNMP::Info::Layer3::AlcatelLucent', 6527 => 'SNMP::Info::Layer3::Timetra', diff --git a/Info/Layer3/Altiga.pm b/Info/Layer3/Altiga.pm new file mode 100644 index 00000000..b416ac37 --- /dev/null +++ b/Info/Layer3/Altiga.pm @@ -0,0 +1,372 @@ +# SNMP::Info::Layer3::Altiga +# $Id$ +# +# Copyright (c) 2008 Jeroen van Ingen Schenau +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Santa Cruz nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +package SNMP::Info::Layer3::Altiga; + +use strict; +use Exporter; +use SNMP::Info::Layer3; + +@SNMP::Info::Layer3::Altiga::ISA = qw/SNMP::Info::Layer3 Exporter/; +@SNMP::Info::Layer3::Altiga::EXPORT_OK = qw//; + +use vars qw/$VERSION %GLOBALS %MIBS %FUNCS %MUNGE + $int_include_vpn $fake_idx $type_class/; + +$VERSION = '2.01'; + +%MIBS = ( + %SNMP::Info::Layer3::MIBS, + 'ALTIGA-VERSION-STATS-MIB' => 'alVersionString', + 'ALTIGA-SESSION-STATS-MIB' => 'alActiveSessionCount', + 'ALTIGA-HARDWARE-STATS-MIB' => 'alHardwarePs1Type', + ); + +%GLOBALS = ( + %SNMP::Info::Layer3::GLOBALS, + # From ALTIGA-VERSION-STATS-MIB + 'os_ver' => 'alVersionString', + # From ALTIGA-SESSION-STATS-MIB + 'vpn_act_sess' => 'alActiveSessionCount', + 'vpn_total_sess' => 'alTotalSessionCount', + 'vpn_max_sess' => 'alMaxSessionCount', + 'vpn_l2l_sess' => 'alActiveLanToLanSessionCount', + 'vpn_mgmt_sess' => 'alActiveManagementSessionCount', + 'vpn_ras_sess' => 'alActiveRemoteAccessSessionCount', + # From ALTIGA-HARDWARE-STATS-MIB + 'ps1_type' => 'alHardwarePs1Type', + 'ps1_3v_alarm' => 'alHardwarePs1Voltage3vAlarm', + 'ps1_5v_alarm' => 'alHardwarePs1Voltage5vAlarm', + 'ps2_type' => 'alHardwarePs2Type', + 'ps2_3v_alarm' => 'alHardwarePs2Voltage3vAlarm', + 'ps2_5v_alarm' => 'alHardwarePs2Voltage5vAlarm', + 'fan1_alarm' => 'alHardwareFan1RpmAlarm', + 'fan2_alarm' => 'alHardwareFan2RpmAlarm', + 'fan3_alarm' => 'alHardwareFan3RpmAlarm', + + ); + +%FUNCS = ( + %SNMP::Info::Layer3::FUNCS, + 'i_type2' => 'ifType', + 'i_lastchange2' => 'ifLastChange', + 'vpn_sess_status' => 'alActiveSessionRowStatus', + 'vpn_sess_user' => 'alActiveSessionUserName', + 'vpn_sess_peer_ip' => 'alActiveSessionIpAddress', + 'vpn_sess_protocol' => 'alActiveSessionProtocol', + 'vpn_sess_encr' => 'alActiveSessionEncrType', + 'vpn_sess_start' => 'alActiveSessionStartTime', + 'vpn_sess_conntime' => 'alActiveSessionConnectTime', + 'vpn_sess_out_oct' => 'alActiveSessionOctetsSent', + 'vpn_sess_in_oct' => 'alActiveSessionOctetsRcvd', + 'vpn_sess_group' => 'alActiveSessionGroupName', + 'vpn_sess_gid' => 'alActiveSessionGroupId', + 'vpn_sess_rem_ip' => 'alActiveSessionPublicIpAddress', + ); + +%MUNGE = ( + %SNMP::Info::Layer3::MUNGE, + 'ps1_3v_alarm' => \&munge_alarm, + 'ps1_5v_alarm' => \&munge_alarm, + 'ps2_3v_alarm' => \&munge_alarm, + 'ps2_5v_alarm' => \&munge_alarm, + 'fan1_alarm' => \&munge_alarm, + 'fan2_alarm' => \&munge_alarm, + 'fan3_alarm' => \&munge_alarm, + + ); + +# Variable to modify behaviour of "interfaces" subroutine. +# * When set to 0, "interfaces" returns only fixed interfaces from the IF-MIB, +# * When set to 1, "interfaces" returns fixed interfaces from IF-MIB and LAN-to-LAN tunnels from ALTIGA-SESSION-MIB +$int_include_vpn = 1; + +# Variable to prepended to each tunnel index when tunnel is added to %interfaces, to avoid overwriting "real" ifIndex entries +$fake_idx = 3076; + +# Variable to classify session types into categories: 0 - unclassified, 1 - LAN-to-LAN or fixed, 2 - RAS or dynamic, 3 - administrative +$type_class = { + 'pptp' => 2, + 'l2tp' => 2, + 'ipsec' => 2, + 'http' => 3, + 'ftp' => 3, + 'telnet' => 3, + 'snmp' => 3, + 'tftp' => 3, + 'console' => 3, + 'debugTelnet' => 3, + 'debugConsole' => 3, + 'other' => 3, + 'ike' => 0, + 'l2tpOverIpSec' => 2, + 'ipsecLanToLan' => 1, + 'ipsecOverUdp' => 2, + 'ssh' => 3, + 'vcaLanToLan' => 1, + 'ipsecOverTcp' => 2, + 'pppoe' => 2, + 'ipsecOverNatT' => 2, + 'ipsecLan2LanOverNatT' => 1, + 'l2tpOverIpsecOverNatT' => 2, + 'userHttps' => 2, + 'pop3s' => 2, + 'imap4s' => 2, + 'smtps' => 2, + 'httpsTunnel' => 2, +}; + +sub vendor { + return 'altiga'; +} + +sub os { + return 'altiga'; +} + +sub hasCDP { + return 0; +} + +# $l3->interfaces() - Map the Interfaces to their physical names +# Add interface number to interface name to prevent duplicate ifDescr +# Included statically configured VPN tunnels if ($int_include_vpn) +sub interfaces { + my $l3 = shift; + my $partial = shift; + + my $interfaces = $l3->i_index($partial); + my $descriptions = $l3->i_description($partial); + + my %int_rev = (); + my %interfaces = (); + foreach my $iid (sort {$a cmp $b} keys %$interfaces) { + my $desc = $descriptions->{$iid}; + next unless defined $desc; + if (!exists $int_rev{$desc}) { + $interfaces{$iid} = $desc; + $int_rev{$desc} = $iid; + } else { + my $done = 0; + my $unique_desc; + my $cnt = 1; + until ($done) { + $cnt++; + $unique_desc = sprintf("%s (%d)", $desc, $cnt); + if (!exists $int_rev{$unique_desc}) { + $done++; + } + } + $int_rev{$unique_desc} = $iid; + $interfaces{$iid} = $unique_desc; + $interfaces{ $int_rev{$desc} } = sprintf("%s (%d)", $desc, 1); + } + } + if ($int_include_vpn) { + my $tun_type = $l3->vpn_sess_protocol(); + my $peer = $l3->vpn_sess_peer_ip(); + my $remote = $l3->vpn_sess_rem_ip(); + my $group = $l3->vpn_sess_gid(); + foreach my $tunnel (keys %$tun_type) { + if ($type_class->{$tun_type->{$tunnel}} eq 1) { + $interfaces{"$fake_idx.$tunnel"} = sprintf("%s VPN to %s", uc($tun_type->{$tunnel}), $remote->{$tunnel}); + } + } + } + + return \%interfaces; +} + +sub i_type { + my $l3 = shift; + my $partial = shift; + my $types = $l3->i_type2(); + if ($int_include_vpn) { + my $tun_type = $l3->vpn_sess_protocol(); + foreach my $tunnel (keys %$tun_type) { + $types->{"$fake_idx.$tunnel"} = $tun_type->{$tunnel}; + } + } + return $types; +} + +sub i_lastchange { + my $l3 = shift; + my $partial = shift; + my $lastchange = $l3->i_lastchange2(); + if ($int_include_vpn) { + my $tun_start = $l3->vpn_sess_start(); + foreach my $tunnel (keys %$tun_start) { + $lastchange->{"$fake_idx.$tunnel"} = $tun_start->{$tunnel}; + } + } + return $lastchange; +} + +sub ps1_status { + my $l3 = shift; + my $alarm_3v = $l3->ps1_3v_alarm() || ""; + my $alarm_5v = $l3->ps1_5v_alarm() || ""; + return sprintf("3V: %s, 5V: %s", $alarm_3v, $alarm_5v); +} + +sub ps2_status { + my $l3 = shift; + my $alarm_3v = $l3->ps2_3v_alarm() || ""; + my $alarm_5v = $l3->ps2_5v_alarm() || ""; + return sprintf("3V: %s, 5V: %s", $alarm_3v, $alarm_5v); +} + +sub fan { + my $l3 = shift; + my $alarm_fan1 = $l3->fan1_alarm() || ""; + my $alarm_fan2 = $l3->fan2_alarm() || ""; + my $alarm_fan3 = $l3->fan3_alarm() || ""; + return sprintf("Fan 1: %s, Fan 2: %s, Fan 3: %s", $alarm_fan1, $alarm_fan2, $alarm_fan3); +} + +sub munge_alarm { + my $alarm = shift; + if ($alarm eq 'false') { + return 'OK'; + } elsif ($alarm eq 'true') { + return 'FAIL'; + } else { + return "(n/a)"; + } +} + +1; +__END__ + +=head1 NAME + +SNMP::Info::Layer3::Altiga - SNMP Interface to Cisco (formerly Altiga) VPN concentrators + +=head1 AUTHOR + +Jeroen van Ingen Schenau + +=head1 SYNOPSIS + + # Let SNMP::Info determine the correct subclass for you. + my $vpn = new SNMP::Info( + AutoSpecify => 1, + Debug => 1, + DestHost => 'my_vpn_host', + Community => 'public', + Version => 1 + ) + or die "Can't connect to DestHost.\n"; + + my $class = $vpn->class(); + print "SNMP::Info determined this device to fall under subclass : $class\n"; + +=head1 DESCRIPTION + +Subclass for Cisco (formerly Altiga) VPN concentrators + +=head2 Inherited Classes + +=over + +=item SNMP::Info::Layer3 + +=back + +=head2 Required MIBs + +=over + +=item Inherited Classes' MIBs + +See L for its own MIB requirements. + +=back + +=head1 Class Variables (options) + +=over + +=item $SNMP::Info::Layer3::Altiga::int_include_vpn + +Variable to modify behaviour of "interfaces" subroutine. + + * When set to 0, "interfaces" returns only fixed interfaces from the IF-MIB, + * When set to 1, "interfaces" returns fixed interfaces from IF-MIB and + LAN-to-LAN tunnels from ALTIGA-SESSION-MIB (default) + +=back + +=head1 GLOBALS + +These are methods that return scalar value from SNMP + +=over + +=item $vpn->vendor() + + Returns 'altiga' + +=item $vpn->os() + + Returns 'altiga' + +=item $vpn->os_ver() + + Tries to determine OS version from the sysDescr.0 field. Returns version or sysDescr.0 + +=back + +=head2 Globals imported from SNMP::Info::Layer3 + +See documentation in L for details. + +=head1 TABLE METHODS + +These are methods that return tables of information in the form of a reference +to a hash. + +=over + +=item $vpn->interfaces() + +This method overrides the interfaces() method inherited from SNMP::Info. +It provides a mapping between the Interface Table Index (iid) and the physical +port name, adding a port number to the port name to prevent duplicate names. + + +=back + +=head2 Table Methods imported from SNMP::Info::Layer3 + +See documentation in L for details. + +=cut diff --git a/t/make_dev_matrix.pl b/t/make_dev_matrix.pl index 1ec06aa5..94902602 100755 --- a/t/make_dev_matrix.pl +++ b/t/make_dev_matrix.pl @@ -40,6 +40,7 @@ if ($@) { $gvds->graph()->as_png($DevPNG); } +print "Creating $DevHTML\n"; open (HTML, "> $DevHTML") or die "Can't open $DevHTML. $!\n"; $old_fh = select(HTML); &html_head;