Skip to content

Commit 2d2c2f9

Browse files
author
ipfreely-uk
committed
Special purpose address sets
1 parent db33ed3 commit 2d2c2f9

2 files changed

Lines changed: 178 additions & 0 deletions

File tree

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package uk.ipfreely.sets;
2+
3+
import uk.ipfreely.Addr;
4+
import uk.ipfreely.Family;
5+
6+
import static java.util.Objects.requireNonNull;
7+
import static uk.ipfreely.sets.AddressSets.parseCidr;
8+
9+
/**
10+
* Select IANA special purpose address sets.
11+
* <p>
12+
* See
13+
* <a href="https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xml"
14+
* >IPv4 Special-Purpose Address Space</a>
15+
* and
16+
* <a href="https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xml"
17+
* >IPv6 Special-Purpose Address Space</a>.
18+
* </p>
19+
*/
20+
public final class SpecialPurpose {
21+
private SpecialPurpose() {}
22+
23+
// TODO: singletons
24+
25+
/**
26+
* Loopback addresses.
27+
* Includes the localhost address.
28+
*
29+
* @param f IP family
30+
* @return loopback addresses
31+
* @param <A> address family
32+
*/
33+
public static <A extends Addr<A>> AddressSet<A> loopback(Family<A> f) {
34+
var expr = (requireNonNull(f) == Family.v4()) ? "127.0.0.0/8" : "::1/128";
35+
return parseCidr(f, expr);
36+
}
37+
38+
/**
39+
* Addresses reserved for private networks.
40+
*
41+
* @param f IP family
42+
* @param inUse set to true to only return currently allocated ranges
43+
* @return private use addresses
44+
* @param <A> address family
45+
*/
46+
public static <A extends Addr<A>> AddressSet<A> localUse(Family<A> f, boolean inUse) {
47+
if (requireNonNull(f) == Family.v4()) {
48+
var ten = parseCidr(f, "10.0.0.0/8");
49+
var oneSevenTwo = parseCidr(f, "172.16.0.0/12");
50+
var oneNineTwo = parseCidr(f, "192.168.0.0/16");
51+
return AddressSets.of(ten, oneSevenTwo, oneNineTwo);
52+
}
53+
if (inUse) {
54+
return parseCidr(f, "FD00::/8");
55+
}
56+
return parseCidr(f, "FC00::/7");
57+
}
58+
59+
/**
60+
* Link-local addresses for use in subnets.
61+
*
62+
* @param f IP family
63+
* @return link-local addresses
64+
* @param <A> address family
65+
*/
66+
public static <A extends Addr<A>> AddressSet<A> linkLocal(Family<A> f) {
67+
var expr = (requireNonNull(f) == Family.v4()) ? "169.254.0.0/16" : "fe80::/10";
68+
return parseCidr(f, expr);
69+
}
70+
71+
/**
72+
* Addresses reserved for documentation.
73+
*
74+
* @param f IP family
75+
* @return documentation addresses
76+
* @param <A> address family
77+
*/
78+
public static <A extends Addr<A>> AddressSet<A> documentation(Family<A> f) {
79+
if (requireNonNull(f) == Family.v4()) {
80+
var oneNineTwo = parseCidr(f, "192.0.2.0/24");
81+
var oneNineEight = parseCidr(f, "198.51.100.0/24");
82+
var twoOhThree = parseCidr(f, "203.0.113.0/24");
83+
return AddressSets.of(oneNineTwo, oneNineEight, twoOhThree);
84+
}
85+
var twoThouOne = parseCidr(f, "2001:db8::/32");
86+
var threeFs = parseCidr(f, "3fff::/20");
87+
return AddressSets.of(twoThouOne, threeFs);
88+
}
89+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package uk.ipfreely.sets;
2+
3+
import org.junit.jupiter.api.Test;
4+
import uk.ipfreely.Family;
5+
import uk.ipfreely.V4;
6+
import uk.ipfreely.V6;
7+
8+
import java.math.BigInteger;
9+
10+
import static org.junit.jupiter.api.Assertions.*;
11+
import static uk.ipfreely.Family.v4;
12+
import static uk.ipfreely.Family.v6;
13+
14+
class SpecialPurposeTest {
15+
16+
private final V4 localhost4 = v4().parse("127.0.0.1");
17+
private final V6 localhost6 = v6().parse("::1");
18+
19+
@Test
20+
void loopback() {
21+
{
22+
var set = SpecialPurpose.loopback(v4());
23+
assertTrue(set.contains(localhost4));
24+
}
25+
{
26+
var set = SpecialPurpose.loopback(v6());
27+
assertTrue(set.contains(localhost6));
28+
assertEquals(BigInteger.ONE, set.size());
29+
}
30+
}
31+
32+
@Test
33+
void localUse() {
34+
{
35+
var set = SpecialPurpose.localUse(v4(), true);
36+
assertFalse(set.contains(localhost4));
37+
var expected = v4().parse("192.168.100.10");
38+
assertTrue(set.contains(expected));
39+
}
40+
{
41+
var set = SpecialPurpose.localUse(v6(), true);
42+
assertFalse(set.contains(localhost6));
43+
var expected = v6().parse("FD00::100");
44+
assertTrue(set.contains(expected));
45+
var reserved = v6().parse("FC00::100");
46+
assertFalse(set.contains(reserved));
47+
}
48+
{
49+
var set = SpecialPurpose.localUse(v6(), false);
50+
assertFalse(set.contains(localhost6));
51+
var expected = v6().parse("FD00::100");
52+
assertTrue(set.contains(expected));
53+
var reserved = v6().parse("FC00::100");
54+
assertTrue(set.contains(reserved));
55+
}
56+
}
57+
58+
@Test
59+
void linkLocal() {
60+
{
61+
var set = SpecialPurpose.linkLocal(v4());
62+
assertFalse(set.contains(localhost4));
63+
var expected = v4().parse("169.254.10.100");
64+
assertTrue(set.contains(expected));
65+
}
66+
{
67+
var set = SpecialPurpose.linkLocal(v6());
68+
assertFalse(set.contains(localhost6));
69+
var expected = v6().parse("fe80::100");
70+
assertTrue(set.contains(expected));
71+
}
72+
}
73+
74+
@Test
75+
void documentation() {
76+
{
77+
var set = SpecialPurpose.documentation(v4());
78+
assertFalse(set.contains(localhost4));
79+
var expected = v4().parse("198.51.100.10");
80+
assertTrue(set.contains(expected));
81+
}
82+
{
83+
var set = SpecialPurpose.documentation(v6());
84+
assertFalse(set.contains(localhost6));
85+
var expected = v6().parse("2001:db8::100");
86+
assertTrue(set.contains(expected));
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)