mirror of https://github.com/apache/cloudstack.git
IPv6: CLOUDSTACK-1153: Fix integer overflow on IPv6 address calcuation
Use BigInteger, which is 128 bits long.
This commit is contained in:
parent
ec206d69be
commit
95e63bc1cf
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
Loading…
Reference in New Issue