Filter special purpose IPs (RFC 6890) in externalAddresses()

Update `InetAddressFilter.externalAddresses()` to filter special purpose
IP addresses as defined by RFC 6890. As a byproduct of this commit to
additional factory methods (`specialPurpose()` and `multicast()`) have
also been introduced.

Closes gh-50668
This commit is contained in:
Dependabot Standalone
2026-06-02 09:52:02 -07:00
parent f98f06388f
commit 739daa7ba8
2 changed files with 243 additions and 2 deletions
@@ -185,12 +185,16 @@ public interface InetAddressFilter {
/** /**
* Return a filter that will match external (non-private) IP addresses. External * Return a filter that will match external (non-private) IP addresses. External
* addresses are all non-{@link #internalAddresses() internal addresses} * addresses are all {@link #routable() routable} addresses that are not:
* <ul>
* <li>{@link #multicast() multicast}</li>
* <li>{@link #specialPurpose() special purpose}</li>
* </ul>
* @return a filter for external IP addresses * @return a filter for external IP addresses
* @see #internalAddresses() * @see #internalAddresses()
*/ */
static InetAddressFilter externalAddresses() { static InetAddressFilter externalAddresses() {
return routable().andNot(InternalInetAddressFilter.instance); return routable().andNot(multicast(), specialPurpose());
} }
/** /**
@@ -224,6 +228,27 @@ public interface InetAddressFilter {
}; };
} }
/**
* Returns a filter that will match all multicast addresses.
* @return a filter for multicast IP addresses
*/
static InetAddressFilter multicast() {
return InetAddress::isMulticastAddress;
}
/**
* Returns a filter that will match special purpose IP addresses as defined by
* <a href="https://www.rfc-editor.org/info/rfc6890">RFC 6890</a>.
* @return a filter for this network
*/
static InetAddressFilter specialPurpose() {
return of("0.0.0.0/8", "100.64.0.0/10", "127.0.0.0/8", "169.254.0.0/16", "192.0.0.0/24", "192.0.0.0/29",
"192.0.2.0/24", "192.88.99.0/24", "198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4",
"255.255.255.255/32", "::1/128", "::/128", "64:ff9b::/96", "100::/64", "2001::/23", "2001::/32",
"2001:2::/48", "2001:db8::/32", "2001:10::/28", "2002::/16", "fc00::/7", "fe80::/10")
.or(InternalInetAddressFilter.instance);
}
/** /**
* Return a filter that is the negation of all the given addresses. * Return a filter that is the negation of all the given addresses.
* @param addresses the addresses to negate in any form supported by * @param addresses the addresses to negate in any form supported by
@@ -327,6 +327,65 @@ class InetAddressFilterTests {
assertThat(filter).doesNotMatch("::"); assertThat(filter).doesNotMatch("::");
} }
@Test
void ipv4CurrentLocalThisNetwork() {
InetAddressFilter filter = InetAddressFilter.externalAddresses();
assertThat(filter).doesNotMatch("0.0.0.4");
}
@Test
void ipv4Subnet() {
InetAddressFilter filter = InetAddressFilter.externalAddresses();
assertThat(filter).doesNotMatch("169.254.0.1");
assertThat(filter).doesNotMatch("255.255.255.255");
}
@Test
void ipv4Documentation() {
InetAddressFilter filter = InetAddressFilter.externalAddresses();
assertThat(filter).doesNotMatch("192.0.2.1");
assertThat(filter).doesNotMatch("203.0.113.1");
}
@Test
void ipv4Multicast() {
InetAddressFilter filter = InetAddressFilter.externalAddresses();
assertThat(filter).doesNotMatch("224.0.0.1");
}
@Test
void ipv4ReservedForFutureUse() {
InetAddressFilter filter = InetAddressFilter.externalAddresses();
assertThat(filter).doesNotMatch("240.0.0.1");
}
@Test
void ipv4SharedAddressSpace() {
InetAddressFilter filter = InetAddressFilter.externalAddresses();
assertThat(filter).doesNotMatch("100.64.0.1");
assertThat(filter).doesNotMatch("100.127.255.254");
}
@Test
void ipv4PerformanceBenchmarking() {
InetAddressFilter filter = InetAddressFilter.externalAddresses();
assertThat(filter).doesNotMatch("198.18.0.1");
assertThat(filter).doesNotMatch("198.19.255.255");
}
@Test
void ipv4AllHostsMulticastGroup() {
InetAddressFilter filter = InetAddressFilter.externalAddresses();
assertThat(filter).doesNotMatch("224.0.0.1");
assertThat(filter).doesNotMatch("239.255.255.250");
}
@Test
void ipv6NodeLinkMulticastAddress() {
InetAddressFilter filter = InetAddressFilter.externalAddresses();
assertThat(filter).doesNotMatch("ff02::1");
}
} }
@Nested @Nested
@@ -521,6 +580,163 @@ class InetAddressFilterTests {
} }
@Nested
class Multicast {
@Test
void multicast() {
InetAddressFilter filter = InetAddressFilter.multicast();
assertThat(filter).matches("239.255.255.255");
assertThat(filter).matches("FF00:0000:0000:0000:0000:0000:0000:0001");
}
}
@Nested
class SpecialPurpose {
@Test
void publicAddress() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).doesNotMatch("8.8.8.8");
}
@Test
void thisHostNetwork() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("0.0.0.1");
}
@Test
void privateUseNetwork() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("10.0.0.1");
assertThat(filter).matches("172.16.0.1");
assertThat(filter).matches("192.168.0.1");
}
@Test
void sharedAddressSpace() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("100.64.0.1");
}
@Test
void loopback() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("127.0.0.0");
assertThat(filter).matches("::1");
}
@Test
void linkLocal() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("169.254.0.1");
}
@Test
void protocolAssignments() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("192.0.0.1");
assertThat(filter).matches("2001:0000:0000:0000:0000:0000:0000:0001");
}
@Test
void dsLite() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("192.0.0.1");
}
@Test
void documentation() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("192.0.2.1");
assertThat(filter).matches("198.51.100.1");
assertThat(filter).matches("203.0.113.1");
assertThat(filter).matches("2001:0db8:0000:0000:0000:0000:0000:0001");
}
@Test
void SixToFourRelay() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("192.88.99.1");
}
@Test
void deviceBenchmarking() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("198.18.0.1");
assertThat(filter).matches("2001:0002:0000:0000:0000:0000:0000:0001");
}
@Test
void futureUse() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("240.0.0.1");
}
@Test
void limitedBroadcast() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("255.255.255.255");
}
@Test
void unspecifiedAddress() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("0000:0000:0000:0000:0000:0000:0000:0001");
}
@Test
void ipv4ToIpv6AddressTranslation() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("0064:ff9b:0000:0000:0000:0000:0000:0001");
}
@Test
void ipv4MappedAddress() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("0000:0000:0000:0000:0000:ffff:0000:0001");
}
@Test
void discardOnly() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("0100:0000:0000:0000:0000:0000:0000:0001");
}
@Test
void teredo() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("2001:0000:0000:0000:0000:0000:0000:0001");
}
@Test
void orchid() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("2001:10:0000:0000:0000:0000:0000:0001");
}
@Test
void sixToFour() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("2002:0000:0000:0000:0000:0000:0000:0001");
}
@Test
void uniqueLocal() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("fc00:0000:0000:0000:0000:0000:0000:0001");
}
@Test
void linkedScopedUnicast() {
InetAddressFilter filter = InetAddressFilter.specialPurpose();
assertThat(filter).matches("fe80:0000:0000:0000:0000:0000:0000:0001");
}
}
@Nested @Nested
class NotTests { class NotTests {