diff --git a/Changes b/Changes index 4752f2c9..4e16345f 100644 --- a/Changes +++ b/Changes @@ -2,7 +2,10 @@ Version 3.61 [ENHANCEMENTS] - * #255 IPv6 support + * #255 IPv6 support - Set the transport-specifier if given an IPv6 address + * #195 IP address table - IPv4 Address Table will use the + IP-MIB::ipAddressTable if the deprecated IP-MIB::ipAddrTable doesn't + return results Version 3.60 (2018-05-06) diff --git a/lib/SNMP/Info.pm b/lib/SNMP/Info.pm index 177a809d..558359ad 100644 --- a/lib/SNMP/Info.pm +++ b/lib/SNMP/Info.pm @@ -2560,36 +2560,45 @@ See C for full description =back -=head2 IP Address Table +=head2 IPv4 Address Table -Each entry in this table is an IP address in use on this device. Usually -this is implemented in Layer3 Devices. +Each entry in this table is an IPv4 address in use on this device. Usually +this is implemented in Layer3 Devices. These methods try the deprecated IPv4 +address table C first due to its prevalence and will try +the current C if it doesn't return any results. +C results are filtered to only return IPv4 unicast +addresses and modified to match the return format of the older table for +backwards compatibility. + +See documentation in L for IPv6 Address Table. =over =item $info->ip_index() -Maps the IP Table to the IID +Maps the IPv4 addresses to the interface index -(C) +(C) or filtered and index modified (C) =item $info->ip_table() -Maps the Table to the IP address +Maps the Table to the IPv4 address -(C) +(C) or address extracted from (C) =item $info->ip_netmask() -Gives netmask setting for IP table entry. +Gives netmask setting for IPv4 table entry. -(C) +(C) or netmask calculated from (C) =item $info->ip_broadcast() -Gives broadcast address for IP table entry. +Gives the value of the least-significant bit in the IPv4 broadcast address +either 1 or 0. -(C) +(C), there is no equivalent from the +C =back @@ -2770,6 +2779,88 @@ no protocols are supported or running. =cut +sub ip_index { + my $self = shift; + + my $o_ip_idx = $self->old_ip_index(); + return $o_ip_idx + if ( ref {} eq ref $o_ip_idx and scalar keys %$o_ip_idx ); + + # Since callers may be using the old iid to get the IP, strip protocol + # and length from the index + my $n_ip_idx = $self->new_ip_index() || {}; + my $n_ip_type = $self->new_ip_type() || {}; + + my %ip_index; + foreach my $iid ( keys %$n_ip_idx ) { + next unless $n_ip_type->{$iid} and $n_ip_type->{$iid} eq 'unicast'; + my @parts = split( /\./, $iid ); + my $type = shift(@parts); + my $len = shift(@parts); + next unless ( ( $type == 1 ) and ( $len == 4 ) ); + + my $new_iid = join( ".", @parts ); + $ip_index{$new_iid} = $n_ip_idx->{$iid}; + } + return \%ip_index; +} + +sub ip_table { + my $self = shift; + + my $o_ip_table = $self->old_ip_table(); + return $o_ip_table + if ( ref {} eq ref $o_ip_table and scalar keys %$o_ip_table ); + + my $n_ip_idx = $self->new_ip_index() || {}; + my $n_ip_type = $self->new_ip_type() || {}; + + my %ip_table; + foreach my $iid ( keys %$n_ip_idx ) { + next unless $n_ip_type->{$iid} and $n_ip_type->{$iid} eq 'unicast'; + my @parts = split( /\./, $iid ); + my $type = shift(@parts); + my $len = shift(@parts); + next unless ( ( $type == 1 ) and ( $len == 4 ) ); + + my $new_iid = join( ".", @parts ); + $ip_table{$new_iid} = $new_iid; + } + return \%ip_table; +} + +sub ip_netmask { + my $self = shift; + + my $o_ip_mask = $self->old_ip_netmask(); + return $o_ip_mask + if ( ref {} eq ref $o_ip_mask and scalar keys %$o_ip_mask ); + + my $n_ip_pfx = $self->new_ip_prefix() || {}; + my $n_ip_type = $self->new_ip_type() || {}; + + my %ip_netmask; + foreach my $iid ( keys %$n_ip_pfx ) { + next unless $n_ip_type->{$iid} and $n_ip_type->{$iid} eq 'unicast'; + my @parts = split( /\./, $iid ); + my $type = shift(@parts); + my $len = shift(@parts); + next unless ( ( $type == 1 ) and ( $len == 4 ) ); + + my $prefix = $n_ip_pfx->{$iid}; + next if ( !$prefix || $prefix =~ /0\.0$/ ); + if ( $prefix =~ /\.(\d+)$/ ) { + $prefix = $1; + } + my $new_iid = join( ".", @parts ); + my $mask = NetAddr::IP::Lite->new( $new_iid . '/' . $prefix )->mask() + || undef; + + $ip_netmask{$new_iid} = $mask; + } + return \%ip_netmask; +} + sub has_topo { my $self = shift; @@ -3182,11 +3273,16 @@ ALTEON-TS-PHYSICAL-MIB::agPortCurCfgPortName. # IF-MIB::IfStackTable 'i_stack_status' => 'ifStackStatus', - # IP::MIB::ipAddrTable (deprecated IPv4 address table) - 'ip_index' => 'ipAdEntIfIndex', - 'ip_table' => 'ipAdEntAddr', - 'ip_netmask' => 'ipAdEntNetMask', - 'ip_broadcast' => 'ipAdEntBcastAddr', + # IP-MIB::ipAddrTable (deprecated IPv4 address table) + 'old_ip_index' => 'ipAdEntIfIndex', + 'old_ip_table' => 'ipAdEntAddr', + 'old_ip_netmask' => 'ipAdEntNetMask', + 'ip_broadcast' => 'ipAdEntBcastAddr', + + # IP-MIB::ipAddressTable + 'new_ip_index' => 'ipAddressIfIndex', + 'new_ip_prefix' => 'ipAddressPrefix', + 'new_ip_type' => 'ipAddressType', # IF-MIB::ifXTable - Extension Table 'i_speed_high' => 'ifHighSpeed', diff --git a/lib/SNMP/Info/Airespace.pm b/lib/SNMP/Info/Airespace.pm index 7b28312e..2a76926a 100644 --- a/lib/SNMP/Info/Airespace.pm +++ b/lib/SNMP/Info/Airespace.pm @@ -508,8 +508,8 @@ sub ip_index { my $airespace = shift; my $partial = shift; - my $ip_index = $airespace->orig_ip_index($partial) || {}; - my $if_ip = $airespace->airespace_if_ip() || {}; + my $ip_index = $airespace->SUPER::ip_index($partial) || {}; + my $if_ip = $airespace->airespace_if_ip() || {}; my %ip_index; foreach my $ip ( keys %$ip_index ) { @@ -534,9 +534,9 @@ sub ip_netmask { my $airespace = shift; my $partial = shift; - my $ip_mask = $airespace->orig_ip_netmask($partial) || {}; - my $if_ip = $airespace->airespace_if_ip() || {}; - my $if_mask = $airespace->airespace_if_mask() || {}; + my $ip_mask = $airespace->SUPER::ip_netmask($partial) || {}; + my $if_ip = $airespace->airespace_if_ip() || {}; + my $if_mask = $airespace->airespace_if_mask() || {}; my %ip_netmask; foreach my $ip ( keys %$ip_mask ) { diff --git a/lib/SNMP/Info/Layer3/Nexus.pm b/lib/SNMP/Info/Layer3/Nexus.pm index 3d531814..1128b5eb 100644 --- a/lib/SNMP/Info/Layer3/Nexus.pm +++ b/lib/SNMP/Info/Layer3/Nexus.pm @@ -143,7 +143,7 @@ sub model { # override methods in ipAddrTable sub ip_table { my $nexus = shift; - my $orig_ip_table = $nexus->orig_ip_table(); + my $orig_ip_table = $nexus->SUPER::ip_table(); my %ip_table; foreach my $iid ( keys %$orig_ip_table ) { @@ -163,8 +163,8 @@ sub ip_table { sub ip_index { my $nexus = shift; - my $orig_ip_table = $nexus->orig_ip_table(); - my $orig_ip_index = $nexus->orig_ip_index(); + my $orig_ip_table = $nexus->SUPER::ip_table(); + my $orig_ip_index = $nexus->SUPER::ip_index(); my %ip_index; foreach my $iid ( keys %$orig_ip_table ) { @@ -186,8 +186,8 @@ sub ip_index { sub ip_netmask { my $nexus = shift; - my $orig_ip_table = $nexus->orig_ip_table(); - my $orig_ip_netmask = $nexus->orig_ip_netmask(); + my $orig_ip_table = $nexus->SUPER::ip_table(); + my $orig_ip_netmask = $nexus->SUPER::ip_netmask(); my %ip_netmask; foreach my $iid ( keys %$orig_ip_table ) { @@ -209,8 +209,8 @@ sub ip_netmask { sub ip_broadcast { my $nexus = shift; - my $orig_ip_table = $nexus->orig_ip_table(); - my $orig_ip_broadcast = $nexus->orig_ip_broadcast(); + my $orig_ip_table = $nexus->SUPER::ip_table(); + my $orig_ip_broadcast = $nexus->SUPER::ip_broadcast(); my %ip_broadcast; foreach my $iid ( keys %$orig_ip_table ) { diff --git a/lib/SNMP/Info/Layer3/Passport.pm b/lib/SNMP/Info/Layer3/Passport.pm index 3e9b543a..e8b62d0d 100644 --- a/lib/SNMP/Info/Layer3/Passport.pm +++ b/lib/SNMP/Info/Layer3/Passport.pm @@ -450,7 +450,7 @@ sub ip_index { my $partial = shift; my $model = $passport->model(); - my $ip_index = $passport->orig_ip_index($partial) || {}; + my $ip_index = $passport->SUPER::ip_index($partial) || {}; my %ip_index; foreach my $ip ( keys %$ip_index ) { @@ -492,7 +492,7 @@ sub ip_netmask { my $partial = shift; my $model = $passport->model(); - my $ip_mask = $passport->orig_ip_netmask($partial) || {}; + my $ip_mask = $passport->SUPER::ip_netmask($partial) || {}; my %ip_index; foreach my $iid ( keys %$ip_mask ) { diff --git a/lib/SNMP/Info/Layer7/Netscaler.pm b/lib/SNMP/Info/Layer7/Netscaler.pm index 74217dfc..d0addb1b 100644 --- a/lib/SNMP/Info/Layer7/Netscaler.pm +++ b/lib/SNMP/Info/Layer7/Netscaler.pm @@ -55,8 +55,8 @@ $VERSION = '3.60'; %FUNCS = ( %SNMP::Info::Layer7::FUNCS, # IP Address Table - NS-ROOT-MIB::nsIpAddrTable - 'ip_index' => 'ipAddr', - 'ip_netmask' => 'ipNetmask', + 'ns_ip_index' => 'ipAddr', + 'ns_ip_netmask' => 'ipNetmask', # TODO VLAN - NS-ROOT-MIB::vlanTable 'ns_vid' =>'vlanId', 'ns_vlan_mem' => 'vlanMemberInterfaces', @@ -89,13 +89,24 @@ sub model { sub os_ver { my $ns = shift; my $ver = $ns->build_ver() || ''; - + if ($ver =~ /^.+\bNS(\d+\.\d+)/) { $ver = $1; } return $ver; } +sub ip_index { + my $ns = shift; + + return $ns->ns_ip_index(); +} + +sub ip_netmask { + my $ns = shift; + + return $ns->ns_ip_netmask(); +} 1; __END__ diff --git a/xt/lib/Test/SNMP/Info.pm b/xt/lib/Test/SNMP/Info.pm index e423ac35..eaa5e5cc 100644 --- a/xt/lib/Test/SNMP/Info.pm +++ b/xt/lib/Test/SNMP/Info.pm @@ -457,6 +457,111 @@ sub i_speed_raw : Tests(3) { $expected, 'Munges restored after i_speed_raw() call'); } +sub ip_index : Tests(4) { + my $test = shift; + + can_ok($test->{info}, 'ip_index'); + + my $cache_data = { + '_old_ip_index' => 1, + '_new_ip_index' => 1, + '_new_ip_type' => 1, + 'store' => { + 'old_ip_index' => + {'2.3.4.5' => 7, '2.2.2.2' => 11}, + 'new_ip_index' => + {'1.4.1.2.3.4' => 6, '1.4.10.255.255.255' => 8, '1.4.8.8.8.8' => 10}, + 'new_ip_type' => + {'1.4.1.2.3.4' => 'unicast', '1.4.10.255.255.255' => 'broadcast', '1.4.8.8.8.8' => 'unicast'}, + } + }; + $test->{info}->cache($cache_data); + + my $expected = {'2.3.4.5' => 7, '2.2.2.2' => 11}; + + cmp_deeply($test->{info}->ip_index(), + $expected, q(IP addresses mapped to 'ifIndex' using old 'ipAddrTable')); + + delete $test->{info}{_old_ip_index}; + $expected = {'1.2.3.4' => 6, '8.8.8.8' => 10}; + + cmp_deeply($test->{info}->ip_index(), + $expected, q(IP addresses mapped to 'ifIndex' using new 'ipAddressTable')); + + $test->{info}->clear_cache(); + cmp_deeply($test->{info}->ip_index(), {}, q(No data returns empty hash)); +} + +sub ip_table : Tests(4) { + my $test = shift; + + can_ok($test->{info}, 'ip_table'); + + my $cache_data = { + '_old_ip_table' => 1, + '_new_ip_index' => 1, + '_new_ip_type' => 1, + 'store' => { + 'old_ip_table' => + {'2.3.4.5' => '2.3.4.5', '2.2.2.2' => '2.2.2.2'}, + 'new_ip_index' => + {'1.4.1.2.3.4' => 6, '1.4.10.255.255.255' => 8, '1.4.8.8.8.8' => 10}, + 'new_ip_type' => + {'1.4.1.2.3.4' => 'unicast', '1.4.10.255.255.255' => 'broadcast', '1.4.8.8.8.8' => 'unicast'}, + } + }; + $test->{info}->cache($cache_data); + + my $expected = {'2.3.4.5' => '2.3.4.5', '2.2.2.2' => '2.2.2.2'}; + + cmp_deeply($test->{info}->ip_table(), + $expected, q(IP addresses using old 'ipAddrTable')); + + delete $test->{info}{_old_ip_table}; + $expected = {'1.2.3.4' => '1.2.3.4', '8.8.8.8' => '8.8.8.8'}; + + cmp_deeply($test->{info}->ip_table(), + $expected, q(IP addresses using new 'ipAddressTable')); + + $test->{info}->clear_cache(); + cmp_deeply($test->{info}->ip_table(), {}, q(No data returns empty hash)); +} + +sub ip_netmask : Tests(4) { + my $test = shift; + + can_ok($test->{info}, 'ip_netmask'); + + my $cache_data = { + '_old_ip_netmask' => 1, + '_new_ip_prefix' => 1, + '_new_ip_type' => 1, + 'store' => { + 'old_ip_netmask' => + {'2.3.4.5' => '255.255.255.0', '2.2.2.2' => '255.255.0.0'}, + 'new_ip_prefix' => + {'1.4.1.2.3.4' => 'IP-MIB::ipAddressPrefixOrigin.2.ipv4."1.2.3.0".24', '1.4.10.2.3.4' => '.1.3.6.1.2.1.4.32.1.5.6.1.4.10.0.0.0.8', '1.4.8.8.8.8' => '.0.0'}, + 'new_ip_type' => + {'1.4.1.2.3.4' => 'unicast', '1.4.10.2.3.4' => 'unicast', '1.4.8.8.8.8' => 'unicast'}, + } + }; + $test->{info}->cache($cache_data); + + my $expected = {'2.3.4.5' => '255.255.255.0', '2.2.2.2' => '255.255.0.0'}; + + cmp_deeply($test->{info}->ip_netmask(), + $expected, q(IP netmask using old 'ipAddrTable')); + + delete $test->{info}{_old_ip_netmask}; + $expected = {'1.2.3.4' => '255.255.255.0', '10.2.3.4' => '255.0.0.0'}; + + cmp_deeply($test->{info}->ip_netmask(), + $expected, q(IP netmask using new 'ipAddressTable')); + + $test->{info}->clear_cache(); + cmp_deeply($test->{info}->ip_netmask(), {}, q(No data returns empty hash)); +} + # Topo routines will need to be tested in sub classes for conditionals sub has_topo : Tests(2) { my $test = shift;