]> git.proxmox.com Git - pve-common.git/commitdiff
inotify/interfaces: ensure cidr, address and netmask are set correctly
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Fri, 13 Mar 2020 10:14:55 +0000 (11:14 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Fri, 13 Mar 2020 10:35:52 +0000 (11:35 +0100)
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 <t.lamprecht@proxmox.com>
src/PVE/INotify.pm
test/etc_network_interfaces/t.list-interfaces.pl

index 86543566fddc0a36d597b13b7e7389812354fb33..ae9e5e2777040f60aaf4bcc072c021a60efb5004 100644 (file)
@@ -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) = @_;
 
index ff44fd159bd74f86d091e55ed882827cee57932c..f8f414ece1cded62f56112eaebc950a1f7bc60ed 100644 (file)
@@ -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',
     },
 );