This is an automated email from the ASF dual-hosted git repository.

gabriel pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new f967944  ipv6: Do not allow Secondary IPv6 addresses to be EUI-64 
(#3136)
f967944 is described below

commit f967944d900847c9a2020f9aa81f5db09ee78a1c
Author: Wido den Hollander <w...@widodh.nl>
AuthorDate: Mon Jan 21 12:20:27 2019 +0100

    ipv6: Do not allow Secondary IPv6 addresses to be EUI-64 (#3136)
    
    * netutils: Add method to verify if IPv6 Address is EUI-64
    
    By checking if ff:fe is present in the address we can see if an IPv6 Address
    is EUI-64 or not.
    
    Signed-off-by: Wido den Hollander <w...@widodh.nl>
    
    * ipv6: Do not allow a Secondary IPv6 address to be EUI-64
    
    EUI-64 addresses should not be allowed as they can be used in the future by 
a to be
    deployed Instance which has to obtain this address because it matches it's 
MAC.
    
    In a /64 subnet there are more then enough other IPs available to be 
allocated to
    Instances, therefor we can safely disallow the allocation of EUI-64 
addresses.
    
    Signed-off-by: Wido den Hollander <w...@widodh.nl>
---
 .../com/cloud/network/Ipv6AddressManagerImpl.java  |  5 ++++
 .../com/cloud/network/Ipv6AddressManagerTest.java  |  7 ++++++
 .../main/java/com/cloud/utils/net/NetUtils.java    | 27 ++++++++++++++++++++++
 .../java/com/cloud/utils/net/NetUtilsTest.java     |  8 +++++++
 4 files changed, 47 insertions(+)

diff --git a/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java 
b/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java
index 0371833..adfc3d2 100644
--- a/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java
@@ -104,6 +104,11 @@ public class Ipv6AddressManagerImpl extends ManagerBase 
implements Ipv6AddressMa
                     network.getDataCenterId());
         }
 
+        if (NetUtils.isIPv6EUI64(requestedIpv6)) {
+            throw new 
InsufficientAddressCapacityException(String.format("Requested IPv6 address [%s] 
may not be a EUI-64 address", requestedIpv6), DataCenter.class,
+                    network.getDataCenterId());
+        }
+
         checkIfCanAllocateIpv6Address(network, requestedIpv6);
 
         IpAddresses requestedIpPair = new IpAddresses(null, requestedIpv6);
diff --git a/server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java 
b/server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java
index 827f533..3f082d5 100644
--- a/server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java
+++ b/server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java
@@ -248,4 +248,11 @@ public class Ipv6AddressManagerTest {
 
         Assert.assertEquals(expected, nic.getIPv6Address());
     }
+
+    @Test(expected = InsufficientAddressCapacityException.class)
+    public void acquireGuestIpv6AddressEUI64Test() throws 
InsufficientAddressCapacityException {
+        setAcquireGuestIpv6AddressTest(true, State.Free);
+        String requestedIpv6 = 
setCheckIfCanAllocateIpv6AddresscTest("2001:db8:13f::1c00:4aff:fe00:fe", false, 
false);
+        ip6Manager.acquireGuestIpv6Address(network, requestedIpv6);
+    }
 }
diff --git a/utils/src/main/java/com/cloud/utils/net/NetUtils.java 
b/utils/src/main/java/com/cloud/utils/net/NetUtils.java
index 958dfc6..72f6583b 100644
--- a/utils/src/main/java/com/cloud/utils/net/NetUtils.java
+++ b/utils/src/main/java/com/cloud/utils/net/NetUtils.java
@@ -88,6 +88,10 @@ public class NetUtils {
     private final static Random s_rand = new 
Random(System.currentTimeMillis());
     private final static long prefix = 0x1e;
 
+    // RFC4291 IPv6 EUI-64
+    public final static int IPV6_EUI64_11TH_BYTE = -1;
+    public final static int IPV6_EUI64_12TH_BYTE = -2;
+
     public static long createSequenceBasedMacAddress(final long macAddress, 
long globalConfig) {
         /*
             Logic for generating MAC address:
@@ -1583,6 +1587,29 @@ public class NetUtils {
     }
 
     /**
+     * When using StateLess Address AutoConfiguration (SLAAC) for IPv6 the 
addresses
+     * choosen by hosts in a network are based on the 48-bit MAC address and 
this is expanded to 64-bits
+     * with EUI-64
+     * FFFE is inserted into the address and these can be identified
+     *
+     * By converting the IPv6 Address to a byte array we can check the 11th 
and 12th byte to see if the
+     * address is EUI064.
+     *
+     * See RFC4291 for more information
+     *
+     * @param address IPv6Address to be checked
+     * @return True if Address is EUI-64 IPv6
+     */
+    public static boolean isIPv6EUI64(final IPv6Address address) {
+        byte[] bytes = address.toByteArray();
+        return (bytes[11] == IPV6_EUI64_11TH_BYTE && bytes[12] == 
IPV6_EUI64_12TH_BYTE);
+    }
+
+    public static boolean isIPv6EUI64(final String address) {
+        return NetUtils.isIPv6EUI64(IPv6Address.fromString(address));
+    }
+
+    /**
      * Returns true if the given IP address is IPv4 or false if it is an IPv6. 
If it is an invalid IP address it throws an exception.
      */
     public static boolean isIpv4(String ipAddr) {
diff --git a/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java 
b/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java
index bb8ba12..173704a 100644
--- a/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java
+++ b/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java
@@ -701,4 +701,12 @@ public class NetUtilsTest {
             
assertTrue(NetUtils.getAllDefaultNicIps().stream().anyMatch(defaultHostIp::contains));
         }
     }
+
+    @Test
+    public void testIsIPv6EUI64() {
+        assertTrue(NetUtils.isIPv6EUI64("fe80::5054:8fff:fe9f:af61"));
+        assertTrue(NetUtils.isIPv6EUI64("2a00:f10:305:0:464:64ff:fe00:4e0"));
+        assertFalse(NetUtils.isIPv6EUI64("2001:db8::100:1"));
+        assertFalse(NetUtils.isIPv6EUI64("2a01:4f9:2a:185f::2"));
+    }
 }

Reply via email to