2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-04 12:07:56 +00:00

Merge pull request #7802 from VersatusHPC/refactor/networkutils-ip-validation

refactor(networkutils): remove the legacy validate_ip helper
This commit is contained in:
Daniel Hilst
2026-09-02 15:04:20 -03:00
committed by GitHub
19 changed files with 343 additions and 88 deletions
+2 -2
View File
@@ -139,7 +139,7 @@ sub getIPaddress
my $type = shift;
my $nodetocheck = shift;
my $port = shift;
if (xCAT::NetworkUtils::isIpaddr($nodetocheck)) {
if (xCAT::NetworkUtils::isIpv4addr($nodetocheck)) {
return $nodetocheck;
}
my $side = "[A|B]";
@@ -201,7 +201,7 @@ sub getIPaddress
if ($tmp_s and $tmp_s =~ /^$side-$port$/i) {
$tmp_s =~ s/a/A/;
$tmp_s =~ s/b/B/;
if (xCAT::NetworkUtils::isIpaddr($tmp_n)) {
if (xCAT::NetworkUtils::isIpv4addr($tmp_n)) {
$node_side_pairs{$tmp_s} = $tmp_n;
$children_num++;
} else {
+2 -2
View File
@@ -771,9 +771,9 @@ sub get_server_nodes
else{
next;
}
chomp $serv;
chomp $serv if $serv;
if (xCAT::NetworkUtils->validate_ip($serv)) {
if (xCAT::NetworkUtils->isValidIp($serv)) {
push(@{ $servernodes{$serv} }, $node);
}
}
+106 -50
View File
@@ -1687,7 +1687,7 @@ sub getNodeIPaddress
}
# Quick return if pass in an IP
return $nodetocheck if (xCAT::NetworkUtils->isIpaddr($nodetocheck));
return $nodetocheck if (xCAT::NetworkUtils->isIpv4addr($nodetocheck));
my $nodeip = xCAT::NetworkUtils->getipaddr($nodetocheck);
if (!$nodeip)
@@ -2085,54 +2085,7 @@ sub toIP
#-------------------------------------------------------------------------------
=head3 validate_ip
Validate list of IPs
Arguments:
List of IPs
Returns:
1 - Invalid IP address in the list
0 - IP addresses are all valid
Globals:
none
Error:
none
Example:
if (xCAT::NetworkUtils->validate_ip($IP)) {}
Comments:
none
=cut
#-------------------------------------------------------------------------------
sub validate_ip
{
my ($class, @IPs) = @_;
foreach (@IPs) {
my $ip = $_;
#TODO need more check for IPv6 address
if ($ip =~ /:/)
{
return ([0]);
}
###################################
# Length is 4 for IPv4 addresses
###################################
my (@octets) = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
if (scalar(@octets) != 4) {
return ([ 1, "Invalid IP address1: $ip" ]);
}
foreach my $octet (@octets) {
if (($octet < 0) or ($octet > 255)) {
return ([ 1, "Invalid IP address2: $ip" ]);
}
}
}
return ([0]);
}
#-------------------------------------------------------------------------------
=head3 isIpaddr
=head3 isIpv4addr
returns 1 if parameter is has a valid IP address form.
@@ -2154,7 +2107,7 @@ sub validate_ip
=cut
#-------------------------------------------------------------------------------
sub isIpaddr
sub isIpv4addr
{
my $addr = shift;
if (($addr) && ($addr =~ /xCAT::NetworkUtils/))
@@ -2183,6 +2136,109 @@ sub isIpaddr
}
}
#-------------------------------------------------------------------------------
=head3 isIpaddr
Deprecated alias for isIpv4addr, kept for external callers.
=cut
#-------------------------------------------------------------------------------
sub isIpaddr
{
return isIpv4addr(@_);
}
#-------------------------------------------------------------------------------
=head3 isIpv6addr
returns 1 if the value is a valid IPv6 address.
Arguments:
IPv6 address string
Returns:
1 - valid IPv6 address
0 - not a valid IPv6 address
Globals:
none
Error:
none
Example:
if (xCAT::NetworkUtils->isIpv6addr($ip)) { blah; }
Comments:
Zone identifiers such as fe80::1%eth0 are not accepted.
=cut
#-------------------------------------------------------------------------------
sub isIpv6addr
{
my $value = shift;
if (($value) && ($value =~ /xCAT::NetworkUtils/))
{
$value = shift;
}
unless (defined($value) and length($value))
{
return 0;
}
# inet_pton handling of zone identifiers is platform-dependent
if ($value =~ /%/)
{
return 0;
}
my $packed_address;
if (defined &Socket::inet_pton)
{
$packed_address = eval { Socket::inet_pton(Socket::AF_INET6(), $value) };
}
elsif (defined &Socket6::inet_pton)
{
# Perl 5.8 core Socket has no inet_pton; Socket6 provides it
$packed_address = eval { Socket6::inet_pton(Socket6::AF_INET6(), $value) };
}
return defined($packed_address) ? 1 : 0;
}
#-------------------------------------------------------------------------------
=head3 isValidIp
returns 1 if the value is a valid IPv4 or IPv6 address.
Arguments:
IP address string
Returns:
1 - valid IP address
0 - not a valid IP address
Globals:
none
Error:
none
Example:
if (xCAT::NetworkUtils->isValidIp($ip)) { blah; }
Comments:
IPv4 values follow the isIpv4addr rules.
=cut
#-------------------------------------------------------------------------------
sub isValidIp
{
my $value = shift;
if (($value) && ($value =~ /xCAT::NetworkUtils/))
{
$value = shift;
}
return (isIpv4addr($value) or isIpv6addr($value)) ? 1 : 0;
}
+1 -1
View File
@@ -520,7 +520,7 @@ sub mkhwconn
for my $nn (@newnodes)
{
my $node_ip;
unless (xCAT::NetworkUtils->isIpaddr($nn)) {
unless (xCAT::NetworkUtils->isIpv4addr($nn)) {
$node_ip = xCAT::NetworkUtils::getNodeIPaddress($nn);
} else {
$node_ip = $nn;
+3 -3
View File
@@ -1106,7 +1106,7 @@ sub get_host {
}
if ($tmpmtm eq $mtm and $tmpsn eq $sn) {
my $ifip = xCAT::NetworkUtils->isIpaddr($oldnode);
my $ifip = xCAT::NetworkUtils->isIpv4addr($oldnode);
if ($ifip) { # which means that the node is defined by the new lsslp
if ($tmpside eq $side) { # match! which means that node is the same as the new one
if ($ip eq $tmpip) { #which means that the ip is not changed
@@ -1230,7 +1230,7 @@ sub get_host {
}
# not matched, use the new name
my $ifip = xCAT::NetworkUtils->isIpaddr($nodename);
my $ifip = xCAT::NetworkUtils->isIpv4addr($nodename);
unless ($ifip) {
return $nodename;
} else {
@@ -1338,7 +1338,7 @@ sub read_from_table {
@{ $::OLD_DATA_CACHE{ $entry->{node} } }[1] = @{ $vpdhash{ $entry->{node} } }[1]; #sn
@{ $::OLD_DATA_CACHE{ $entry->{node} } }[2] = @{ $vpdhash{ $entry->{node} } }[2]; #side
# find node ip address, check node name first, then check hosts table
my $ifip = xCAT::NetworkUtils->isIpaddr($entry->{node});
my $ifip = xCAT::NetworkUtils->isIpv4addr($entry->{node});
if ($ifip)
{
@{ $::OLD_DATA_CACHE{ $entry->{node} } }[3] = $entry->{node}; #ip
+8 -5
View File
@@ -114,8 +114,7 @@ sub parse_args {
} else {
$server = xCAT::ServiceNodeUtils->getSNformattedhash($node, "xcat", "node", "primary");
foreach my $key (keys %$server) {
my $valid_ip = xCAT::NetworkUtils->validate_ip($key);
if ($valid_ip) {
unless (xCAT::NetworkUtils->isValidIp($key)) {
###################################################
# Service node is returned as hostname, Convert
# hostname to IP
@@ -224,9 +223,13 @@ sub parse_args {
if (scalar(@network) != 3) {
return (usage());
}
my $result = xCAT::NetworkUtils->validate_ip($opt{C}, $opt{G}, $opt{S});
if (@$result[0]) {
return (usage(@$result[1]));
foreach my $key (qw(C G S)) {
my $ip = $opt{$key};
# lpar_netboot accepts an all-zero gateway when no router is needed
next if $key eq 'G' and $ip eq '0.0.0.0';
next if xCAT::NetworkUtils->isValidIp($ip);
return (usage("Invalid IP address: $ip"));
}
}
} elsif ((exists($opt{S}) || exists($opt{G}) || exists($opt{C})) && !exists($opt{D})) {
-1
View File
@@ -104,7 +104,6 @@ our @EXPORT_OK = qw(genpassword runcmd3 natural_sort_cmp);
# xCAT::Utils::get_subnet_aix ====> xCAT::NetworkUtils::get_subnet_aix
# xCAT::Utils->determinehostname ====> xCAT::NetworkUtils->determinehostname
# xCAT::Utils::toIP ====> xCAT::NetworkUtils::toIP
# xCAT::Utils->validate_ip ====> xCAT::NetworkUtils->validate_ip
# xCAT::Utils->getFacingIP ====> xCAT::NetworkUtils->getFacingIP
# xCAT::Utils->isIpaddr ====> xCAT::NetworkUtils->isIpaddr
# xCAT::Utils::getNodeNetworkCfg ====> xCAT::NetworkUtils::getNodeNetworkCfg
+3 -3
View File
@@ -487,7 +487,7 @@ sub obtain_log_content {
if ($split_line[0] =~ /(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(.+)-(.+)/) {
$log_content{time_record} = "$4:$5:$6";
$log_content{time} = $self->convert_to_epoch_seconds($split_line[0]);
if (!xCAT::NetworkUtils->isIpaddr($split_line[1])) {
if (!xCAT::NetworkUtils->isIpv4addr($split_line[1])) {
my @sender_tmp = split(/\./, $split_line[1]);
$log_content{sender} = $sender_tmp[0];
} else {
@@ -515,7 +515,7 @@ sub obtain_log_content {
my $timestamp = join(" ", @split_line[ 0 .. 2 ]);
$log_content{time_record} = $split_line[2];
$log_content{time} = $self->convert_to_epoch_seconds($timestamp);
if (!xCAT::NetworkUtils->isIpaddr($split_line[3])) {
if (!xCAT::NetworkUtils->isIpv4addr($split_line[3])) {
my @sender_tmp = split(/\./, $split_line[3]);
$log_content{sender} = $sender_tmp[0];
} else {
@@ -546,7 +546,7 @@ sub obtain_log_content {
$log_content{time_record} = "$4:$5:$6";
}
$log_content{time} = $self->convert_to_epoch_seconds($split_line[3]);
if (!xCAT::NetworkUtils->isIpaddr($split_line[0])) {
if (!xCAT::NetworkUtils->isIpv4addr($split_line[0])) {
my @sender_tmp = split(/\./, $split_line[0]);
$log_content{sender} = $sender_tmp[0];
} else {
+1 -1
View File
@@ -478,7 +478,7 @@ sub do_pre_check {
exit 1;
}
if (!xCAT::NetworkUtils->isIpaddr("$masteripinsite")) {
if (!xCAT::NetworkUtils->isIpv4addr("$masteripinsite")) {
probe_utils->send_msg("stdout", "f", $msg);
probe_utils->send_msg("stdout", "d", "The value of 'master' in 'site' table isn't an IP address");
exit 1;
+2 -2
View File
@@ -401,7 +401,7 @@ sub check_site_table {
$rst = 1;
}
} else {
if (($attr eq "master") and (!xCAT::NetworkUtils->isIpaddr("$value"))) {
if (($attr eq "master") and (!xCAT::NetworkUtils->isIpv4addr("$value"))) {
my $masterip = xCAT::NetworkUtils->getipaddr("$value");
if (! defined $masterip){
push @$error_ref, "The value of 'master' in 'site' table isn't an IP address and can not be resolved to a IP address";
@@ -571,7 +571,7 @@ sub check_directory {
my $mountip;
if ($mountoutput =~ /(.+):$sitetable_ref->{$dir} on $sitetable_ref->{$dir} /) {
my $mountsource = $1;
if (xCAT::NetworkUtils->isIpaddr($mountsource)) {
if (xCAT::NetworkUtils->isIpv4addr($mountsource)) {
$mountip = $mountsource;
} else {
$mountip = xCAT::NetworkUtils->getipaddr($mountsource);
+1 -1
View File
@@ -4932,7 +4932,7 @@ sub isobjnamevalid{
$objtype="node" unless(defined $objtype and ($objtype ne ""));
if($objtype eq "node"){
#the ip address as a valid node object name is a hack for p7IH support
if(($objname !~ /^[a-zA-Z0-9-_]+$/) and !xCAT::NetworkUtils->isIpaddr($objname)){
if(($objname !~ /^[a-zA-Z0-9-_]+$/) and !xCAT::NetworkUtils->isIpv4addr($objname)){
return 0;
}
} elsif ($objtype eq "group"){
+2 -2
View File
@@ -718,7 +718,7 @@ sub mknetboot
}
my $imgsrvip;
unless($imgsrv eq '!myipfn!' or xCAT::NetworkUtils->validate_ip($imgsrv)==0){
unless ($imgsrv eq '!myipfn!' or xCAT::NetworkUtils->isValidIp($imgsrv)) {
# if imgsrv is hostname, convert it to ip address
# the host name might not be resolved inside initrd
$imgsrvip = xCAT::NetworkUtils->getipaddr($imgsrv);
@@ -728,7 +728,7 @@ sub mknetboot
}
my $xcatmasterip;
if (xCAT::NetworkUtils->validate_ip($xcatmaster)) {
unless (xCAT::NetworkUtils->isValidIp($xcatmaster)) {
# if xcatmaster is hostname, convert it to ip address
# the host name might not be resolved inside initrd
$xcatmasterip = xCAT::NetworkUtils->getipaddr($xcatmaster);
+1 -1
View File
@@ -2424,7 +2424,7 @@ sub process_request
foreach my $node (@{ $req->{node} }) {
#need to change the way of finding IP for nodes
my $ifip = xCAT::NetworkUtils->isIpaddr($node);
my $ifip = xCAT::NetworkUtils->isIpv4addr($node);
if ($ifip)
{
$ip_hash->{$node} = $node;
+4 -4
View File
@@ -297,7 +297,7 @@ sub addotherinterfaces
} else {
($itf, $ip) = split(/:/, $_);
}
if ($ip && xCAT::NetworkUtils->isIpaddr($ip))
if ($ip && xCAT::NetworkUtils->isIpv4addr($ip))
{
if ($itf =~ /^-/)
{
@@ -330,7 +330,7 @@ sub delotherinterfaces
} else {
($itf, $ip) = split(/:/, $_);
}
if ($ip && xCAT::NetworkUtils->isIpaddr($ip))
if ($ip && xCAT::NetworkUtils->isIpv4addr($ip))
{
if ($itf =~ /^-/)
{
@@ -393,7 +393,7 @@ sub add_hosts_content {
}
else
{
if (xCAT::NetworkUtils->isIpaddr($ip))
if (xCAT::NetworkUtils->isIpv4addr($ip))
{
addnode $callback, $nodename, $ip, $ref->{hostnames}, $domain;
}
@@ -632,7 +632,7 @@ sub process_request
$domain = $::XCATSITEVALS{domain};
}
if (xCAT::NetworkUtils->isIpaddr($_->{ip}))
if (xCAT::NetworkUtils->isIpv4addr($_->{ip}))
{
addnode $callback, $_->{node}, $_->{ip}, $_->{hostnames}, $domain;
}
+4 -4
View File
@@ -1359,7 +1359,7 @@ sub rspconfig_parse_address_port {
return (undef, undef, "Invalid parameter: $value");
}
return (undef, undef, "Invalid parameter: $address") if (!xCAT::NetworkUtils->isIpaddr($address));
return (undef, undef, "Invalid parameter: $address") if (!xCAT::NetworkUtils->isIpv4addr($address));
return (undef, undef, "Invalid parameter: $port") if (!rspconfig_valid_port($port) or $port == 0);
return ($address, $port, undef);
}
@@ -1678,12 +1678,12 @@ sub parse_args {
my $nodes_num = @$noderange;
return ([ 1, "Invalid parameter for option $key" ]) if (!$value and $key ne ("ntpservers"));
return ([ 1, "Invalid parameter for option $key: $value" ]) if (($key eq "netmask") and !xCAT::NetworkUtils->isIpaddr($value));
return ([ 1, "Invalid parameter for option $key: $value" ]) if (($key eq "gateway") and ($value !~ "0.0.0.0" and !xCAT::NetworkUtils->isIpaddr($value)));
return ([ 1, "Invalid parameter for option $key: $value" ]) if (($key eq "netmask") and !xCAT::NetworkUtils->isIpv4addr($value));
return ([ 1, "Invalid parameter for option $key: $value" ]) if (($key eq "gateway") and ($value !~ "0.0.0.0" and !xCAT::NetworkUtils->isIpv4addr($value)));
if ($key eq "ip") {
return ([ 1, "Can not configure more than 1 nodes' ip at the same time" ]) if ($nodes_num >= 2 and $value ne "dhcp");
if ($value ne "dhcp" ) {
if (!xCAT::NetworkUtils->isIpaddr($value)) {
if (!xCAT::NetworkUtils->isIpv4addr($value)) {
return ([ 1, "Invalid parameter for option $key: $value" ]);
} else {
$all_subcommand .= $key . ",";
+3 -3
View File
@@ -324,12 +324,12 @@ sub parse_args {
return([1, "Invalid parameter for option $key: $value"]);
}
} elsif ($key eq "netmask") {
if (!xCAT::NetworkUtils->isIpaddr($value)) {
if (!xCAT::NetworkUtils->isIpv4addr($value)) {
return ([ 1, "Invalid parameter for option $key: $value" ]);
}
$set_net_info{"netmask"} = 1;
} elsif ($key eq "gateway") {
if ($value ne "0.0.0.0" and !xCAT::NetworkUtils->isIpaddr($value)) {
if ($value ne "0.0.0.0" and !xCAT::NetworkUtils->isIpv4addr($value)) {
return ([ 1, "Invalid parameter for option $key: $value" ]);
}
$set_net_info{"gateway"} = 1;
@@ -339,7 +339,7 @@ sub parse_args {
if ($value ne "dhcp") {
if (@$noderange > 1) {
return ([ 1, "Can not configure more than 1 nodes' ip at the same time" ]);
} elsif (!xCAT::NetworkUtils->isIpaddr($value)) {
} elsif (!xCAT::NetworkUtils->isIpv4addr($value)) {
return ([ 1, "Invalid parameter for option $key: $value" ]);
}
$set_net_info{"ip"} = 1;
@@ -1354,7 +1354,7 @@ Usage:
if (exists $allips{ $args_dict{'ip'} }) {
setrsp_errormsg("The specified IP address $args_dict{'ip'} already exists in the IP address database. You must use a different IP address.");
return;
} elsif ((xCAT::NetworkUtils->validate_ip($args_dict{'ip'}))[0]->[0]) {
} elsif (!xCAT::NetworkUtils->isValidIp($args_dict{'ip'})) {
setrsp_errormsg("The specified IP address $args_dict{'ip'} is invalid. You must use a valid IP address.");
return;
}
@@ -2597,7 +2597,7 @@ sub validate_node_entry {
} elsif ($_ eq "ip") {
if (exists $allips{ $node_entry{$_} }) {
$errmsg .= "IP address $node_entry{$_} already exists in the database or in the node information file.\n";
} elsif ((xCAT::NetworkUtils->validate_ip($node_entry{$_}))[0]->[0]) {
} elsif (!xCAT::NetworkUtils->isValidIp($node_entry{$_})) {
$errmsg .= "IP address $node_entry{$_} is invalid. You must use a valid IP address.\n";
} else {
@@ -2747,7 +2747,7 @@ sub validate_node_entry {
$nic_ip = $nic_and_ips[1];
if (exists $allips{$nic_ip}) {
$errmsg .= "IP address $nic_ip already exists in the database or in the node information file.\n";
} elsif ((xCAT::NetworkUtils->validate_ip($nic_ip))[0]->[0]) {
} elsif (!xCAT::NetworkUtils->isValidIp($nic_ip)) {
$errmsg .= "IP address $nic_ip is invalid. You must use a valid IP address.\n";
} else {
+112
View File
@@ -0,0 +1,112 @@
#!/usr/bin/env perl
use strict;
use warnings;
use File::Spec;
use FindBin;
use Test::More;
my $repo_root = $ENV{XCAT_REPO_ROOT}
|| File::Spec->catdir( $FindBin::Bin, '..', '..' );
unshift @INC, File::Spec->catdir( $repo_root, 'perl-xCAT' );
require xCAT::NetworkUtils;
subtest 'isIpv4addr accepts host addresses' => sub {
my @accepted = qw(10.0.0.1 192.168.0.1 172.16.254.10 255.255.255.255);
foreach my $address (@accepted) {
ok( xCAT::NetworkUtils->isIpv4addr($address), "$address is accepted" );
}
ok( xCAT::NetworkUtils::isIpv4addr('10.0.0.1'),
'the function form works without a class argument' );
ok( xCAT::NetworkUtils->isIpaddr('10.0.0.1'),
'the deprecated isIpaddr alias still answers' );
ok( !xCAT::NetworkUtils->isIpaddr('fe80::1'),
'the alias keeps the strict IPv4 contract' );
};
subtest 'isIpv4addr rejects invalid or ambiguous forms' => sub {
my @rejected = (
[ '192.168.001.010', 'leading-zero octets are octal to some resolvers' ],
[ '0.1.2.3', 'a host address cannot start with zero' ],
[ '0.0.0.0', 'all-zero is a call-site policy, not a host address' ],
[ '256.1.1.1', 'octet above 255' ],
[ '1.2.3', 'three-part form' ],
[ '1.2.3.4.5', 'five-part form' ],
[ 'fe80::1', 'IPv6 is outside the IPv4 contract' ],
[ 'bmc.example.test', 'hostnames are not addresses' ],
[ '', 'empty value' ],
);
foreach my $case (@rejected) {
my ( $value, $reason ) = @{$case};
ok( !xCAT::NetworkUtils->isIpv4addr($value), "'$value' is rejected: $reason" );
}
ok( !xCAT::NetworkUtils->isIpv4addr(undef), 'undef is rejected' );
};
subtest 'isIpv6addr validates IPv6 syntax' => sub {
my @accepted = ( 'fe80::1', '::1', '::', '2001:db8::1', '::ffff:10.1.1.1' );
foreach my $address (@accepted) {
ok( xCAT::NetworkUtils->isIpv6addr($address), "$address is accepted" );
}
my @rejected = (
[ 'not:an:ip', 'colon text is not an address' ],
[ ':::::', 'malformed compression' ],
[ 'fe80::zzzz', 'invalid hex digits' ],
[ 'fe80::1%eth0', 'zone identifiers are platform-dependent and rejected' ],
[ '10.0.0.1', 'IPv4 is outside the IPv6 contract' ],
[ '', 'empty value' ],
);
foreach my $case (@rejected) {
my ( $value, $reason ) = @{$case};
ok( !xCAT::NetworkUtils->isIpv6addr($value), "'$value' is rejected: $reason" );
}
ok( !xCAT::NetworkUtils->isIpv6addr(undef), 'undef is rejected' );
ok( xCAT::NetworkUtils::isIpv6addr('::1'),
'the function form works without a class argument' );
};
sub socket6_fallback_ok {
ok( !defined &Socket::inet_pton, 'core inet_pton is absent' );
ok( xCAT::NetworkUtils->isIpv6addr('2001:db8::1'),
'a valid IPv6 address is accepted through Socket6' );
ok( !xCAT::NetworkUtils->isIpv6addr('fe80::zzzz'),
'an invalid IPv6 address is still rejected through Socket6' );
return;
}
subtest 'isIpv6addr falls back to Socket6 without core inet_pton' => sub {
no warnings qw(once redefine);
if ( defined &Socket6::inet_pton ) {
local *Socket::inet_pton;
socket6_fallback_ok();
return;
}
plan skip_all => 'neither core inet_pton nor Socket6 is available'
unless defined &Socket::inet_pton;
# lend the core implementation to Socket6 so the fallback path runs
# where Socket6 is not installed
my $core_pton = \&Socket::inet_pton;
my $af6 = Socket::AF_INET6();
local *Socket6::inet_pton = sub { return $core_pton->(@_) };
local *Socket6::AF_INET6 = sub { return $af6 };
local *Socket::inet_pton;
socket6_fallback_ok();
};
subtest 'isValidIp accepts both families and nothing else' => sub {
ok( xCAT::NetworkUtils->isValidIp('10.0.0.1'), 'IPv4 delegates to isIpv4addr' );
ok( xCAT::NetworkUtils->isValidIp('fe80::1'), 'IPv6 delegates to isIpv6addr' );
my @rejected = (
'not:an:ip', 'fe80::1%eth0', '192.168.001.010', '0.0.0.0',
'bmc.example.test', '',
);
foreach my $value (@rejected) {
ok( !xCAT::NetworkUtils->isValidIp($value), "'$value' is rejected" );
}
ok( !xCAT::NetworkUtils->isValidIp(undef), 'undef is rejected' );
ok( xCAT::NetworkUtils::isValidIp('10.0.0.1'),
'the function form works without a class argument' );
};
done_testing();
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env perl
use strict;
use warnings;
use File::Spec;
use FindBin;
use Test::More;
my $repo_root = $ENV{XCAT_REPO_ROOT}
|| File::Spec->catdir( $FindBin::Bin, '..', '..' );
unshift @INC, File::Spec->catdir( $repo_root, 'perl-xCAT' );
# parse_args never opens the database, so keep the table layer and the
# driver out of the test
BEGIN {
package xCAT::Table;
sub import { }
sub new { return bless {}, shift; }
$INC{'xCAT/Table.pm'} = 1;
$INC{'DBI.pm'} = 1;
}
require xCAT::PPCmac;
# xcatd loads the usage table before it dispatches a plugin
require xCAT::Usage;
# both endpoints resolve through the networks table; one subnet is enough
# to reach the address checks
no warnings qw(once redefine);
local *xCAT::DBobjUtils::getNetwkInfo = sub {
my ( $class, $endpoints ) = @_;
return map { $_ => { net => '192.0.2.0', gateway => '192.0.2.1' } }
@{$endpoints};
};
sub parse {
my (@args) = @_;
my $request = { command => 'getmacs', node => ['lpar1'], arg => \@args };
return xCAT::PPCmac::parse_args($request);
}
sub rejection {
my ($result) = @_;
return ref($result) eq 'ARRAY' ? $result->[0] : undef;
}
subtest 'valid addresses reach the ping options' => sub {
my $result = parse(qw(-D -S 192.0.2.10 -G 192.0.2.1 -C 192.0.2.20));
is( ref $result, 'HASH', 'IPv4 endpoints are accepted' );
is_deeply(
[ @{$result}{qw(C G S)} ],
[qw(192.0.2.20 192.0.2.1 192.0.2.10)],
'the addresses are kept as given'
);
$result = parse(qw(-D -S 2001:db8::10 -G 2001:db8::1 -C 2001:db8::20));
is( ref $result, 'HASH', 'IPv6 endpoints are accepted' );
};
subtest 'only the gateway may be all zeros' => sub {
my $result = parse(qw(-D -S 192.0.2.10 -G 0.0.0.0 -C 192.0.2.20));
is( ref $result, 'HASH', 'an all-zero gateway is accepted' );
is( $result->{G}, '0.0.0.0', 'the gateway is passed through' );
is( rejection( parse(qw(-D -S 0.0.0.0 -G 192.0.2.1 -C 192.0.2.20)) ),
'Invalid IP address: 0.0.0.0', 'an all-zero server is rejected' );
is( rejection( parse(qw(-D -S 0.0.0.0 -G 0.0.0.0 -C 192.0.2.20)) ),
'Invalid IP address: 0.0.0.0',
'an all-zero server is rejected even when the gateway is all zeros' );
is( rejection( parse(qw(-D -S 192.0.2.10 -G 0.0.0.0 -C 0.0.0.0)) ),
'Invalid IP address: 0.0.0.0',
'an all-zero client is rejected even when the gateway is all zeros' );
};
subtest 'malformed addresses are rejected' => sub {
is( rejection( parse(qw(-D -S 192.0.2.10 -G 192.0.2.1 -C 192.168.001.010)) ),
'Invalid IP address: 192.168.001.010',
'leading-zero octets are rejected' );
is( rejection( parse(qw(-D -S 192.0.2.10 -G 192.0.2.1 -C 999.1.1.1)) ),
'Invalid IP address: 999.1.1.1', 'an octet above 255 is rejected' );
is( rejection( parse(qw(-D -S not:an:ip -G 192.0.2.1 -C 192.0.2.20)) ),
'Invalid IP address: not:an:ip', 'colon text is not an address' );
};
done_testing();