IPAddress Java Library supports both IPv4 and IPv6 subnets in a polymorphic fashion. Disclaimer: I am a project manager.
Here is sample code for transparently displaying an address list for an IPv4 or IPv6 subnet. Subnets can be quite large, especially with IPv6, and you should not try to iterate over a large subnet, so the code for iterateEdges shows how to iterate over only the start and end addresses in the subnet.
show("192.168.10.0/24"); show("2001:db8:abcd:0012::/64"); static void show(String subnet) throws AddressStringException { IPAddressString addrString = new IPAddressString(subnet); IPAddress addr = addrString.toAddress(); show(addr); } static void show(IPAddress subnet) { Integer prefixLength = subnet.getNetworkPrefixLength(); if(prefixLength == null) { prefixLength = subnet.getBitCount(); } IPAddress mask = subnet.getNetwork().getNetworkMask(prefixLength, false); BigInteger count = subnet.getCount(); System.out.println("Subnet of size " + count + " with prefix length " + prefixLength + " and mask " + mask); System.out.println("Subnet ranges from " + subnet.getLower() + " to " + subnet.getUpper()); int edgeCount = 3; if(count.compareTo(BigInteger.valueOf(256)) <= 0) { iterateAll(subnet, edgeCount); } else { iterateEdges(subnet, edgeCount); } }
Iterates over the entire subnet, use with caution:
static void iterateAll(IPAddress subnet, int edgeCount) { BigInteger count = subnet.getCount(); BigInteger bigEdge = BigInteger.valueOf(edgeCount), currentCount = count; int i = 0; for(IPAddress addr: subnet.getIterable()) { currentCount = currentCount.subtract(BigInteger.ONE); if(i < edgeCount) { System.out.println(++i + ": " + addr); } else if(currentCount.compareTo(bigEdge) < 0) { System.out.println(count.subtract(currentCount) + ": " + addr); } else if(i == edgeCount) { System.out.println("...skipping..."); i++; } } }
Iterate over the edges of the subnet:
static void iterateEdges(IPAddress subnet, int edgeCount) { for(int increment = 0; increment < edgeCount; increment++) { System.out.println((increment + 1) + ": " + subnet.getLower().increment(increment)); } System.out.println("...skipping..."); BigInteger count = subnet.getCount(); for(int decrement = 1 - edgeCount; decrement <= 0; decrement++) { System.out.println(count.add(BigInteger.valueOf(decrement)) + ": " + subnet.getUpper().increment(decrement)); } }
Here is the conclusion:
Subnet of size 256 with prefix length 24 and mask 255.255.255.0 Subnet ranges from 192.168.5.0/24 to 192.168.5.255/24 1: 192.168.5.0/24 2: 192.168.5.1/24 3: 192.168.5.2/24 ...skipping... 254: 192.168.5.253/24 255: 192.168.5.254/24 256: 192.168.5.255/24 Subnet of size 18446744073709551616 with prefix length 64 and mask ffff:ffff:ffff:ffff:: Subnet ranges from 2001:db8:abcd:12::/64 to 2001:db8:abcd:12:ffff:ffff:ffff:ffff/64 1: 2001:db8:abcd:12::/64 2: 2001:db8:abcd:12::1/64 3: 2001:db8:abcd:12::2/64 ...skipping... 18446744073709551614: 2001:db8:abcd:12:ffff:ffff:ffff:fffd/64 18446744073709551615: 2001:db8:abcd:12:ffff:ffff:ffff:fffe/64 18446744073709551616: 2001:db8:abcd:12:ffff:ffff:ffff:ffff/64
source share