Skip to content

Commit

Permalink
feat: ip-detector ipv6 support
Browse files Browse the repository at this point in the history
  • Loading branch information
hancin committed May 20, 2024
1 parent 1d21086 commit a287fe4
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 17 deletions.
72 changes: 72 additions & 0 deletions src/main/java/com/aws/greengrass/detector/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,27 @@ public class Config {
private final Logger logger = LogManager.getLogger(Config.class);

static final String INCLUDE_IPV4_LOOPBACK_ADDRESSES_CONFIG_KEY = "includeIPv4LoopbackAddrs";
static final String INCLUDE_IPV6_LOOPBACK_ADDRESSES_CONFIG_KEY = "includeIPv6LoopbackAddrs";
static final String INCLUDE_IPV4_LINK_LOCAL_ADDRESSES_CONFIG_KEY = "includeIPv4LinkLocalAddrs";
static final String INCLUDE_IPV6_LINK_LOCAL_ADDRESSES_CONFIG_KEY = "includeIPv6LinkLocalAddrs";
static final String INCLUDE_IPV4_ADDRESSES_CONFIG_KEY = "includeIPv4Addrs";
static final String INCLUDE_IPV6_ADDRESSES_CONFIG_KEY = "includeIPv6Addrs";
static final String DEFAULT_PORT_CONFIG_KEY = "defaultPort";
static final boolean DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES = false;
static final boolean DEFAULT_INCLUDE_IPV6_LOOPBACK_ADDRESSES = false;
static final boolean DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES = false;
static final boolean DEFAULT_INCLUDE_IPV6_LINK_LOCAL_ADDRESSES = false;
static final boolean DEFAULT_INCLUDE_IPV4_ADDRESSES = true;
static final boolean DEFAULT_INCLUDE_IPV6_ADDRESSES = false;
static final int DEFAULT_PORT = 8883;

private AtomicInteger defaultPort = new AtomicInteger(DEFAULT_PORT);
private AtomicBoolean includeIPv4LoopbackAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES);
private AtomicBoolean includeIPv6LoopbackAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV6_LOOPBACK_ADDRESSES);
private AtomicBoolean includeIPv4LinkLocalAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES);
private AtomicBoolean includeIPv6LinkLocalAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV6_LINK_LOCAL_ADDRESSES);
private AtomicBoolean includeIPv4Addrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_ADDRESSES);
private AtomicBoolean includeIPv6Addrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV6_ADDRESSES);

/**
* Config constructor.
Expand All @@ -38,7 +50,11 @@ public Config(Topics topics) {
configurationTopics.subscribe((whatHappened, node) -> {
if (configurationTopics.isEmpty()) {
this.includeIPv4LoopbackAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES);
this.includeIPv6LoopbackAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV6_LOOPBACK_ADDRESSES);
this.includeIPv4LinkLocalAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES);
this.includeIPv6LinkLocalAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV6_LINK_LOCAL_ADDRESSES);
this.includeIPv4Addrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_ADDRESSES);
this.includeIPv6Addrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV6_ADDRESSES);
this.defaultPort = new AtomicInteger(DEFAULT_PORT);
return;
}
Expand All @@ -48,18 +64,42 @@ public Config(Topics topics) {
configurationTopics.findOrDefault(
DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES,
INCLUDE_IPV4_LOOPBACK_ADDRESSES_CONFIG_KEY)));
this.includeIPv6LoopbackAddrs = new AtomicBoolean(
Coerce.toBoolean(
configurationTopics.findOrDefault(
DEFAULT_INCLUDE_IPV6_LOOPBACK_ADDRESSES,
INCLUDE_IPV6_LOOPBACK_ADDRESSES_CONFIG_KEY)));
this.includeIPv4LinkLocalAddrs = new AtomicBoolean(
Coerce.toBoolean(
configurationTopics.findOrDefault(
DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES,
INCLUDE_IPV4_LINK_LOCAL_ADDRESSES_CONFIG_KEY)));
this.includeIPv6LinkLocalAddrs = new AtomicBoolean(
Coerce.toBoolean(
configurationTopics.findOrDefault(
DEFAULT_INCLUDE_IPV6_LINK_LOCAL_ADDRESSES,
INCLUDE_IPV6_LINK_LOCAL_ADDRESSES_CONFIG_KEY)));
this.includeIPv4Addrs = new AtomicBoolean(
Coerce.toBoolean(
configurationTopics.findOrDefault(
DEFAULT_INCLUDE_IPV4_ADDRESSES,
INCLUDE_IPV4_ADDRESSES_CONFIG_KEY)));
this.includeIPv6Addrs = new AtomicBoolean(
Coerce.toBoolean(
configurationTopics.findOrDefault(
DEFAULT_INCLUDE_IPV6_ADDRESSES,
INCLUDE_IPV6_ADDRESSES_CONFIG_KEY)));
this.defaultPort = new AtomicInteger(
Coerce.toInt(
configurationTopics.findOrDefault(DEFAULT_PORT,
DEFAULT_PORT_CONFIG_KEY)));

logger.atInfo().kv("includeIPv4LoopbackAddrs", includeIPv4LoopbackAddrs.get())
.kv("includeIPv4LinkLocalAddrs", includeIPv4LinkLocalAddrs.get())
.kv("includeIPv6LoopbackAddrs", includeIPv6LoopbackAddrs.get())
.kv("includeIPv6LinkLocalAddrs", includeIPv6LinkLocalAddrs.get())
.kv("includeIPv4Addrs", includeIPv4Addrs.get())
.kv("includeIPv6Addrs", includeIPv6Addrs.get())
.kv("defaultPort", defaultPort.get())
.log("Configuration updated");
});
Expand All @@ -81,6 +121,38 @@ public boolean isIncludeIPv4LinkLocalAddrs() {
return this.includeIPv4LinkLocalAddrs.get();
}

/**
* includeIPv6LoopbackAddrs getter.
* @return boolean includeIPv6LoopbackAddrs
*/
public boolean isIncludeIPv6LoopbackAddrs() {
return this.includeIPv6LoopbackAddrs.get();
}

/**
* includeIPv6LinkLocalAddrs getter.
* @return boolean includeIPv6LinkLocalAddrs
*/
public boolean isIncludeIPv6LinkLocalAddrs() {
return this.includeIPv6LinkLocalAddrs.get();
}

/**
* includeIPv4Addrs getter.
* @return boolean includeIPv4Addrs
*/
public boolean isIncludeIPv4Addrs() {
return this.includeIPv4Addrs.get();
}

/**
* includeIPv6Addrs getter.
* @return boolean includeIPv6Addrs
*/
public boolean isIncludeIPv6Addrs() {
return this.includeIPv6Addrs.get();
}

/**
* defaultPort getter.
* @return integer defaultPort
Expand Down
26 changes: 19 additions & 7 deletions src/main/java/com/aws/greengrass/detector/detector/IpDetector.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,25 @@ List<InetAddress> getIpAddresses(Enumeration<NetworkInterface> interfaces, Confi
for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
InetAddress address = interfaceAddress.getAddress();
if (address instanceof Inet6Address) {
continue;
}
if (address.isLoopbackAddress() && !config.isIncludeIPv4LoopbackAddrs()) {
continue;
}
if (address.isLinkLocalAddress() && !config.isIncludeIPv4LinkLocalAddrs()) {
continue;
if (!config.isIncludeIPv6Addrs()) {
continue;
}
if (address.isLinkLocalAddress() && !config.isIncludeIPv6LinkLocalAddrs()) {
continue;
}
if (address.isLoopbackAddress() && !config.isIncludeIPv6LoopbackAddrs()) {
continue;
}
} else {
if (!config.isIncludeIPv4Addrs()) {
continue;
}
if (address.isLoopbackAddress() && !config.isIncludeIPv4LoopbackAddrs()) {
continue;
}
if (address.isLinkLocalAddress() && !config.isIncludeIPv4LinkLocalAddrs()) {
continue;
}
}
ipAddresses.add(address);
}
Expand Down
133 changes: 127 additions & 6 deletions src/test/java/com/aws/greengrass/detector/detector/IpDetectorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public void GIVEN_validIps_WHEN_get_ipAddresses_THEN_ip_addresses_returned() thr

Mockito.doReturn(interfaceAddresses).when(networkInterface1).getInterfaceAddresses();
Mockito.doReturn(true).when(networkInterface1).isUp();
Mockito.doReturn(true).when(config).isIncludeIPv4Addrs();
// include IPv4 Loopback addresses and Link-Local addresses
Mockito.doReturn(true).when(config).isIncludeIPv4LoopbackAddrs();
Mockito.doReturn(true).when(config).isIncludeIPv4LinkLocalAddrs();
Expand All @@ -56,6 +57,70 @@ public void GIVEN_validIps_WHEN_get_ipAddresses_THEN_ip_addresses_returned() thr
assertEquals(TestConstants.IPV4_LINK_LOCAL, ipAddresses.get(2).getHostAddress());
}

@Test
public void GIVEN_ipv6Enabled_WHEN_get_ipAddresses_THEN_ip_addresses_returned() throws SocketException {
NetworkInterface networkInterface1 = Mockito.mock(NetworkInterface.class);
Config config = Mockito.mock(Config.class);

List<NetworkInterface> networkInterfaces = new ArrayList<>();
List<InterfaceAddress> interfaceAddresses = getAllAddresses();

Mockito.doReturn(interfaceAddresses).when(networkInterface1).getInterfaceAddresses();
Mockito.doReturn(true).when(networkInterface1).isUp();
Mockito.doReturn(false).when(config).isIncludeIPv4Addrs();
Mockito.doReturn(true).when(config).isIncludeIPv6Addrs();
// include IPv6 Loopback addresses and Link-Local addresses
Mockito.doReturn(true).when(config).isIncludeIPv6LoopbackAddrs();
Mockito.doReturn(true).when(config).isIncludeIPv6LinkLocalAddrs();

networkInterfaces.add(networkInterface1);
Enumeration<NetworkInterface> enumeration = Collections.enumeration(networkInterfaces);
ipDetector = new IpDetector();
List<InetAddress> ipAddresses = ipDetector.getIpAddresses(enumeration, config);

assertEquals(4, ipAddresses.size());
assertEquals(TestConstants.IPV6_LOOPBACK, ipAddresses.get(0).getHostAddress());
assertEquals(TestConstants.IPV6_LINK_LOCAL_1, ipAddresses.get(1).getHostAddress());
assertEquals(TestConstants.IPV6_LINK_LOCAL_2, ipAddresses.get(2).getHostAddress());
assertEquals(TestConstants.IPV6_1, ipAddresses.get(3).getHostAddress());

}


@Test
public void GIVEN_dualStack_WHEN_get_ipAddresses_THEN_ip_addresses_returned() throws SocketException {
NetworkInterface networkInterface1 = Mockito.mock(NetworkInterface.class);
Config config = Mockito.mock(Config.class);

List<NetworkInterface> networkInterfaces = new ArrayList<>();
List<InterfaceAddress> interfaceAddresses = getAllAddresses();

Mockito.doReturn(interfaceAddresses).when(networkInterface1).getInterfaceAddresses();
Mockito.doReturn(true).when(networkInterface1).isUp();
Mockito.doReturn(true).when(config).isIncludeIPv4Addrs();
Mockito.doReturn(true).when(config).isIncludeIPv6Addrs();
// include IPv4 Loopback addresses and Link-Local addresses
Mockito.doReturn(true).when(config).isIncludeIPv4LoopbackAddrs();
Mockito.doReturn(true).when(config).isIncludeIPv4LinkLocalAddrs();
Mockito.lenient().doReturn(true).when(config).isIncludeIPv6LoopbackAddrs();
Mockito.lenient().doReturn(true).when(config).isIncludeIPv6LinkLocalAddrs();

networkInterfaces.add(networkInterface1);
Enumeration<NetworkInterface> enumeration = Collections.enumeration(networkInterfaces);
ipDetector = new IpDetector();
List<InetAddress> ipAddresses = ipDetector.getIpAddresses(enumeration, config);

assertEquals(7, ipAddresses.size());
assertEquals(TestConstants.IPV4_LOOPBACK, ipAddresses.get(0).getHostAddress());
assertEquals(TestConstants.IP_1, ipAddresses.get(1).getHostAddress());
assertEquals(TestConstants.IPV6_LOOPBACK, ipAddresses.get(2).getHostAddress());
assertEquals(TestConstants.IPV6_LINK_LOCAL_1, ipAddresses.get(3).getHostAddress());
assertEquals(TestConstants.IPV6_LINK_LOCAL_2, ipAddresses.get(4).getHostAddress());
assertEquals(TestConstants.IPV4_LINK_LOCAL, ipAddresses.get(5).getHostAddress());
assertEquals(TestConstants.IPV6_1, ipAddresses.get(6).getHostAddress());

}

@Test
public void GIVEN_loopbackAddress_linkLocalAddress_WHEN_get_ipAddresses_THEN_loopbackAddress_linkLocalAddress_filtered() throws SocketException {
NetworkInterface networkInterface = Mockito.mock(NetworkInterface.class);
Expand All @@ -66,6 +131,7 @@ public void GIVEN_loopbackAddress_linkLocalAddress_WHEN_get_ipAddresses_THEN_loo

Mockito.doReturn(interfaceAddresses).when(networkInterface).getInterfaceAddresses();
Mockito.doReturn(true).when(networkInterface).isUp();
Mockito.doReturn(true).when(config).isIncludeIPv4Addrs();
// Exclude IPv4 Loopback addresses and Link-Local addresses
Mockito.doReturn(false).when(config).isIncludeIPv4LoopbackAddrs();
Mockito.doReturn(false).when(config).isIncludeIPv4LinkLocalAddrs();
Expand All @@ -79,6 +145,53 @@ public void GIVEN_loopbackAddress_linkLocalAddress_WHEN_get_ipAddresses_THEN_loo
assertEquals(TestConstants.IP_1, ipAddresses.get(0).getHostAddress());
}


@Test
public void GIVEN_ipv6_filter_WHEN_get_ipAddresses_THEN_loopbackAddress_linkLocalAddress_filtered() throws SocketException {
NetworkInterface networkInterface = Mockito.mock(NetworkInterface.class);
Config config = Mockito.mock(Config.class);

List<NetworkInterface> networkInterfaces = new ArrayList<>();
List<InterfaceAddress> interfaceAddresses = getAllAddresses();

Mockito.doReturn(interfaceAddresses).when(networkInterface).getInterfaceAddresses();
Mockito.doReturn(true).when(networkInterface).isUp();
Mockito.doReturn(false).when(config).isIncludeIPv4Addrs();
Mockito.doReturn(true).when(config).isIncludeIPv6Addrs();
// Exclude IPv4 Loopback addresses and Link-Local addresses
Mockito.lenient().doReturn(false).when(config).isIncludeIPv6LoopbackAddrs();
Mockito.lenient().doReturn(false).when(config).isIncludeIPv6LinkLocalAddrs();

networkInterfaces.add(networkInterface);
Enumeration<NetworkInterface> enumeration = Collections.enumeration(networkInterfaces);
ipDetector = new IpDetector();
List<InetAddress> ipAddresses = ipDetector.getIpAddresses(enumeration, config);

assertEquals(1, ipAddresses.size());
assertEquals(TestConstants.IPV6_1, ipAddresses.get(0).getHostAddress());
}

@Test
public void GIVEN_ipv4_ipv6_disabled_WHEN_get_ipAddresses_THEN_empty_returned() throws SocketException {
NetworkInterface networkInterface = Mockito.mock(NetworkInterface.class);
Config config = Mockito.mock(Config.class);

List<NetworkInterface> networkInterfaces = new ArrayList<>();
List<InterfaceAddress> interfaceAddresses = getAllAddresses();

Mockito.doReturn(interfaceAddresses).when(networkInterface).getInterfaceAddresses();
Mockito.doReturn(true).when(networkInterface).isUp();
Mockito.doReturn(false).when(config).isIncludeIPv4Addrs();
Mockito.doReturn(false).when(config).isIncludeIPv6Addrs();

networkInterfaces.add(networkInterface);
Enumeration<NetworkInterface> enumeration = Collections.enumeration(networkInterfaces);
ipDetector = new IpDetector();
List<InetAddress> ipAddresses = ipDetector.getIpAddresses(enumeration, config);

assertEquals(0, ipAddresses.size());
}

@Test
public void GIVEN_noIps_WHEN_get_ipAddresses_THEN_null_returned() throws SocketException {
ipDetector = new IpDetector();
Expand Down Expand Up @@ -106,37 +219,45 @@ private List<InterfaceAddress> getAllAddresses() {
InterfaceAddress interfaceAddress4 = Mockito.mock(InterfaceAddress.class);
InterfaceAddress interfaceAddress5 = Mockito.mock(InterfaceAddress.class);
InterfaceAddress interfaceAddress6 = Mockito.mock(InterfaceAddress.class);
InterfaceAddress interfaceAddress7 = Mockito.mock(InterfaceAddress.class);

InetAddress inetAddress1 = Mockito.mock(Inet4Address.class);
InetAddress inetAddress2 = Mockito.mock(Inet4Address.class);
InetAddress inetAddress3 = Mockito.mock(Inet6Address.class);
InetAddress inetAddress4 = Mockito.mock(Inet6Address.class);
InetAddress inetAddress5 = Mockito.mock(Inet6Address.class);
InetAddress inetAddress6 = Mockito.mock(Inet4Address.class);
InetAddress inetAddress7 = Mockito.mock(Inet6Address.class);

Mockito.lenient().doReturn(TestConstants.IPV4_LOOPBACK).when(inetAddress1).getHostAddress();
Mockito.doReturn(TestConstants.IP_1).when(inetAddress2).getHostAddress();
Mockito.lenient().doReturn(TestConstants.IP_2).when(inetAddress3).getHostAddress();
Mockito.lenient().doReturn(TestConstants.IP_3).when(inetAddress4).getHostAddress();
Mockito.lenient().doReturn(TestConstants.IP_4).when(inetAddress5).getHostAddress();
Mockito.lenient().doReturn(TestConstants.IP_1).when(inetAddress2).getHostAddress();
Mockito.lenient().doReturn(TestConstants.IPV6_LOOPBACK).when(inetAddress3).getHostAddress();
Mockito.lenient().doReturn(TestConstants.IPV6_LINK_LOCAL_1).when(inetAddress4).getHostAddress();
Mockito.lenient().doReturn(TestConstants.IPV6_LINK_LOCAL_2).when(inetAddress5).getHostAddress();
Mockito.lenient().doReturn(TestConstants.IPV4_LINK_LOCAL).when(inetAddress6).getHostAddress();
Mockito.lenient().doReturn(TestConstants.IPV6_1).when(inetAddress7).getHostAddress();

Mockito.doReturn(true).when(inetAddress1).isLoopbackAddress();
Mockito.doReturn(true).when(inetAddress6).isLinkLocalAddress();
Mockito.lenient().doReturn(true).when(inetAddress1).isLoopbackAddress();
Mockito.lenient().doReturn(true).when(inetAddress3).isLoopbackAddress();
Mockito.lenient().doReturn(true).when(inetAddress4).isLinkLocalAddress();
Mockito.lenient().doReturn(true).when(inetAddress5).isLinkLocalAddress();
Mockito.lenient().doReturn(true).when(inetAddress6).isLinkLocalAddress();

Mockito.doReturn(inetAddress1).when(interfaceAddress1).getAddress();
Mockito.doReturn(inetAddress2).when(interfaceAddress2).getAddress();
Mockito.doReturn(inetAddress3).when(interfaceAddress3).getAddress();
Mockito.doReturn(inetAddress4).when(interfaceAddress4).getAddress();
Mockito.doReturn(inetAddress5).when(interfaceAddress5).getAddress();
Mockito.doReturn(inetAddress6).when(interfaceAddress6).getAddress();
Mockito.doReturn(inetAddress7).when(interfaceAddress7).getAddress();

interfaceAddresses.add(interfaceAddress1);
interfaceAddresses.add(interfaceAddress2);
interfaceAddresses.add(interfaceAddress3);
interfaceAddresses.add(interfaceAddress4);
interfaceAddresses.add(interfaceAddress5);
interfaceAddresses.add(interfaceAddress6);
interfaceAddresses.add(interfaceAddress7);

return interfaceAddresses;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ private List<String> getIps() {
private List<String> getNewIps() {
List<String> ips = new ArrayList<>();
ips.add(TestConstants.IPV4_LOOPBACK);
ips.add(TestConstants.IP_2);
ips.add(TestConstants.IPV6_LOOPBACK);
return ips;
}
}
Expand Down
Loading

0 comments on commit a287fe4

Please sign in to comment.