#============================================================# # # # $ID:$ # # # # NaSocket6.pm # # # # IPv4/IPv6 socket interface for ONTAPI APIs # # # # Copyright (c) 2010-2012 NetApp, Inc. All rights reserved. # # Specifications subject to change without notice. # # # # This SDK sample code is provided AS IS, with no support or # # warranties of any kind, including but not limited to # # warranties of merchantability or fitness of any kind, # # expressed or implied. This code is subject to the license # # agreement that accompanies the SDK. # # # # tab size = 8 # # # #============================================================# package NaSocket6; use strict; use warnings; use IO::Socket (); use Socket qw(AF_INET AF_INET6 AF_UNSPEC SOCK_STREAM INADDR_ANY); use Socket6 qw(getaddrinfo pack_sockaddr_in6 in6addr_any); # Look up address of hostname-or-IP-address $server_name, and # construct and return a sockaddr structure for its address and port. # Return that sockaddr structure, and also return the protocol family # (suitable for use in socket()) # In the case of this module, we use whatever address and address # family the name service returns first for $server_name, which could # be IPv4 or IPv6. # Since NaSocket6 is currently used only if NaSocket4 rejects the # address, the $server_name should be an IPv6 numeric address and so # there is pretty much only one possible outcome. If instead we were # to use this for both IPv4 and IPv6, we might also need the caller to # loop through all the possible results and try each one (to really # use these APIs the way they were intended). sub make_sockaddr { my ($pkg, $server_name, $port) = @_; my @res = getaddrinfo($server_name, $port, AF_UNSPEC, SOCK_STREAM); return undef if (@res < 5); my ($family, $socktype, $proto, $sockaddr) = @res; return ($sockaddr, $family) } # Construct and return a local sockaddr suitable for binding to local # port $port and for connecting to the remote address/port/family # specified by sockaddr structure $remote_sockaddr, which was created # using make_sockaddr, above. sub make_local_sockaddr { my ($pkg, $remote_sockaddr, $port) = @_; my ($family) = unpack('S',$remote_sockaddr); if ($family eq AF_INET6) { return pack_sockaddr_in6($port,in6addr_any); } elsif ($family eq AF_INET) { return pack('S n a4 x8',AF_INET,$port,INADDR_ANY); } return undef; } # Return a true value if the given hostname-or-IP-address is suitable # for being connected to from this module. # In the case of this module, it handles at least IPv4 or IPv6 (even # though it may only be given a chance with IPv6 numeric addresses) so # return true always. sub can_handle_address { my ($pkg, $addr) = @_; return 1; } 1;