seancfoley / IPAddress

Java library for handling IP addresses and subnets, both IPv4 and IPv6
https://seancfoley.github.io/IPAddress/
Apache License 2.0
466 stars 63 forks source link

Too short IP range when bits are set in first host address #122

Closed jms4t closed 7 months ago

jms4t commented 7 months ago

I'm facing an issue creating IP Ranges,

What I expect:

IPAddressString("46.114.184.1/21").toSequentialRange() --> range: 46.114.184.1 to 46.114.191.255
...
IPAddressString("46.114.185.0/21").toSequentialRange() --> range 46.114.185.0 to 46.114.191.255
... 

What I get:

IPAddressString("46.114.184.1/21").toSequentialRange() --> range: 46.114.184.1 to 46.114.184.1
...
IPAddressString("46.114.185.0/21").toSequentialRange() --> range 46.114.185.0 to 46.114.185.0
... 

here i find similar results to what i expected. Is it a bug, or am i using it wrong? Please let me know :)

(I'm using the latest version 5.4.2)

seancfoley commented 7 months ago

With both your examples 46.114.184.1/21 and 46.114.185.0/21, the address is a CIDR address with a non-zero host, so it's parsed as a single address by this library, as well as by that page.

On the web-page you linked, the page makes the distinction between the address you've supplied and the associated CIDR subnet 46.114.184.0/21, and you need to do the same here. You have a misunderstanding of what that page is telling you. You are supplying an address and a prefix length, and it is telling you what CIDR subnet with the same prefix length that the address belongs to. Both address/prefix pairs you specified are in the same subnet, 46.114.184.0/21. The page is also telling you the min and max host for that subnet if you want to exclude the network address 46.114.184.0 and the broadcast address 46.114.191.255, but those two addresses are still in the subnet.

Also note that there is no CIDR subnet from 46.114.185.0 to 46.114.191.255. You should read up on CIDR to understand this. For both addresses, the subnet is 46.114.184.0 to 46.114.191.255 or the subnet with network address 46.114.184.0/21.

So, in this library, you can get the subnet range 46.114.184.0 to 46.114.191.255 using the subnet address

print(new IPAddressString("46.114.184.0/21").getAddress().toCanonicalWildcardString()); // the network address gives you the network
print(new IPAddressString("46.114.184.0/21").getAddress().toSequentialRange());
print(new IPAddressString("46.114.184.0/21").getSequentialRange());

static void print(Object o) {
    System.out.println(o);
}
46.114.184-191.*
46.114.184.0 -> 46.114.191.255
46.114.184.0 -> 46.114.191.255

You do not really need to use a sequential range object IPAddressSeqRange when you are working with CIDR subnets, but since that is what your example code is doing, I've done that too. But in general with CIDR, just use an IPAddress to represent a CIDR subnet.

For any address, including those with non-zero host, you can get the subnet using toPrefixBlock:

print(new IPAddressString("46.114.184.1/21").getAddress().toPrefixBlock().toSequentialRange()); // convert address to its associated CIDR subnet
print(new IPAddressString("46.114.185.0/21").getAddress().toPrefixBlock().toSequentialRange()); 
46.114.184.0 -> 46.114.191.255
46.114.184.0 -> 46.114.191.255

The above is explained in this wiki entry and this entry.

You can also use range notation:

print(new IPAddressString("46.114.184-191.*").getSequentialRange()); // just be explicit
print(new IPAddressString("46.114.184-191.0-255").getSequentialRange());
46.114.184.0 -> 46.114.191.255
46.114.184.0 -> 46.114.191.255

You can also construct addresses individually to specify any given range, including those not corresponding to a CIDR subnet:

print(new IPv4AddressSeqRange(new IPAddressString("46.114.184.1").getAddress().toIPv4(), new IPAddressString("46.114.191.255").getAddress().toIPv4())); // create range directly from boundaries
print(new IPv4AddressSeqRange(new IPAddressString("46.114.185.0").getAddress().toIPv4(), new IPAddressString("46.114.191.255").getAddress().toIPv4()));
46.114.184.1 -> 46.114.191.255
46.114.185.0 -> 46.114.191.255
jms4t commented 7 months ago

Thanks for elaborating, much appreciated.

Actually I have the requirement to parse 46.114.184.1/21 to 46.114.184.1 -> 46.114.191.255.

I think this can be done like this:

new IPv4AddressSeqRange(
                new IPAddressString("46.114.184.1/21").getAddress().toIPv4(),
                new IPAddressString("46.114.184.1/21").getAddress().toPrefixBlock().getUpper().toIPv4()
        );

Can it be done independent of the IP Version? - IPv4 / IPv6 (without if-ipv4, if-ipv6 conditions)

seancfoley commented 7 months ago
String str = "46.114.184.1/21";
IPAddress addr = new IPAddressString(str).getAddress();
IPAddressSeqRange rng = addr.spanWithRange(addr.toPrefixBlock().getUpper());
jms4t commented 7 months ago

Thanks a lot.