File Coverage

blib/lib/Net/SNMP/Mixin/InetCidrRouteTable.pm
Criterion Covered Total %
statement 67 169 39.6
branch 12 40 30.0
condition 3 28 10.7
subroutine 19 21 90.4
pod 1 1 100.0
total 102 259 39.3


line stmt bran cond sub pod time code
1             package Net::SNMP::Mixin::InetCidrRouteTable;
2              
3 4     4   379085 use strict;
  4         12  
  4         116  
4 4     4   22 use warnings;
  4         21  
  4         140  
5              
6             #
7             # store this package name in a handy variable,
8             # used for unambiguous prefix of mixin attributes
9             # storage in object hash
10             #
11             my $prefix = __PACKAGE__;
12              
13             #
14             # this module import config
15             #
16 4     4   23 use Carp ();
  4         14  
  4         97  
17 4     4   959 use Net::SNMP qw(oid_lex_sort);
  4         78762  
  4         457  
18 4     4   680 use Net::SNMP::Mixin::Util qw/idx2val push_error get_init_slot/;
  4         12807  
  4         34  
19 4     4   3613 use Socket qw(inet_ntop AF_INET AF_INET6);
  4         11026  
  4         591  
20              
21             #
22             # this module export config
23             #
24             my @mixin_methods;
25              
26             BEGIN {
27 4     4   153 @mixin_methods = (qw/ get_inet_cidr_route_table /);
28             }
29              
30 4         42 use Sub::Exporter -setup => {
31             exports => [@mixin_methods],
32             groups => { default => [@mixin_methods], },
33 4     4   34 };
  4         8  
34              
35             =head1 NAME
36              
37             Net::SNMP::Mixin::InetCidrRouteTable - mixin class for the inetCidrRouteTable
38              
39             =head1 VERSION
40              
41             Version 0.03
42              
43             =cut
44              
45             our $VERSION = '0.03';
46              
47             =head1 SYNOPSIS
48              
49             use Net::SNMP;
50             use Net::SNMP::Mixin;
51              
52             #...
53              
54             my $session = Net::SNMP->session( -hostname => 'foo.bar.com' );
55              
56             $session->mixer('Net::SNMP::Mixin::InetCidrRouteTable');
57             $session->init_mixins;
58             snmp_dispatcher();
59             $session->init_ok();
60             die $session->errors if $session->errors;
61              
62             my @routes = $session->get_inet_cidr_route_table();
63              
64             foreach my $route (@routes) {
65             my $prefix = $route->{inetCidrRoutePrefix};
66             my $next_hop = $route->{inetCidrRouteNextHop};
67             my $if_index = $route->{inetCidrRouteIfIndex};
68             # ...
69              
70             print "$prefix => $if_index/$next_hop\n";
71             }
72              
73             =head1 DESCRIPTION
74              
75             A Net::SNMP mixin class for inetCidrRouteTable.
76              
77             The inetCidrRouteTable provides the ability to display IP version-independent multipath CIDR routes.
78              
79             =cut
80              
81             #
82             # SNMP oid constants used in this module
83             #
84             # from IP Forwarding Table MIB, RFC 2096
85             #
86             use constant {
87 4         2697 INET_CIDR_ROUTE_TABLE => '1.3.6.1.2.1.4.24.7',
88             INET_CIDR_ROUTE_ENTRY => '1.3.6.1.2.1.4.24.7.1',
89              
90             INET_CIDR_ROUTE_DEST_TYPE => '1.3.6.1.2.1.4.24.7.1.1', # index, InetAddressType
91             INET_CIDR_ROUTE_DEST => '1.3.6.1.2.1.4.24.7.1.2', # index, InetAddress
92             INET_CIDR_ROUTE_PFXLEN => '1.3.6.1.2.1.4.24.7.1.3', # index, InetAddressPrefixLength
93             INET_CIDR_ROUTE_POLICY => '1.3.6.1.2.1.4.24.7.1.4', # index, OID
94             INET_CIDR_ROUTE_NEXTHOP_TYPE => '1.3.6.1.2.1.4.24.7.1.5', # index, InetAddressType
95             INET_CIDR_ROUTE_NEXTHOP => '1.3.6.1.2.1.4.24.7.1.6', # index, InetAddress
96             INET_CIDR_ROUTE_IFINDEX => '1.3.6.1.2.1.4.24.7.1.7',
97             INET_CIDR_ROUTE_TYPE => '1.3.6.1.2.1.4.24.7.1.8',
98             INET_CIDR_ROUTE_PROTO => '1.3.6.1.2.1.4.24.7.1.9',
99             INET_CIDR_ROUTE_AGE => '1.3.6.1.2.1.4.24.7.1.10',
100             INET_CIDR_ROUTE_NEXTHOPAS => '1.3.6.1.2.1.4.24.7.1.11',
101             INET_CIDR_ROUTE_METRIC1 => '1.3.6.1.2.1.4.24.7.1.12',
102             INET_CIDR_ROUTE_METRIC2 => '1.3.6.1.2.1.4.24.7.1.13',
103             INET_CIDR_ROUTE_METRIC3 => '1.3.6.1.2.1.4.24.7.1.14',
104             INET_CIDR_ROUTE_METRIC4 => '1.3.6.1.2.1.4.24.7.1.15',
105             INET_CIDR_ROUTE_METRIC5 => '1.3.6.1.2.1.4.24.7.1.16',
106             INET_CIDR_ROUTE_STATUS => '1.3.6.1.2.1.4.24.7.1.17',
107 4     4   2160 };
  4         10  
108              
109             #
110             # the InetAddressType enum
111             #
112             my %address_type_enum = (
113             0 => 'unknown',
114             1 => 'ipv4',
115             2 => 'ipv6',
116             3 => 'ipv4z',
117             4 => 'ipv6z',
118             16 => 'dns16',
119             );
120              
121             #
122             # the inetCidrRouteType enum
123             #
124             my %route_type_enum = (
125             1 => 'other',
126             2 => 'reject',
127             3 => 'local',
128             4 => 'remote',
129             5 => 'blackhole',
130             );
131              
132             #
133             # the inetCidrRouteProto enum
134             #
135             my %proto_enum = (
136             1 => 'other',
137             2 => 'local',
138             3 => 'netmgmt',
139             4 => 'icmp',
140             5 => 'egp',
141             6 => 'ggp',
142             7 => 'hello',
143             8 => 'rip',
144             9 => 'is-is',
145             10 => 'es-is',
146             11 => 'ciscoIgrp',
147             12 => 'bbnSpfIgp',
148             13 => 'ospf',
149             14 => 'bgp',
150             15 => 'idpr',
151             16 => 'ciscoEigrp',
152             17 => 'DVMR',
153             18 => 'RPL',
154             19 => 'DHCP',
155             20 => 'TTDP',
156             );
157              
158             #
159             # the inetCidrRouteStatus enum
160             #
161             my %status_enum = (
162             1 => 'active',
163             2 => 'notInService',
164             3 => 'notReady',
165             4 => 'createAndGo',
166             5 => 'createAndWait',
167             6 => 'destroy',
168             );
169              
170             =head1 MIXIN METHODS
171              
172             =head2 B<< OBJ->get_inet_cidr_route_table() >>
173              
174             Returns a sorted list of inetCidrRouteTable and cooked entries. Every list element (route entry) is a hashref with the following fields and values:
175              
176             {
177             inetCidrRoutePrefix => CIDR String,
178             inetCidrRouteZone => InetAddress,
179             inetCidrRouteNextHop => InetAddress,
180             inetCidrRoutePolicy => OBJECT IDENTIFIER,
181             inetCidrRouteIfIndex => InterfaceIndexOrZero,
182             inetCidrRouteType => INTEGER,
183             inetCidrRouteTypeString => String, # resolved enum
184             inetCidrRouteProto => IANAipRouteProtocol,
185             inetCidrRouteProtoString => String, # resolved enum
186             inetCidrRouteAge => Gauge32,
187             inetCidrRouteNextHopAS => InetAutonomousSystemNumber,
188             inetCidrRouteMetric1 => Integer32,
189             inetCidrRouteMetric2 => Integer32,
190             inetCidrRouteMetric3 => Integer32,
191             inetCidrRouteMetric4 => Integer32,
192             inetCidrRouteMetric5 => Integer32,
193             inetCidrRouteStatus => RowStatus
194             inetCidrRouteStatusString => String, # resolved enum
195             }
196              
197             =cut
198              
199             sub get_inet_cidr_route_table {
200 1     1 1 24784 my $session = shift;
201 1         6 my $agent = $session->hostname;
202              
203 1 50       9 Carp::croak "$agent: '$prefix' not initialized,"
204             unless $session->init_ok($prefix);
205              
206             # stash for return values
207 0         0 my @route_tbl;
208              
209             my (
210 0         0 $inetCidrRoutePrefix, $inetCidrRouteZone, $inetCidrRouteNextHop, $inetCidrRoutePolicy,
211             $inetCidrRouteIfIndex, $inetCidrRouteType, $inetCidrRouteTypeString, $inetCidrRouteProto,
212             $inetCidrRouteProtoString, $inetCidrRouteAge, $inetCidrRouteNextHopAS, $inetCidrRouteMetric1,
213             $inetCidrRouteMetric2, $inetCidrRouteMetric3, $inetCidrRouteMetric4, $inetCidrRouteMetric5,
214             $inetCidrRouteStatus, $inetCidrRouteStatusString,
215             );
216              
217             #
218             # inetCidrRouteIfIndex is used for table index walk
219 0         0 foreach my $idx ( oid_lex_sort keys %{ $session->{$prefix}{inetCidrRouteIfIndex} } ) {
  0         0  
220              
221 0   0     0 $inetCidrRoutePrefix = $session->{$prefix}{inetCidrRoutePrefix}{$idx} // '';
222 0   0     0 $inetCidrRouteZone = $session->{$prefix}{inetCidrRouteZone}{$idx} // '';
223 0   0     0 $inetCidrRouteNextHop = $session->{$prefix}{inetCidrRouteNextHop}{$idx} // '';
224 0   0     0 $inetCidrRoutePolicy = $session->{$prefix}{inetCidrRoutePolicy}{$idx} // '';
225 0   0     0 $inetCidrRouteIfIndex = $session->{$prefix}{inetCidrRouteIfIndex}{$idx} // 0;
226 0   0     0 $inetCidrRouteType = $session->{$prefix}{inetCidrRouteType}{$idx} // -1;
227 0   0     0 $inetCidrRouteTypeString = $route_type_enum{$inetCidrRouteType} // 'unknown';
228 0   0     0 $inetCidrRouteProto = $session->{$prefix}{inetCidrRouteProto}{$idx} // -1;
229 0   0     0 $inetCidrRouteProtoString = $proto_enum{$inetCidrRouteProto} // 'unknown';
230 0         0 $inetCidrRouteAge = $session->{$prefix}{inetCidrRouteAge}{$idx};
231 0         0 $inetCidrRouteNextHopAS = $session->{$prefix}{inetCidrRouteNextHopAS}{$idx};
232 0         0 $inetCidrRouteMetric1 = $session->{$prefix}{inetCidrRouteMetric1}{$idx};
233 0         0 $inetCidrRouteMetric2 = $session->{$prefix}{inetCidrRouteMetric2}{$idx};
234 0         0 $inetCidrRouteMetric3 = $session->{$prefix}{inetCidrRouteMetric3}{$idx};
235 0         0 $inetCidrRouteMetric4 = $session->{$prefix}{inetCidrRouteMetric4}{$idx};
236 0         0 $inetCidrRouteMetric5 = $session->{$prefix}{inetCidrRouteMetric5}{$idx};
237 0   0     0 $inetCidrRouteStatus = $session->{$prefix}{inetCidrRouteStatus}{$idx} // -1;
238 0   0     0 $inetCidrRouteStatusString = $status_enum{$inetCidrRouteStatus} // 'unknown';
239              
240 0         0 push @route_tbl, {
241             inetCidrRoutePrefix => $inetCidrRoutePrefix,
242             inetCidrRouteZone => $inetCidrRouteZone,
243             inetCidrRouteNextHop => $inetCidrRouteNextHop,
244             inetCidrRoutePolicy => $inetCidrRoutePolicy,
245             inetCidrRouteIfIndex => $inetCidrRouteIfIndex,
246             inetCidrRouteType => $inetCidrRouteType,
247             inetCidrRouteTypeString => $inetCidrRouteTypeString,
248             inetCidrRouteProto => $inetCidrRouteProto,
249             inetCidrRouteProtoString => $inetCidrRouteProtoString,
250             inetCidrRouteAge => $inetCidrRouteAge,
251             inetCidrRouteNextHopAS => $inetCidrRouteNextHopAS,
252             inetCidrRouteMetric1 => $inetCidrRouteMetric1,
253             inetCidrRouteMetric2 => $inetCidrRouteMetric2,
254             inetCidrRouteMetric3 => $inetCidrRouteMetric3,
255             inetCidrRouteMetric4 => $inetCidrRouteMetric4,
256             inetCidrRouteMetric5 => $inetCidrRouteMetric5,
257             inetCidrRouteStatus => $inetCidrRouteStatus,
258             inetCidrRouteStatusString => $inetCidrRouteStatusString,
259              
260             };
261             }
262              
263 0         0 return @route_tbl;
264             }
265              
266             =head1 INITIALIZATION
267              
268             =head2 B<< OBJ->_init($reload) >>
269              
270             Fetch the inetCidrRouteTable from the host. Don't call this method direct!
271              
272             =cut
273              
274             #
275             # due to the asynchron nature, we don't know what init job is really the last, we decrement
276             # the value after each callback
277             #
278 4     4   34 use constant THIS_INIT_JOBS => 1;
  4         11  
  4         3496  
279              
280             sub _init {
281 4     4   9475 my ( $session, $reload ) = @_;
282 4         14 my $agent = $session->hostname;
283              
284             die "$agent: $prefix already initialized and reload not forced.\n"
285             if exists get_init_slot($session)->{$prefix}
286 4 50 66     43 && get_init_slot($session)->{$prefix} == 0
      33        
287             && not $reload;
288              
289             # set number of async init jobs for proper initialization
290 4         118 get_init_slot($session)->{$prefix} = THIS_INIT_JOBS;
291              
292             # populate the object with needed mib values
293             #
294             # initialize the object for inetCidrRouteTable infos
295 4         46 _fetch_inet_cidr_route_tbl($session);
296 4 100       24 return if $session->error;
297              
298 2         16 return 1;
299             }
300              
301             =head1 PRIVATE METHODS
302              
303             Only for developers or maintainers.
304              
305             =head2 B<< _fetch_inet_cidr_route_tbl($session) >>
306              
307             Fetch the inetCidrRouteTable once during object initialization.
308              
309             =cut
310              
311             sub _fetch_inet_cidr_route_tbl {
312 4     4   10 my $session = shift;
313 4         7 my $result;
314              
315             # fetch the inetCidrRouteTable
316 4 100       25 $result = $session->get_table(
317             -baseoid => INET_CIDR_ROUTE_TABLE,
318              
319             # define callback if in nonblocking mode
320             $session->nonblocking ? ( -callback => \&_inet_cidr_route_tbl_cb ) : (),
321              
322             );
323              
324 4 100       2010583 unless ( defined $result ) {
325 2 50       20 if ( my $err_msg = $session->error ) {
326 2         41 push_error( $session, "$prefix: $err_msg" );
327             }
328 2         129 return;
329             }
330              
331             # in nonblocking mode the callback will be called asynchronously
332 2 50       26 return 1 if $session->nonblocking;
333              
334             # ok we are in synchronous mode, call the result mangling function
335             # by hand
336 0         0 _inet_cidr_route_tbl_cb($session);
337              
338             }
339              
340             =head2 B<< _inet_cidr_route_tbl_cb($session) >>
341              
342             The callback for _fetch_inet_cidr_route_tbl().
343              
344             =cut
345              
346             sub _inet_cidr_route_tbl_cb {
347 2     2   2005500 my $session = shift;
348 2         9 my $vbl = $session->var_bind_list;
349              
350 2 50       22 unless ( defined $vbl ) {
351 2 50       11 if ( my $err_msg = $session->error ) {
352 2         33 push_error( $session, "$prefix: $err_msg" );
353             }
354 2         85 return;
355             }
356              
357             # build parallel hashes, keys are the very complex table index,
358             # index OIDs are not extra populated with valus,
359             #
360             # INET_CIDR_ROUTE_DEST_TYPE => '1.3.6.1.2.1.4.24.7.1.1', # index, InetAddressType
361             # INET_CIDR_ROUTE_DEST => '1.3.6.1.2.1.4.24.7.1.2', # index, InetAddress
362             # INET_CIDR_ROUTE_PFXLEN => '1.3.6.1.2.1.4.24.7.1.3', # index, InetAddressPrefixLength
363             # INET_CIDR_ROUTE_POLICY => '1.3.6.1.2.1.4.24.7.1.4', # index, OID
364             # INET_CIDR_ROUTE_NEXTHOP_TYPE => '1.3.6.1.2.1.4.24.7.1.5', # index, InetAddressType
365             # INET_CIDR_ROUTE_NEXTHOP => '1.3.6.1.2.1.4.24.7.1.6', # index, InetAddress
366             #
367             # split the index for these values in get_inet_cidr_route_table()
368             #
369              
370             $session->{$prefix}{inetCidrRouteIfIndex} =
371 0           idx2val( $vbl, INET_CIDR_ROUTE_IFINDEX, undef, undef, );
372              
373             $session->{$prefix}{inetCidrRouteType} =
374 0           idx2val( $vbl, INET_CIDR_ROUTE_TYPE, undef, undef, );
375              
376             $session->{$prefix}{inetCidrRouteProto} =
377 0           idx2val( $vbl, INET_CIDR_ROUTE_PROTO, undef, undef, );
378              
379             $session->{$prefix}{inetCidrRouteAge} =
380 0           idx2val( $vbl, INET_CIDR_ROUTE_AGE, undef, undef, );
381              
382             $session->{$prefix}{inetCidrRouteNextHopAS} =
383 0           idx2val( $vbl, INET_CIDR_ROUTE_NEXTHOPAS, undef, undef, );
384              
385             $session->{$prefix}{inetCidrRouteMetric1} =
386 0           idx2val( $vbl, INET_CIDR_ROUTE_METRIC1, undef, undef, );
387              
388             $session->{$prefix}{inetCidrRouteMetric2} =
389 0           idx2val( $vbl, INET_CIDR_ROUTE_METRIC2, undef, undef, );
390              
391             $session->{$prefix}{inetCidrRouteMetric3} =
392 0           idx2val( $vbl, INET_CIDR_ROUTE_METRIC3, undef, undef, );
393              
394             $session->{$prefix}{inetCidrRouteMetric4} =
395 0           idx2val( $vbl, INET_CIDR_ROUTE_METRIC4, undef, undef, );
396              
397             $session->{$prefix}{inetCidrRouteMetric5} =
398 0           idx2val( $vbl, INET_CIDR_ROUTE_METRIC5, undef, undef, );
399              
400             $session->{$prefix}{inetCidrRouteStatus} =
401 0           idx2val( $vbl, INET_CIDR_ROUTE_STATUS, undef, undef, );
402              
403 0           foreach my $idx ( keys %{ $session->{$prefix}{inetCidrRouteIfIndex} } ) {
  0            
404              
405             #
406             # split the index for these values to get the values for prefix, next_hop and policy
407             #
408 0           my ( $rt_prefix, $zone, $next_hop, $policy ) = _split_idx( $session, $idx );
409              
410 0           $session->{$prefix}{inetCidrRoutePrefix}{$idx} = $rt_prefix;
411 0           $session->{$prefix}{inetCidrRouteZone}{$idx} = $zone;
412 0           $session->{$prefix}{inetCidrRouteNextHop}{$idx} = $next_hop;
413 0           $session->{$prefix}{inetCidrRoutePolicy}{$idx} = $policy;
414             }
415              
416             # this init job is finished
417 0           get_init_slot($session)->{$prefix}--;
418              
419 0           return 1;
420             }
421              
422             # type IPv4
423             # | len in bytes
424             # | | IP address destination, var len
425             # | | | Pfxlen destination
426             # | | | | OID, policy, var len
427             # | | | | | type
428             # | | | | | | len in bytes
429             # | | | | | | | IP address next hop, var len
430             # | | | | | | | |
431             # 1.4.10.96.2.0.24.2.0.0.1.4.134.60.112.246
432              
433             # type IPv6
434             # | len in bytes
435             # | | IP address destination, var len
436             # | | | Pfxlen destination
437             # | | | | OID, policy, var len
438             # | | | | | type
439             # | | | | | | len in bytes
440             # | | | | | | | IP address next hop, var len
441             # | | | | | | | |
442             # 2.16.32.1.7.192.0.3.161.11.0.0.0.0.0.0.0.0.127.2.0.0.2.16.254.128.0.0.0.0.0.0.78.119.109.255.254.212.255.135
443              
444             # type IPv6z
445             # | len in bytes
446             # | | IP address destination, var len
447             # | | | Pfxlen destination
448             # | | | | OID, policy, var len
449             # | | | | | type
450             # | | | | | | len in bytes
451             # | | | | | | |
452             # | | | | | | |
453             # 4.20.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.0.18.0.0.1.10.2.0.0.0.0
454              
455             sub _split_idx {
456 0     0     my ( $session, $idx ) = @_;
457              
458 0           my @subs = split( /\./, $idx );
459              
460 0           my ( $t1, $t2, $dest, $nh, $pfx_len, $policy, $size );
461              
462 0           $t1 = shift @subs;
463 0           $size = shift @subs;
464 0           $dest = pack( 'C*', @subs[ 0 .. $size - 1 ] );
465              
466 0           @subs = @subs[ $size .. $#subs ];
467              
468 0           $pfx_len = shift @subs;
469 0           $size = shift @subs;
470 0           $policy = join( '.', @subs[ 0 .. $size - 1 ] );
471              
472 0           @subs = @subs[ $size .. $#subs ];
473              
474 0           $t2 = shift @subs;
475 0           $size = shift @subs;
476 0           $nh = pack( 'C*', @subs[ 0 .. $size - 1 ] );
477              
478 0           my ( $rt_prefix, $zone, $next_hop );
479              
480 0           ( $rt_prefix, $zone ) = _get_addr( $session, $idx, $t1, $dest );
481 0 0         $rt_prefix = "$rt_prefix/$pfx_len" if defined $rt_prefix;
482              
483 0           ( $next_hop, undef ) = _get_addr( $session, $idx, $t2, $nh );
484              
485 0           return ( $rt_prefix, $zone, $next_hop, $policy );
486             }
487              
488             sub _get_addr {
489 0     0     my ( $session, $idx, $type, $n_bytes ) = @_;
490              
491 0 0         if ( $address_type_enum{$type} eq 'unknown' ) {
492 4     4   48 my $len = do { use bytes; length($n_bytes) };
  4         9  
  4         35  
  0            
  0            
493 0 0         push_error( $session, "$prefix: address-type and -value mismatch in '$idx'" )
494             if $len != 0;
495 0           return;
496             }
497              
498 0 0         if ( $address_type_enum{$type} eq 'ipv4' ) {
499 4     4   373 my $len = do { use bytes; length($n_bytes) };
  4         11  
  4         22  
  0            
  0            
500 0 0         push_error( $session, "$prefix: address-type and -value mismatch in '$idx'" )
501             if $len != 4;
502              
503 0           my $ip_addr = inet_ntop( AF_INET, $n_bytes );
504 0           return $ip_addr;
505             }
506              
507 0 0         if ( $address_type_enum{$type} eq 'ipv6' ) {
508 4     4   440 my $len = do { use bytes; length($n_bytes) };
  4         9  
  4         48  
  0            
  0            
509 0 0         push_error( $session, "$prefix: address-type and -value mismatch in '$idx'" )
510             if $len != 16;
511              
512 0           my $ip_addr = inet_ntop( AF_INET6, $n_bytes );
513 0           return $ip_addr;
514             }
515              
516             # addrs with zones suffix
517 0 0         if ( $address_type_enum{$type} eq 'ipv4z' ) {
518 4     4   428 my $len = do { use bytes; length($n_bytes) };
  4         12  
  4         16  
  0            
  0            
519 0 0         push_error( $session, "$prefix: address-type and -value mismatch in '$idx'" )
520             if $len != 8;
521              
522 0           my $ip_n = substr( $n_bytes, 0, 4 );
523 0           my $zone_n = substr( $n_bytes, 4, 4 );
524              
525 0           my $ip_addr = inet_ntop( AF_INET, $ip_n );
526 0           my $zone = inet_ntop( AF_INET, $zone_n );
527              
528 0           return ( $ip_addr, $zone );
529             }
530              
531 0 0         if ( $address_type_enum{$type} eq 'ipv6z' ) {
532 4     4   513 my $len = do { use bytes; length($n_bytes) };
  4         10  
  4         19  
  0            
  0            
533 0 0         push_error( $session, "$prefix: address-type and -value mismatch in '$idx'" )
534             if $len != 20;
535              
536 0           my $ip_n = substr( $n_bytes, 0, 16 );
537 0           my $zone_n = substr( $n_bytes, 16, 4 );
538              
539 0           my $ip_addr = inet_ntop( AF_INET6, $ip_n );
540 0           my $zone = inet_ntop( AF_INET, $zone_n );
541              
542 0           return ( $ip_addr, $zone );
543             }
544              
545 0           push_error( $session, "$prefix: unknown address-type '$type' in '$idx'" );
546 0           return;
547             }
548              
549             unless ( caller() ) {
550             print "$prefix compiles and initializes successful.\n";
551             }
552              
553             =head1 SEE ALSO
554              
555             L<< Net::SNMP::Mixin >>
556              
557             =head1 REQUIREMENTS
558              
559             L<< Net::SNMP >>, L<< Net::SNMP::Mixin >>
560              
561             =head1 BUGS, PATCHES & FIXES
562              
563             There are no known bugs at the time of this release. However, if you spot a bug or are experiencing difficulties that are not explained within the POD documentation, please submit a bug to the RT system (see link below). However, it would help greatly if you are able to pinpoint problems or even supply a patch.
564              
565             Fixes are dependant upon their severity and my availablity. Should a fix not be forthcoming, please feel free to (politely) remind me by sending an email to gaissmai@cpan.org .
566              
567             RT: http://rt.cpan.org/Public/Dist/Display.html?Name=Net-SNMP-Mixin-InetCidrRouteTable
568              
569              
570             =head1 AUTHOR
571              
572             Karl Gaissmaier
573              
574             =head1 COPYRIGHT & LICENSE
575              
576             Copyright 2019 Karl Gaissmaier, all rights reserved.
577              
578             This program is free software; you can redistribute it and/or modify it
579             under the same terms as Perl itself.
580              
581             =cut
582              
583             1;
584              
585             # vim: sw=2