From fa6e6946569c0e6730a1c9acbc459911ae5c544f Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Fri, 13 Mar 2020 11:14:55 +0100 Subject: [PATCH] inotify/interfaces: ensure cidr, address and netmask are set correctly This should bring back compatibillity in the read site and one for all clears that cidr is cidr, netmask is mask and address is address (outgoing). We're still very flexible on what can be written out. Signed-off-by: Thomas Lamprecht --- src/PVE/INotify.pm | 62 +++++++++++++++---- .../t.list-interfaces.pl | 12 +++- 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/PVE/INotify.pm b/src/PVE/INotify.pm index 8654356..ae9e5e2 100644 --- a/src/PVE/INotify.pm +++ b/src/PVE/INotify.pm @@ -1109,23 +1109,34 @@ sub __read_etc_network_interfaces { } # map address and netmask to cidr - if ($d->{address}) { - if ($d->{netmask}) { - if ($d->{netmask} =~ m/^\d+$/) { # e.g. netmask 20 - $d->{address} = $d->{address} . "/" . $d->{netmask}; - } elsif (my $mask = PVE::JSONSchema::get_netmask_bits($d->{netmask})) { - $d->{address} = $d->{address} . "/" . $mask; - } + if (my $addr = $d->{address}) { + if (_address_is_cidr($addr)) { + $d->{cidr} = $addr; + my ($baseaddr, $mask) = _cidr_split($addr); + $d->{address} = $baseaddr; + $d->{netmask} = $mask; + } elsif (my $cidr = _get_cidr($d->{address}, $d->{netmask})) { + $d->{cidr} = $cidr; + (undef, $d->{netmask}) = _cidr_split($cidr); + } else { + # no mask, else we'd got a cidr above + $d->{cidr} = $addr ."/32"; } - # for api compatibility - $d->{cidr} = $d->{address}; } # map address6 and netmask6 to cidr6 - if ($d->{address6}) { - $d->{address6} .= "/" . $d->{netmask6} if $d->{address6} !~ m!^(.*)/(\d+)$! && $d->{netmask6}; - # for api compatibility - $d->{cidr6} = $d->{address6}; + if (my $addr6 = $d->{address6}) { + if (_address_is_cidr($addr6)) { + $d->{cidr6} = $addr6; + my ($baseaddr, $mask) = _cidr_split($addr6); + $d->{address6} = $baseaddr; + $d->{netmask6} = $mask; + } elsif (my $cidr6 = _get_cidr($d->{address6}, $d->{netmask6})) { + $d->{cidr6} = $cidr6; + } else { + # no mask, else we'd got a cidr above + $d->{cidr6} = $addr6 ."/128"; + } } $d->{method} = 'manual' if !$d->{method}; @@ -1163,6 +1174,31 @@ sub __read_etc_network_interfaces { return $config; } +sub _address_is_cidr { + my ($addr) = @_; + return $addr =~ /\/\d+$/ ? 1 : 0; +} + +sub _cidr_split { + my ($cidr) = @_; + $cidr =~ /^(.+)\/(\d+)$/; + return ($1, $2); # (address, mask) +} + +sub _get_cidr { + my ($addr, $mask) = @_; + + return $addr if _address_is_cidr($addr); + return undef if !$mask; + + if ($mask =~ m/^\d+$/) { # cidr notation + return $addr . "/" . $mask; + } elsif (my $cidrmask = PVE::JSONSchema::get_netmask_bits($mask)) { + return $addr . "/" . $cidrmask; + } + return undef; +} + sub __interface_to_string { my ($iface, $d, $family, $first_block, $ifupdown2) = @_; diff --git a/test/etc_network_interfaces/t.list-interfaces.pl b/test/etc_network_interfaces/t.list-interfaces.pl index ff44fd1..f8f414e 100644 --- a/test/etc_network_interfaces/t.list-interfaces.pl +++ b/test/etc_network_interfaces/t.list-interfaces.pl @@ -17,12 +17,18 @@ eth100: my %wanted = ( vmbr0 => { - address => '192.168.1.2/24', + address => '192.168.1.2', + netmask => '24', + cidr => '192.168.1.2/24', gateway => '192.168.1.1', - address6 => 'fc05::1:1/112', + address6 => 'fc05::1:1', + netmask6 => '112', + cidr6 => 'fc05::1:1/112', }, vmbr1 => { - address => '10.0.0.5/24', + address => '10.0.0.5', + netmask => '24', + cidr => '10.0.0.5/24', }, );