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 <[email protected]>
Authored: Tue Feb 5 17:32:40 2013 -0800
Committer: Sheng Yang <[email protected]>
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"));

Reply via email to