diff --git a/lib/SNMP_Session.pm b/lib/SNMP_Session.pm index 9d643ac..2e0b163 100644 --- a/lib/SNMP_Session.pm +++ b/lib/SNMP_Session.pm @@ -136,13 +136,19 @@ my $dont_wait_flags; BEGIN { $ipv6_addr_len = undef; $SNMP_Session::ipv6available = 0; + $SNMP_Session::old_ipv6_networking = 0; $dont_wait_flags = 0; - if (eval {local $SIG{__DIE__};require Socket6;} && + if (eval {local $SIG{__DIE__};Socket->VERSION("2.000");}) { + Socket->import(qw(inet_pton inet_ntop getaddrinfo unpack_sockaddr_in6)); + $ipv6_addr_len = length(pack_sockaddr_in6(161, inet_pton(AF_INET6(), "::1"))); + $SNMP_Session::ipv6available = 1; + } elsif (eval {local $SIG{__DIE__};require Socket6;} && eval {local $SIG{__DIE__};require IO::Socket::INET6; IO::Socket::INET6->VERSION("1.26");}) { - Socket6->import(qw(inet_pton inet_ntop getaddrinfo)); - $ipv6_addr_len = length(Socket6::pack_sockaddr_in6(161, inet_pton(AF_INET6(), "::1"))); + Socket6->import(qw(inet_pton inet_ntop getaddrinfo unpack_sockaddr_in6)); + $ipv6_addr_len = length(pack_sockaddr_in6(161, inet_pton(AF_INET6(), "::1"))); $SNMP_Session::ipv6available = 1; + $SNMP_Session::old_ipv6_networking = 1; } eval 'local $SIG{__DIE__};local $SIG{__WARN__};$dont_wait_flags = MSG_DONTWAIT();'; } @@ -684,11 +690,8 @@ sub pretty_address { my($addr) = shift; my($port, $addrunpack, $addrstr); - # Disable strict subs to stop old versions of perl from - # complaining about AF_INET6 when Socket6 is not available - if( (defined $ipv6_addr_len) && (length $addr == $ipv6_addr_len)) { - ($port,$addrunpack) = Socket6::unpack_sockaddr_in6 ($addr); + ($port,$addrunpack) = unpack_sockaddr_in6 ($addr); $addrstr = inet_ntop (AF_INET6(), $addrunpack); } else { ($port,$addrunpack) = unpack_sockaddr_in ($addr); @@ -774,7 +777,7 @@ sub receive_trap ($ ) { my ($iaddr, $port, $af); if ((defined $ipv6_addr_len) && (length $remote_addr == $ipv6_addr_len)) { - ($port, $iaddr) = Socket6::unpack_sockaddr_in6 ($remote_addr); + ($port, $iaddr) = unpack_sockaddr_in6 ($remote_addr); $af = AF_INET6; } else { ($port, $iaddr) = unpack_sockaddr_in ($remote_addr); @@ -849,8 +852,16 @@ use Carp; BEGIN { if($SNMP_Session::ipv6available) { - import IO::Socket::INET6; - Socket6->import(qw(inet_pton inet_ntop getaddrinfo)); + if (! $SNMP_Session::old_ipv6_networking + && eval{local $SIG{__DIE__}; require IO::Socket::IP; IO::Socket::IP->VERSION('0.25');}) { + + import IO::Socket::IP; + Socket->import(qw(inet_pton inet_ntop getaddrinfo)); + } elsif (eval{local $SIG{__DIE__}; require IO::Socket::INET6;}) { + import IO::Socket::INET6; + Socket6->import(qw(inet_pton inet_ntop getaddrinfo)); + $SNMP_Session::old_ipv6_networking = 1; + } } } @@ -902,7 +913,7 @@ sub open { $local_hostname,$ipv4only) = @_; my($remote_addr,$socket,$sockfamily); - $ipv4only = 1 unless defined $ipv4only; + $ipv4only = 1 if defined $ipv4only; $sockfamily = AF_INET; $community = 'public' unless defined $community; @@ -940,11 +951,22 @@ sub open { $remote_hostname = $1; } my (@res, $socktype_tmp, $proto_tmp, $canonname_tmp); - @res = getaddrinfo($remote_hostname, $port, AF_UNSPEC, SOCK_DGRAM); - ($sockfamily, $socktype_tmp, $proto_tmp, $remote_addr, $canonname_tmp) = @res; - if (scalar(@res) < 5) { - return $this->error_return ("can't resolve \"$remote_hostname\" to IPv6 address"); - } + if ($SNMP_Session::old_ipv6_networking) { + @res = getaddrinfo($remote_hostname, $port, AF_UNSPEC, SOCK_DGRAM); + ($sockfamily, $socktype_tmp, $proto_tmp, $remote_addr, $canonname_tmp) = @res; + if (scalar(@res) < 5) { + return $this->error_return ("can't resolve \"$remote_hostname\" to IPv6 address"); + } + } else { + my ($err, $result) = getaddrinfo($remote_hostname, $port, + {'family' => AF_UNSPEC, 'socktype' => SOCK_DGRAM}); + ($sockfamily, $socktype_tmp, $proto_tmp, $remote_addr, $canonname_tmp) + = ($result->{'family'}, $result->{'socktype'}, $result->{'protocol'}, + $result->{'addr'}, $result->{'canonname'}); + if ($err) { + return $this->error_return ("can't resolve \"$remote_hostname\" to IPv6 address"); + } + } } else { $sockfamily = AF_INET6; } @@ -958,12 +980,20 @@ sub open { LocalPort => $local_port) || return $this->error_return ("creating socket: $!"); } else { - $socket = IO::Socket::INET6->new(Domain => AF_INET6, - Proto => 17, - Type => SOCK_DGRAM, - LocalAddr => $local_hostname, - LocalPort => $local_port) - || return $this->error_return ("creating socket: $!"); + my %net_setting = ( + Domain => AF_INET6, + Proto => 17, + Type => SOCK_DGRAM, + LocalAddr => $local_hostname, + LocalPort => $local_port, + ); + if ($SNMP_Session::old_ipv6_networking) { + $socket = IO::Socket::INET6->new(%net_setting) + || return $this->error_return ("creating socket: $!"); + } else { + $socket = IO::Socket::IP->new(%net_setting) + || return $this->error_return ("creating socket: $!"); + } $the_socket{$sockfamily} = $socket if $SNMP_Session::recycle_socket; } @@ -1125,8 +1155,8 @@ sub sa_equal_p ($$$) { ($p2,$a2) = unpack_sockaddr_in ($sa2); } elsif($this->{'sockfamily'} == AF_INET6()) { # IPv6 addresses - ($p1,$a1) = Socket6::unpack_sockaddr_in6 ($sa1); - ($p2,$a2) = Socket6::unpack_sockaddr_in6 ($sa2); + ($p1,$a1) = unpack_sockaddr_in6 ($sa1); + ($p2,$a2) = unpack_sockaddr_in6 ($sa2); } else { return 0; }