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 <wido@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 <wido@widodh.nl>
This commit is contained in:
Wido den Hollander 2019-01-21 12:20:27 +01:00 committed by Gabriel Beims Bräscher
parent 3aaf281f94
commit f967944d90
4 changed files with 47 additions and 0 deletions

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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:
@ -1582,6 +1586,29 @@ public class NetUtils {
return EUI64Address(IPv6Network.LINK_LOCAL_NETWORK, macAddress);
}
/**
* 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.
*/

View File

@ -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"));
}
}