# # Copyright (c) 2001-2012 NetApp, Inc., All Rights Reserved # Any use, modification, or distribution is prohibited # without prior written consent from NetApp, Inc. # ## @summary IPv6 related utility methods ## @author dl-nacl-dev@netapp.com ## @status shared ## @pod here package NACL::Util::IPv6; =head1 NAME NACL::Util::IPv6 =head1 DESCRIPTION C is a collection of utility methods related to IPv6. These methods are not specific to any particular NACL layer and can be used outside of NACL code as well. =cut use strict; use warnings; use NATE::Log qw(log_global); my $Log = log_global(); my $may_enter = $Log->may_enter(); my $may_exit = $Log->may_exit(); use Params::Validate qw(validate_with SCALAR); use NATE::Exceptions::Argument qw(); BEGIN { use Exporter qw(import); our @EXPORT_OK = qw(convert_ipv6_address_format handle_proto); } =head1 METHODS =head2 convert_ipv6_address_format use NACL::Util::IPv6 qw(convert_ipv6_address_format); ... my $ipv6_address = NACL::Util::IPv6 ->convert_ipv6_address_format( ipv6_address => $address, client_type => 'Linux', # other values are Windows, Solaris compress_ip => 1, # default is 0 ); This routine converts an IPv6 address to different format depending on the client_type parameter. Below are the formats 1. For Windows client, ip6-literal-net format will be used ( Eg. fd20-8b1e-b255-8332--33.ipv6-literal.net ) 2. For Linux and Solaris client, bracketed format will be used ( Eg. [fd20:8b1e:b255:8332::33] ) This routine also compresses an IPv6 address depending on the input parameter compress_ip and returns compressed and converted address. =over =item Options =over =item C<< ipv6_address => $address >> (Required) IPv6 address. =item C<< client_type => $client_type >> (Required) Client type (Windows, Linux or Solaris), based on which an IPv6 address will be converted. =item C<< compress_ip => 0 | 1 >> (Optional, default is 0) Compress an IPv6 address. For Example: fd20:8b1e:b255:814e:0000:0000:0000:0001 -> fd20:8b1e:b255:814e::1 =back =back =cut sub convert_ipv6_address_format { $Log->enter() if $may_enter; my %opts = validate_with( params => \@_, spec => { ipv6_address => { type => SCALAR, callbacks => { "Specify valid IPv6 address" => sub { return Net::IP::ip_is_ipv6( $_[0] ); } } }, client_type => { type => SCALAR, }, compress_ip => { type => SCALAR, optional => 1 } } ); my $ipv6_address = $opts{ipv6_address}; if ( $opts{compress_ip} ) { $ipv6_address = Net::IP::ip_compress_address( $ipv6_address, 'IPv6' ); } if ( $opts{client_type} =~ m[Windows]i ) { $ipv6_address =~ s/\:/\-/g; $ipv6_address .= ".ipv6-literal.net"; } elsif ( $opts{client_type} =~ m[Linux|Solaris]i ) { if ( $ipv6_address !~ m/\[/ ) { $ipv6_address = "[" . $ipv6_address . "]"; } if ( $ipv6_address !~ m['] ) { $ipv6_address = "'" . $ipv6_address . "'"; } } else { $Log->exit() if $may_exit; NATE::Exceptions::Argument->throw( "IPv6 address format conversion " . "is not supported for client type $opts{client_type}" ); } $Log->exit() if $may_exit; return $ipv6_address; } ## end sub convert_ipv6_address_format =head2 handle_proto use NACL::Util::IPv6 qw(convert_ipv6_address_format); ... my $ipv6_address = NACL::Util::IPv6 ->handle_proto( is_ipv6 => "true", proto => "tcp" ); This routine converts the proto value based on the parameter is_ipv6. If is_ipv6 is "true", replace udp/tcp with udp6/tcp6 and vice versa, if the is_ipv6 value passed "false". =over =item Options =over =item C<< is_ipv6 => "true|false" >> (Required) Should be passed "true" if "proto" is for ipv6; else "false". =item C<< proto => $proto >> (Required) "proto" (tcp/udp or tcp6/udp6) which needs to be converted, based on IPv6 or IPv4. =back =back =cut sub handle_proto { $Log->enter() if $may_enter; my %opts = validate_with( params => \@_, spec => { is_ipv6 => { regex => qr/^(true|false)$/ }, proto => { type => SCALAR, }, } ); my $proto = $opts{'proto'}; if ( $opts{'is_ipv6'} eq "true" ) { if ( $proto =~ /^(udp|tcp)\d?$/i ) { $proto = $1 . '6'; } } else { if ( $proto =~ /^(udp|tcp)/ ) { $proto = $1; } } $Log->exit() if $may_exit; return $proto; } 1;