Updated Branches: refs/heads/master e81389a23 -> fda8ec3c5
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/fda8ec3c Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/fda8ec3c Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/fda8ec3c Branch: refs/heads/master Commit: fda8ec3c594d16a710b9baeb04b9682e7d86e6b4 Parents: e81389a Author: Sheng Yang <[email protected]> Authored: Tue Feb 5 17:32:40 2013 -0800 Committer: Sheng Yang <[email protected]> Committed: Tue Feb 5 17:41:37 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/fda8ec3c/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 6e22782..f8d0add 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; @@ -556,8 +557,9 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { } 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/fda8ec3c/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 0875f88..f6b62de 100755 --- a/utils/src/com/cloud/utils/net/NetUtils.java +++ b/utils/src/com/cloud/utils/net/NetUtils.java @@ -19,6 +19,7 @@ package com.cloud.utils.net; import java.io.BufferedReader; 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; @@ -1151,19 +1152,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(); } @@ -1173,11 +1180,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]; } @@ -1186,13 +1203,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/fda8ec3c/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 686025e..09c6f60 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; @@ -84,13 +85,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); @@ -105,9 +111,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"));
