You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ya...@apache.org on 2013/02/06 02:41:59 UTC

git commit: refs/heads/network-refactor - IPv6: CLOUDSTACK-1153: Fix integer overflow on IPv6 address calcuation

Updated Branches:
  refs/heads/network-refactor ec206d69b -> 95e63bc1c


IPv6: CLOUDSTACK-1153: Fix integer overflow on IPv6 address calcuation

Use BigInteger, which is 128 bits long.


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/95e63bc1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/95e63bc1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/95e63bc1

Branch: refs/heads/network-refactor
Commit: 95e63bc1cfe36a451d317a88ed8125d2bdcea864
Parents: ec206d6
Author: Sheng Yang <sh...@citrix.com>
Authored: Tue Feb 5 17:32:40 2013 -0800
Committer: Sheng Yang <sh...@citrix.com>
Committed: Tue Feb 5 17:32:40 2013 -0800

----------------------------------------------------------------------
 server/src/com/cloud/network/NetworkModelImpl.java |    6 +-
 utils/src/com/cloud/utils/net/NetUtils.java        |   50 ++++++++++-----
 utils/test/com/cloud/utils/net/NetUtilsTest.java   |   19 ++++--
 3 files changed, 52 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/95e63bc1/server/src/com/cloud/network/NetworkModelImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java
index f682a06..70debc0 100644
--- a/server/src/com/cloud/network/NetworkModelImpl.java
+++ b/server/src/com/cloud/network/NetworkModelImpl.java
@@ -17,6 +17,7 @@
 
 package com.cloud.network;
 
+import java.math.BigInteger;
 import java.security.InvalidParameterException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -550,8 +551,9 @@ public class NetworkModelImpl  implements NetworkModel, Manager{
     	}
     	Vlan vlan = getVlanForNetwork(network.getId());
     	long existedCount = _ipv6Dao.countExistedIpsInNetwork(network.getId());
-    	long rangeCount = NetUtils.countIp6InRange(vlan.getIp6Range());
-		return (existedCount < rangeCount);
+    	BigInteger existedInt = BigInteger.valueOf(existedCount);
+    	BigInteger rangeInt = NetUtils.countIp6InRange(vlan.getIp6Range());
+		return (existedInt.compareTo(rangeInt) < 0);
 	}
 
 	@Override

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/95e63bc1/utils/src/com/cloud/utils/net/NetUtils.java
----------------------------------------------------------------------
diff --git a/utils/src/com/cloud/utils/net/NetUtils.java b/utils/src/com/cloud/utils/net/NetUtils.java
index 2772ce4..b941a41 100755
--- a/utils/src/com/cloud/utils/net/NetUtils.java
+++ b/utils/src/com/cloud/utils/net/NetUtils.java
@@ -20,6 +20,7 @@ import java.io.BufferedReader;
 import java.io.File;
 import java.io.InputStreamReader;
 import java.lang.reflect.Array;
+import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.InterfaceAddress;
 import java.net.NetworkInterface;
@@ -1175,19 +1176,25 @@ public class NetUtils {
 		return network.getNetmask().asPrefixLength();
 	}
 
-	//FIXME: only able to cover lower 32 bits
+	// Can cover 127 bits
 	public static String getIp6FromRange(String ip6Range) {
     	String[] ips = ip6Range.split("-");
     	String startIp = ips[0];
     	IPv6Address start = IPv6Address.fromString(startIp);
-    	// Find a random number based on lower 32 bits
-    	long gap = countIp6InRange(ip6Range);
-    	if (gap > Integer.MAX_VALUE) {
-    		gap = Integer.MAX_VALUE;
+    	BigInteger gap = countIp6InRange(ip6Range);
+    	BigInteger next = new BigInteger(gap.bitLength(), _rand);
+    	while (next.compareTo(gap) >= 0) {
+    		next = new BigInteger(gap.bitLength(), _rand);
     	}
-    	int next = _rand.nextInt((int)(gap));
-    	// And a number based on the difference of lower 32 bits
-    	IPv6Address ip = start.add(next);
+    	BigInteger startInt = convertIPv6AddressToBigInteger(start);
+    	BigInteger resultInt = startInt.add(next);
+    	InetAddress resultAddr;
+		try {
+			resultAddr = InetAddress.getByAddress(resultInt.toByteArray());
+		} catch (UnknownHostException e) {
+			return null;
+		}
+    	IPv6Address ip = IPv6Address.fromInetAddress(resultAddr);
     	return ip.toString();
 	}
 
@@ -1197,11 +1204,21 @@ public class NetUtils {
 		return duid;
 	}
 	
-	//FIXME: only able to cover lower 64 bits
-	public static long countIp6InRange(String ip6Range) {
+	private static BigInteger convertIPv6AddressToBigInteger(IPv6Address addr) {
+		InetAddress inetAddr;
+		try {
+			inetAddr = addr.toInetAddress();
+		} catch (UnknownHostException e) {
+			return null;
+		}
+		return new BigInteger(inetAddr.getAddress());
+	}
+	
+	// Can cover 127 bits
+	public static BigInteger countIp6InRange(String ip6Range) {
     	String[] ips = ip6Range.split("-");
     	String startIp = ips[0];
-    	String endIp = null;
+    	String endIp = ips[0];
     	if (ips.length > 1) {
     		endIp = ips[1];
     	}
@@ -1210,13 +1227,14 @@ public class NetUtils {
     		start = IPv6Address.fromString(startIp);
     		end = IPv6Address.fromString(endIp);
 		} catch (IllegalArgumentException ex) {
-			return 0;
+			return null;
 		}
-    	long startLow = start.getLowBits(), endLow = end.getLowBits();
-    	if (startLow > endLow) {
-    		return 0;
+    	BigInteger startInt = convertIPv6AddressToBigInteger(start);
+    	BigInteger endInt = convertIPv6AddressToBigInteger(end);
+    	if (startInt.compareTo(endInt) > 0) {
+    		return null;
     	}
-    	return endLow - startLow + 1;
+    	return endInt.subtract(startInt).add(BigInteger.ONE);
 	}
 
 	public static boolean isIp6InRange(String ip6, String ip6Range) {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/95e63bc1/utils/test/com/cloud/utils/net/NetUtilsTest.java
----------------------------------------------------------------------
diff --git a/utils/test/com/cloud/utils/net/NetUtilsTest.java b/utils/test/com/cloud/utils/net/NetUtilsTest.java
index ccf0991..fae49fd 100644
--- a/utils/test/com/cloud/utils/net/NetUtilsTest.java
+++ b/utils/test/com/cloud/utils/net/NetUtilsTest.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.utils.net;
 
+import java.math.BigInteger;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
@@ -83,13 +84,18 @@ public class NetUtilsTest extends TestCase {
     	assertFalse(NetUtils.isValidIp6Cidr("1234:5678::1"));
     	assertEquals(NetUtils.getIp6CidrSize("1234:5678::1/32"), 32);
     	assertEquals(NetUtils.getIp6CidrSize("1234:5678::1"), 0);
-    	assertEquals(NetUtils.countIp6InRange("1234:5678::1-1234:5678::2"), 2);
-    	assertEquals(NetUtils.countIp6InRange("1234:5678::2-1234:5678::0"), 0);
+    	BigInteger two = new BigInteger("2");
+    	assertEquals(NetUtils.countIp6InRange("1234:5678::1-1234:5678::2"), two);
+    	assertEquals(NetUtils.countIp6InRange("1234:5678::2-1234:5678::0"), null);
     	assertEquals(NetUtils.getIp6FromRange("1234:5678::1-1234:5678::1"), "1234:5678::1");
+    	for (int i = 0; i < 5; i ++) {
+    		String ip = NetUtils.getIp6FromRange("1234:5678::1-1234:5678::2");
+    		assertTrue(ip.equals("1234:5678::1") || ip.equals("1234:5678::2"));
+    		s_logger.info("IP is " + ip);
+    	}
     	String ipString = null;
-    	String range = "1234:5678::1-1234:5678::8000:0000";
     	IPv6Address ipStart = IPv6Address.fromString("1234:5678::1");
-    	IPv6Address ipEnd = IPv6Address.fromString("1234:5678::8000:0000");
+    	IPv6Address ipEnd = IPv6Address.fromString("1234:5678::ffff:ffff:ffff:ffff");
     	for (int i = 0; i < 10; i ++) {
     		ipString = NetUtils.getIp6FromRange(ipStart.toString() + "-" + ipEnd.toString());
     		s_logger.info("IP is " + ipString);
@@ -104,9 +110,12 @@ public class NetUtilsTest extends TestCase {
     	assertFalse(NetUtils.isIp6RangeOverlap("1234:5678::f-1234:5678::ffff", "1234:5678::2-1234:5678::e"));
     	assertFalse(NetUtils.isIp6RangeOverlap("1234:5678::f-1234:5678::f", "1234:5678::2-1234:5678::e"));
     	//Test getNextIp6InRange
-    	assertEquals(NetUtils.getNextIp6InRange("1234:5678::8000:0000", range), "1234:5678::1");
+    	String range = "1234:5678::1-1234:5678::8000:0000";
+    	assertEquals(NetUtils.getNextIp6InRange("1234:5678::8000:0", range), "1234:5678::1");
     	assertEquals(NetUtils.getNextIp6InRange("1234:5678::7fff:ffff", range), "1234:5678::8000:0");
     	assertEquals(NetUtils.getNextIp6InRange("1234:5678::1", range), "1234:5678::2");
+    	range = "1234:5678::1-1234:5678::ffff:ffff:ffff:ffff";
+    	assertEquals(NetUtils.getNextIp6InRange("1234:5678::ffff:ffff:ffff:ffff", range), "1234:5678::1");
     	//Test isIp6InNetwork
     	assertFalse(NetUtils.isIp6InNetwork("1234:5678:abcd::1", "1234:5678::/64"));
     	assertTrue(NetUtils.isIp6InNetwork("1234:5678::1", "1234:5678::/64"));