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 <[email protected]>
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 <[email protected]>
* 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 <[email protected]>
---
.../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"));
+ }
}