[pve-devel] [PATCH 11/18] improve ip address normalization

Alexandre Derumier aderumier at odiso.com
Tue Jul 15 09:58:09 CEST 2014


iptables and ipset use short ipv6 notation,
we need to normalize them

Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 src/PVE/Firewall.pm |   31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 25d4d50..2ac9c4e 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -17,6 +17,7 @@ use IO::File;
 use Net::IP;
 use PVE::Tools qw(run_command lock_file dir_glob_foreach);
 use Encode;
+use Socket qw(AF_INET6 inet_ntop inet_pton);
 
 my $hostfw_conf_filename = "/etc/pve/local/host.fw";
 my $pvefw_conf_dir = "/etc/pve/firewall";
@@ -2216,10 +2217,11 @@ sub parse_alias {
 
     if ($line =~ m/^(\S+)\s(\S+)$/) {
 	my ($name, $cidr) = ($1, $2);
-	$cidr =~ s|/32$||;
-	$cidr =~ s|/128$||;
-	pve_verify_ipv4_or_cidr($cidr);
+
+	$cidr = ip_normalize($cidr);
 	my $ipversion = get_ip_version($cidr);
+
+	pve_verify_ipv4_or_cidr($cidr);
 	my $data = {
 	    name => $name,
 	    cidr => $cidr,
@@ -2375,7 +2377,7 @@ sub generic_fw_config_parser {
 		if ($cidr =~ m/^${ip_alias_pattern}$/) {
 		    resolve_alias($cluster_conf, $res, $cidr); # make sure alias exists
 		} else {
-		    $cidr =~ s|/32$||;
+		    $cidr = ip_normalize($cidr);
 		    pve_verify_ipv4_or_cidr_or_alias($cidr);
 		}
 	    };
@@ -2735,7 +2737,7 @@ sub generate_ipset {
 		$cidr = resolve_alias($clusterfw_conf, $fw_conf, $entry->{cidr}) 
 	    }
 	    my $ipversion = get_ip_version($cidr);
-	    $cidr = compress_ipv6(lc($cidr));
+	    $cidr = ip_normalize($cidr);
 
 	    $nethash->{$ipversion}->{$cidr} = { cidr => $cidr, nomatch => $entry->{nomatch} };
 	};
@@ -3357,17 +3359,18 @@ sub update {
     run_locked($code);
 }
 
-# Replace longest run of null blocks with a double colon
-sub compress_ipv6 {
+sub ip_normalize {
     my $ip = shift;
-    if (my @runs = $ip =~ /((?:(?:^|:)(?:0000))+:?)/g ) {
-        my $max = $runs[0];
-        for (@runs[1..$#runs]) {
-            $max = $_ if length($max) < length;
-        }
-        $ip =~ s/$max/::/;
+
+    #http://backreference.org/2013/03/01/ipv6-address-normalization/
+    my $ipv6 = inet_pton(AF_INET6, lc($ip));
+    if (defined($ipv6)) {
+	$ip = inet_ntop(AF_INET6, $ipv6);
+        $ip =~ s|/128$||;
+    } else {
+        $ip =~ s|/32$||;
     }
-    $ip =~ s/:0{1,3}/:/g;
     return $ip;
 }
+
 1;
-- 
1.7.10.4



More information about the pve-devel mailing list