简体   繁体   中英

Get all IP addresses from a given IP address and subnet mask

In Java, I need to get list of all IP Addresses contained by a given IP network.

For eg let the netowork be: 192.168.5.0/24 then the output will be (192.168.5.0 ... 192.168.5.255).

I could think of the following way but it looks dirty, is there any elegant way? There is no function for the same in InetAddress class.

  1. Get Network Ip from the input Ip and subnet mask.

     mask = (long)(0xffffffff) << (32-subnetMask); Long netIp = getLongfromIp(Inputip)& mask; 

The function 'getLongfromIp' contains code from - How to convert string (IP numbers) to Integer in Java

  1. get the number of hosts by Subnet Mask

    maxRange = (long)0x1<<(32-subnetMask);

  2. Get address of all hopes by adding i for i in (0 .. maxRange) in the netIp

  3. Convert the ip from above step to octet string.

Ps: I am sure the the IP Addresses will be in IPV4 only.

Answering my own question, solution is to use Apache commons.net library

import org.apache.commons.net.util.*;

SubnetUtils utils = new SubnetUtils("192.168.1.0/24");
String[] allIps = utils.getInfo().getAllAddresses();
//appIps will contain all the ip address in the subnet

Read more: Class SubnetUtils.SubnetInfo

To include NetworkAddress and BroadcastAddress

import org.apache.commons.net.util.*;

 SubnetUtils utils = new SubnetUtils("192.168.1.0/28");
       utils.setInclusiveHostCount(true);

       String[] allIps = utils.getInfo().getAllAddresses();

The IPAddress Java library supports both IPv4 and IPv6 subnets in a polymorphic manner. Disclaimer: I am the project manager.

Here is sample code to list the addresses for an IPv4 or Ipv6 subnet transparently. Subnets can get quite large, especially with IPv6, and it is not wise to attempt to iterate through a large subnet, so the code for iterateEdges shows how to iterate through just the beginning and ending 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);
    System.out.println();
}

static void show(IPAddress subnet) {
    Integer prefix = subnet.getNetworkPrefixLength();
    IPAddress mask = subnet.getNetwork().getNetworkMask(prefix, false);
    BigInteger count = subnet.getCount();
    System.out.println("Subnet of size " + count + " with prefix length " + prefix + " and mask " + mask);
    System.out.println("Subnet ranges from " + subnet.getLower() + " to " + subnet.getUpper());
    if(count.compareTo(BigInteger.valueOf(256)) <= 0) {
        iterateAll(subnet);
    } else {
        iterateEdges(subnet);
    }
}

static void iterateAll(IPAddress subnet) {
    BigInteger count = subnet.getCount();
    BigInteger three = BigInteger.valueOf(3), currentCount = count;
    int i = 0;
    for(IPAddress addr: subnet.getIterable()) {
        if(i < 3) {
            System.out.println(++i + ": " + addr);
        } else if(currentCount.compareTo(three) <= 0) {
            System.out.println(count.subtract(currentCount) + ": " + addr);
        } else if(i == 3) {
            System.out.println("...skipping...");
            i++;
        }
        currentCount = currentCount.subtract(BigInteger.ONE);
    }
}

static void iterateEdges(IPAddress subnet) {
    int sample = 3;
    for(int i = -sample; i < sample; i++) {
        if(i < 0) {
            int increment = i + sample + 1;
            System.out.println(increment + ": " + subnet.getLower().increment(increment - 1));
        } else {
            if(i == 0) {
                System.out.println("...skipping...");
            }
            BigInteger count = subnet.getCount();
            int increment = i - sample + 1;
            System.out.println(count.add(BigInteger.valueOf(increment)) + ": " + subnet.getUpper().increment(increment));
        } 
    }
}

Here is the output:

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...
253: 192.168.5.253/24
254: 192.168.5.254/24
255: 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

If you start with an address, then you can get the subnet using toPrefixBlock():

IPAddress addr = new IPAddressString("192.168.5.1/24").toAddress();
IPAddress subnet = addr.toPrefixBlock();
System.out.println(addr + " is from subnet " + subnet);

output:

192.168.5.1/24 is from subnet 192.168.5.0/24

The following is the same as Sean's (really nice!) answer using https://seancfoley.github.io/IPAddress/ , it is only reducing the signal to noise ratio:

subnetToIps("192.168.10.0/28");

    public void subnetToIps(String ipOrCidr) {
        IPAddressString addrString = new IPAddressString(ipOrCidr, IPAddressString.DEFAULT_VALIDATION_OPTIONS);
        IPAddress subnet = addrString.toAddress();
        System.out.println("Subnet ranges from " + subnet.getLower() + " to " + subnet.getUpper());

        int i = 0;
        for (IPAddress addr : subnet.getIterable()) {
            System.out.println(++i + ": " + addr);
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM