diff --git a/perl-xCAT/xCAT/NetworkUtils.pm b/perl-xCAT/xCAT/NetworkUtils.pm new file mode 100755 index 000000000..acae340e0 --- /dev/null +++ b/perl-xCAT/xCAT/NetworkUtils.pm @@ -0,0 +1,297 @@ +#!/usr/bin/env perl +# IBM(c) 2010 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT::Utils; + +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; +} + +# if AIX - make sure we include perl 5.8.2 in INC path. +# Needed to find perl dependencies shipped in deps tarball. +if ($^O =~ /^aix/i) { + use lib "/usr/opt/perl5/lib/5.8.2/aix-thread-multi"; + use lib "/usr/opt/perl5/lib/5.8.2"; + use lib "/usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi"; + use lib "/usr/opt/perl5/lib/site_perl/5.8.2"; +} + +use lib "$::XCATROOT/lib/perl"; +use POSIX qw(ceil); +use File::Path; +use Socket; +use strict; +use warnings "all"; + +our @ISA = qw(Exporter); + +#-------------------------------------------------------------------------------- + +=head1 xCAT::NetworkUtils + +=head2 Package Description + +This program module file, is a set of network utilities used by xCAT commands. + +=cut + +#------------------------------------------------------------- + + +#------------------------------------------------------------------------------- + +=head3 gethostnameandip + Works for both IPv4 and IPv6. + Takes either a host name or an IP address string + and performs a lookup on that name, + returns an array with two elements: the hostname, the ip address + if the host name or ip address can not be resolved, + the corresponding element in the array will be undef + Arguments: + hostname or ip address + Returns: the hostname and the ip address + Globals: + + Error: + none + Example: + my ($ip, $host) = xCAT::Utils->gethostnameandip($iporhost); + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub gethostnameandip() +{ + my ($class, $iporhost) = @_; + + if (($iporhost =~ /\d+\.\d+\.\d+\.\d+/) || ($iporhost =~ /:/)) #ip address + { + return (xCAT::Utils->gethostname($iporhost), $iporhost); + } + else #hostname + { + return ($iporhost, xCAT::Utils->getipaddr($iporhost)); + } +} + +#------------------------------------------------------------------------------- + +=head3 gethostname + Works for both IPv4 and IPv6. + Takes an IP address string and performs a lookup on that name, + returns the hostname of the ip address + if the ip address can not be resolved, returns undef + Arguments: + ip address + Returns: the hostname + Globals: + cache: %::iphosthash + Error: + none + Example: + my $host = xCAT::Utils->gethostname($ip); + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub gethostname() +{ + my ($class, $iporhost) = @_; + + my $socket6support = eval { require Socket6 }; + + if (($iporhost !~ /\d+\.\d+\.\d+\.\d+/) && ($iporhost !~ /:/)) + { + #why you do so? pass in a hostname and only want a hostname?? + return $iporhost; + } + #cache, do not lookup DNS each time + if (defined($::iphosthash{$iporhost}) && $::iphosthash{$iporhost}) + { + return $::iphosthash{$iporhost}; + } + else + { + if ($socket6support) # the getaddrinfo and getnameinfo supports both IPv4 and IPv6 + { + my ($family, $socket, $protocol, $ip, $name) = getaddrinfo($iporhost,0); + my $host = (getnameinfo($ip))[0]; + if ($host eq $iporhost) # can not resolve + { + return undef; + } + if ($host) + { + $host =~ s/\..*//; #short hostname + } + return $host; + } + else + { + my $hostname = gethostbyaddr(inet_aton($iporhost), AF_INET); + $hostname =~ s/\..*//; #short hostname + return $hostname; + } + } +} + +#------------------------------------------------------------------------------- + +=head3 getipaddr + Works for both IPv4 and IPv6. + Takes a hostname string and performs a lookup on that name, + returns the the ip address of the hostname + if the hostname can not be resolved, returns undef + Arguments: + hostname + Returns: ip address + Globals: + cache: %::hostiphash + Error: + none + Example: + my $ip = xCAT::Utils->getipaddr($hostname); + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub getipaddr() +{ + my ($class, $iporhost) = @_; + + my $socket6support = eval { require Socket6 }; + + if (($iporhost =~ /\d+\.\d+\.\d+\.\d+/) || ($iporhost =~ /:/)) + { + #pass in an ip and only want an ip?? + return $iporhost; + } + + #cache, do not lookup DNS each time + if (defined($::hostiphash{$iporhost}) && $::hostiphash{$iporhost}) + { + return $::hostiphash{$iporhost}; + } + else + { + if ($socket6support) # the getaddrinfo and getnameinfo supports both IPv4 and IPv6 + { + my ($family, $socket, $protocol, $ip, $name) = getaddrinfo($iporhost,0); + if ($ip) + { + return (getnameinfo($ip, NI_NUMERICHOST()))[0]; + } + return undef; + } + else + { + return inet_ntoa(inet_aton($iporhost)) + } + } +} + +#------------------------------------------------------------------------------- + +=head3 linklocaladdr + Only for IPv6. + Takes a mac address, calculate the IPv6 link local address + Arguments: + mac address + Returns: + ipv6 link local address. returns undef if passed in a invalid mac address + Globals: + Error: + none + Example: + my $linklocaladdr = xCAT::Utils->linklocaladdr($mac); + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub linklocaladdr { + my ($class, $mac) = @_; + $mac = lc($mac); + my $localprefix = "fe80"; + + my ($m1, $m2, $m3, $m6, $m7, $m8); + # mac address can be 00215EA376B0 or 00:21:5E:A3:76:B0 + if($mac =~ /^([0-9A-Fa-f]{2}).*?([0-9A-Fa-f]{2}).*?([0-9A-Fa-f]{2}).*?([0-9A-Fa-f]{2}).*?([0-9A-Fa-f]{2}).*?([0-9A-Fa-f]{2})$/) + { + ($m1, $m2, $m3, $m6, $m7, $m8) = ($1, $2, $3, $4, $5, $6); + } + else + { + #not a valid mac address + return undef; + } + my ($m4, $m5) = ("ff","fe"); + + my $bit = (int $m1) & 2; + if ($bit) { + $m1 = $m1 - 2; + } else { + $m1 = $m1 + 2; + } + + $m1 = $m1 . $m2; + $m3 = $m3 . $m4; + $m5 = $m5 . $m6; + $m7 = $m7 . $m8; + + my $laddr = join ":", $m1, $m3, $m5, $m7; + $laddr = join "::", $localprefix, $laddr; + + return $laddr; +} + +#------------------------------------------------------------------------------- + +=head3 ishostinsubnet + Works for both IPv4 and IPv6. + Takes an ip address, the netmask and a subnet, + chcek if the ip address is in the subnet + Arguments: + ip address, netmask, subnet + Returns: + 1 - if the ip address is in the subnet + 0 - if the ip address is NOT in the subnet + Globals: + Error: + none + Example: + if(xCAT::Utils->ishostinsubnet($ip, $netmask, $subnet); + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub ishostinsubnet { + my ($class, $ip) = shift; + my $mask = shift; + my $subnet =shift; + + if ($ip =~ /\d+\.\d+\.\d+\.\d+/) {# ipv4 address + $ip =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/; + my $ipnum = ($1<<24)+($2<<16)+($3<<8)+$4; + + $mask =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/; + my $masknum = ($1<<24)+($2<<16)+($3<<8)+$4; + + $subnet =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/; + my $netnum = ($1<<24)+($2<<16)+($3<<8)+$4; + + if (($ipnum & $masknum) == $netnum) { + return 1; + } else { + return 0; + } + } else { # for ipv6 + #TODO + } +} + +1; diff --git a/perl-xCAT/xCAT/Utils.pm b/perl-xCAT/xCAT/Utils.pm index f0918d01d..e4267d119 100644 --- a/perl-xCAT/xCAT/Utils.pm +++ b/perl-xCAT/xCAT/Utils.pm @@ -1,5 +1,5 @@ #!/usr/bin/env perl -# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +# IBM(c) 2010 EPL license http://www.eclipse.org/legal/epl-v10.html package xCAT::Utils; BEGIN