mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-11-04 00:02:37 +01:00 
			
		
		
		
	IPv6: CLOUDSTACK-1153: Fix integer overflow on IPv6 address calcuation
Use BigInteger, which is 128 bits long.
This commit is contained in:
		
							parent
							
								
									e81389a23e
								
							
						
					
					
						commit
						fda8ec3c59
					
				@ -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
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -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"));
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user