Skip to content

Commit f967944

Browse files
widoGabrielBrascher
authored andcommitted
ipv6: Do not allow Secondary IPv6 addresses to be EUI-64 (apache#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]>
1 parent 3aaf281 commit f967944

File tree

4 files changed

+47
-0
lines changed

4 files changed

+47
-0
lines changed

server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ public String acquireGuestIpv6Address(Network network, String requestedIpv6) thr
104104
network.getDataCenterId());
105105
}
106106

107+
if (NetUtils.isIPv6EUI64(requestedIpv6)) {
108+
throw new InsufficientAddressCapacityException(String.format("Requested IPv6 address [%s] may not be a EUI-64 address", requestedIpv6), DataCenter.class,
109+
network.getDataCenterId());
110+
}
111+
107112
checkIfCanAllocateIpv6Address(network, requestedIpv6);
108113

109114
IpAddresses requestedIpPair = new IpAddresses(null, requestedIpv6);

server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,4 +248,11 @@ public void setNICIPv6AddressTest() {
248248

249249
Assert.assertEquals(expected, nic.getIPv6Address());
250250
}
251+
252+
@Test(expected = InsufficientAddressCapacityException.class)
253+
public void acquireGuestIpv6AddressEUI64Test() throws InsufficientAddressCapacityException {
254+
setAcquireGuestIpv6AddressTest(true, State.Free);
255+
String requestedIpv6 = setCheckIfCanAllocateIpv6AddresscTest("2001:db8:13f::1c00:4aff:fe00:fe", false, false);
256+
ip6Manager.acquireGuestIpv6Address(network, requestedIpv6);
257+
}
251258
}

utils/src/main/java/com/cloud/utils/net/NetUtils.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ public class NetUtils {
8888
private final static Random s_rand = new Random(System.currentTimeMillis());
8989
private final static long prefix = 0x1e;
9090

91+
// RFC4291 IPv6 EUI-64
92+
public final static int IPV6_EUI64_11TH_BYTE = -1;
93+
public final static int IPV6_EUI64_12TH_BYTE = -2;
94+
9195
public static long createSequenceBasedMacAddress(final long macAddress, long globalConfig) {
9296
/*
9397
Logic for generating MAC address:
@@ -1582,6 +1586,29 @@ public static IPv6Address ipv6LinkLocal(final String macAddress) {
15821586
return EUI64Address(IPv6Network.LINK_LOCAL_NETWORK, macAddress);
15831587
}
15841588

1589+
/**
1590+
* When using StateLess Address AutoConfiguration (SLAAC) for IPv6 the addresses
1591+
* choosen by hosts in a network are based on the 48-bit MAC address and this is expanded to 64-bits
1592+
* with EUI-64
1593+
* FFFE is inserted into the address and these can be identified
1594+
*
1595+
* By converting the IPv6 Address to a byte array we can check the 11th and 12th byte to see if the
1596+
* address is EUI064.
1597+
*
1598+
* See RFC4291 for more information
1599+
*
1600+
* @param address IPv6Address to be checked
1601+
* @return True if Address is EUI-64 IPv6
1602+
*/
1603+
public static boolean isIPv6EUI64(final IPv6Address address) {
1604+
byte[] bytes = address.toByteArray();
1605+
return (bytes[11] == IPV6_EUI64_11TH_BYTE && bytes[12] == IPV6_EUI64_12TH_BYTE);
1606+
}
1607+
1608+
public static boolean isIPv6EUI64(final String address) {
1609+
return NetUtils.isIPv6EUI64(IPv6Address.fromString(address));
1610+
}
1611+
15851612
/**
15861613
* 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.
15871614
*/

utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,4 +701,12 @@ public void testAllIpsOfDefaultNic() {
701701
assertTrue(NetUtils.getAllDefaultNicIps().stream().anyMatch(defaultHostIp::contains));
702702
}
703703
}
704+
705+
@Test
706+
public void testIsIPv6EUI64() {
707+
assertTrue(NetUtils.isIPv6EUI64("fe80::5054:8fff:fe9f:af61"));
708+
assertTrue(NetUtils.isIPv6EUI64("2a00:f10:305:0:464:64ff:fe00:4e0"));
709+
assertFalse(NetUtils.isIPv6EUI64("2001:db8::100:1"));
710+
assertFalse(NetUtils.isIPv6EUI64("2a01:4f9:2a:185f::2"));
711+
}
704712
}

0 commit comments

Comments
 (0)