Last active
June 30, 2023 14:11
-
-
Save ssttevee/b0e2b431f4b23d289537 to your computer and use it in GitHub Desktop.
List all possible IP addresses in a given subnet. Should work with both IPv4 and IPv6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.net.*; | |
| import java.util.*; | |
| public class SubnetAddresses { | |
| public static void main(String[] args) throws UnknownHostException, SocketException { | |
| // get all possible IP addresses of all LANs | |
| Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces(); | |
| while (nis.hasMoreElements()) { | |
| // Get the next network interface | |
| NetworkInterface ni = nis.nextElement(); | |
| // We only want LANs | |
| // loopback infers that it is not a LAN | |
| if (ni.isLoopback()) continue; | |
| // Iterate through the addresses attached to the network interface | |
| for (InterfaceAddress ia : ni.getInterfaceAddresses()) { | |
| List<byte[]> addresses = getAllAddresses(ia.getAddress().getAddress(), ia.getNetworkPrefixLength()); | |
| // Sort addresses | |
| Collections.sort(addresses, new AddressComparator()); | |
| // Output addresses to console | |
| for (byte[] address : addresses) System.out.println(InetAddress.getByAddress(address)); | |
| } | |
| } | |
| } | |
| /** | |
| * Creates a list of all possible IP addresses in a subnet given an IP address and the network mask | |
| * @param address IP address in byte array form (i.e. 127.0.0.1 = 01111111 00000000 00000000 00000001) | |
| * @param maskLength Network mask length (i.e. the number after the forward-slash, '/', in CIDR notation) | |
| * @return All possible IP addresses | |
| */ | |
| public static List<byte[]> getAllAddresses(byte[] address, int maskLength) { | |
| return getAllAddresses(address, maskLength, true); | |
| } | |
| /** | |
| * Recursively calculate each IP address within a subnet | |
| * @param address IP address in byte array form (i.e. 127.0.0.1 = 01111111 00000000 00000000 00000001) | |
| * @param maskLength Network mask length (i.e. the number after the forward-slash, '/', in CIDR notation) | |
| * @param scrub Whether or not to scrub the unmasked bits of the address | |
| * @return All possible IP addresses | |
| */ | |
| private static List<byte[]> getAllAddresses(byte[] address, int maskLength, boolean scrub) { | |
| if (scrub) scrubAddress(address, maskLength); | |
| // logAddress(address); | |
| if (maskLength >= address.length * 8) return Collections.singletonList(address); | |
| List<byte[]> addresses = new ArrayList<byte[]>(); | |
| int set = maskLength / 8; | |
| int pos = maskLength % 8; | |
| byte[] addressLeft = address.clone(); | |
| addressLeft[set] |= 1 << pos; | |
| addresses.addAll(getAllAddresses(addressLeft, maskLength + 1, false)); | |
| byte[] addressRight = address.clone(); | |
| addressRight[set] &= ~(1 << pos); | |
| addresses.addAll(getAllAddresses(addressRight, maskLength + 1, false)); | |
| return addresses; | |
| } | |
| /** | |
| * Set the unmasked bits of the IP address to 0 | |
| * @param address IP address in byte array form (i.e. 127.0.0.1 = 01111111 00000000 00000000 00000001) | |
| * @param maskLength Network mask length (i.e. the number after the forward-slash, '/', in CIDR notation) | |
| * @return The scrubbed IP address | |
| */ | |
| private static byte[] scrubAddress(byte[] address, int maskLength) { | |
| for (int i = 0; i < address.length * 8; i++) { | |
| if (i < maskLength) continue; | |
| address[i / 8] &= ~(1 << (i % 8)); | |
| } | |
| return address; | |
| } | |
| /** | |
| * Output the IP address to the console, first in dotted-decimal notation, then in byte array form | |
| * <br><br> | |
| * i.e.<br> | |
| * 127.0.0.1<br> | |
| * 01111111 00000000 00000000 00000001 | |
| * | |
| * @param address IP address in byte array form (i.e. 127.0.0.1 = 01111111 00000000 00000000 00000001) | |
| */ | |
| public static void logAddress(byte[] address) { | |
| String addressInts = ""; | |
| String addressBits = ""; | |
| for (byte octet : address) { | |
| addressInts += String.valueOf((int) octet & 0xFF); | |
| addressInts += "."; | |
| for (int i = 7; i >= 0; i--) { | |
| int bit = 1 << i; | |
| addressBits += String.valueOf((octet & bit) == bit ? "1" : "0"); | |
| } | |
| addressBits += " "; | |
| } | |
| System.out.println(addressInts.substring(0, addressInts.length() - 1)); | |
| System.out.println(addressBits.substring(0, addressBits.length() - 1)); | |
| } | |
| /** | |
| * Comparator to compare IP addresses that are in byte array form | |
| */ | |
| public static class AddressComparator implements Comparator<byte[]> { | |
| @Override | |
| public int compare(byte[] lhs, byte[] rhs) { | |
| if (lhs.length != rhs.length) return lhs.length < rhs.length ? -1 : 1; | |
| int pos = lhs.length - 1; | |
| while (lhs[pos] == rhs[pos]) { | |
| if (--pos < 0) return 0; | |
| } | |
| return (lhs[pos] & 0xFF) < (rhs[pos] & 0xFF) ? -1 : 1; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
God that is so complicated