IPv4/IPv6 network calculations and validation for Java?

11,501

Solution 1

It's only for IPv4, but the SubnetUtils class that is part of Commons Net has the functionality you are looking for. Based on that you could code up an IPv6 version and contribute it back to the project! :)

Solution 2

Maybe CIDRUtils can help you. It enables you to convert CIDR notation to an IP range.

Disclaimer: I am the author of CIDRUtils.

Solution 3

The IPAddress Java library supports both IPv4 and IPv6 in a polymorphic manner including subnets. The javadoc is available at the link. Disclaimer: I am the project manager.

All the use cases you listed are supported for both IPv4 and Ipv6 transparently. In other words, it differs from most other utilities in the sense that the code below works identically with either IPv4 or IPv6 as the input strings.

Verify if an address is valid

    String str = "::1";
    IPAddressString addrString = new IPAddressString(str);
    try {
         IPAddress addr = addrString.toAddress();
         ...
    } catch(IPAddressStringException e) {
        //e.getMessage provides validation issue
    }

Return if address is contained within a subnet

    String str = "1::1";
    String subnetStr = "1::/64";
    IPAddressString addrString = new IPAddressString(str);
    IPAddressString subnetString = new IPAddressString(subnetStr);
    try {
         IPAddress addr = addrString.toAddress();
         IPAddress subnet = subnetString.toAddress();
         boolean isContained = subnet.contains(addr); //true in this case
         ...
    } catch(IPAddressStringException e) {
        //e.getMessage provides validation issue
    }

Return the broadcast address for a given subnet

    String subnet = "127.0.0.0/28";
    IPAddressString subnetString = new IPAddressString(subnet);
    try {
         IPAddress subnet = subnetString.toAddress();
         IPAddress broadcastAddr = subnet.getHighest();
         ...
    } catch(IPAddressStringException e) {
        //e.getMessage provides validation issue
    }

Return a list of addresses for a subnet in order

    String subnet = "127.0.0.0/28";
    IPAddressString subnetString = new IPAddressString(subnet);
    try {
         IPAddress subnet = subnetString.toAddress();
         for(IPAddress addr : subnet) {
             ...
         }
    } catch(IPAddressStringException e) {
        //e.getMessage provides validation issue
    }

Sort a list of addresses

    List<IPAddressString> addrs; 
    Collections.sort(addrs); //IPAddressString implements Comparable

Get set of subnetted networks and list of addresses (response to AhmedRana):

    IPAddress subnet = new IPAddressString("192.168.0.0/28").getAddress();
    IPAddress newSubnets = subnet.adjustPrefixLength(1, false);
    System.out.println(newSubnets); //192.168.0.0-8/29
    HashSet<IPAddress> subnetSet = new HashSet<IPAddress>();
    ArrayList<IPAddress> addrList = new ArrayList<IPAddress>();
    for(IPAddress addr : newSubnets.getIterable()) {
        subnetSet.add(addr.toPrefixBlock());
        addrList.add(addr);
    }
    System.out.println(subnetSet);//[192.168.0.0/29, 192.168.0.8/29]

    System.out.println(addrList);
                //[192.168.0.0/29, 192.168.0.1/29, 192.168.0.2/29,
                //192.168.0.3/29, 192.168.0.4/29, 192.168.0.5/29,
                //192.168.0.6/29, 192.168.0.7/29, 192.168.0.8/29,
                //192.168.0.9/29, 192.168.0.10/29, 192.168.0.11/29,
                //192.168.0.12/29, 192.168.0.13/29, 192.168.0.14/29,
                //192.168.0.15/29]

There can be a lot of addresses. The more efficient way to get the new subnets list is to use the prefix block iterator, which iterates through the prefix block subnets, as shown:

    IPAddress subnet = new IPAddressString("192.168.0.0/28").getAddress();
    IPAddress newSubnets = subnet.adjustPrefixLength(1, false);
    System.out.println(newSubnets); // 192.168.0.0-8/29
    Iterator<? extends IPAddress> iterator = newSubnets.prefixBlockIterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
    }
    // 192.168.0.0/29
    // 192.168.0.8/29

Solution 4

I'm the main contributor of commons-ip-math, an open-source Java library that offers a rich API for dealing with the most common calculations of IPv4, IPv6 and AS numbers. Although it has only been recently open sourced it has been battle-tested for years inside RIPE NCC. See how you can use it below.

(All the examples are working with similar syntax for IPv6 and AS numbers. Just use the Ipv6, Ipv6Range, Asn and AsnRange classes instead).

  • Verify an address is valid (e.g. 127.0.0.1 is valid, 127.0.0.257 is not)
Ipv4.parse("127.0.0.1");     // IPv4 representation of "127.0.0.1"
Ipv4.parse("127.0.0.257");   // IllegalArgumentException
  • Return if an address is contained within a subnet (e.g. 127.0.0.11 is in 127.0.0.0/28)
Ipv4Range.parse("127.0.0.0/28").contains(Ipv4.parse("127.0.0.11"));  //true  
  • Return the broadcast address for a given subnet (e.g. for 127.0.0.0/28 it's 127.0.0.15)
Ipv4Range.parse("127.0.0.0/28").start().upperBoundForPrefix(28)  // 127.0.0.15
  • Return a list of addresses for a subnet in order
// Range types are Iterable
for (Ipv4 ipv4 : Ipv4Range.parse("127.0.0.0/30")) {
  System.out.println(ipv4);
}
// Will print:
127.0.0.0
127.0.0.1
127.0.0.2
127.0.0.3
  • Sort a list of addresses

Although the library offers comparators for range types (e.g. comparing the size of subnets), there is no comparator for single addresses. However, it is fairly trivial to write your own since Ipv4, IPv6 and ASN types implement the Comparable interface:

List<Ipv4> list = new ArrayList<Ipv4>();
list.add(Ipv4.of("0.0.0.3"));
list.add(Ipv4.of("0.0.0.4"));
list.add(Ipv4.of("0.0.0.2"));
list.add(Ipv4.of("0.0.0.1"));
Collections.sort(list, new Comparator<Ipv4>() {
    @Override
    public int compare(Ipv4 left, Ipv4 right) {
        return left.compareTo(right);
    }
});
System.out.println(list);
// Will print:
[0.0.0.1, 0.0.0.2, 0.0.0.3, 0.0.0.4]
Share:
11,501
ttkalec
Author by

ttkalec

I have a degree in Computer Science. This teaches you nothing about making real world programs.

Updated on June 08, 2022

Comments

  • ttkalec
    ttkalec almost 2 years

    I am looking for a package that is similar to Net_IPv4 and Net_IPv6 but written for Java. It needs to be able to do the following:

    • Verify an address is valid (e.g. 127.0.0.1 is valid, 127.0.0.257 is not)
    • Return if an address is contained within a subnet (e.g. 127.0.0.11 is in 127.0.0.0/28)
    • Return the broadcast address for a given subnet (e.g. for 127.0.0.0/28 it's 127.0.0.15)

    It would be awesome if it could also:

    • Return a list of addresses for a subnet in order
    • Sort a list of addresses

    I could probably write a package to do all this, but if someone has already gone through the trouble and most likely has done a better job, I'm all about using that. Anyone know of such a package or packages that could do all this? We are expanding into IPv6, so it needs to work for both IPv4 and IPv6 if possible.

    I appreciate any help.

  • Andrew Barber
    Andrew Barber about 11 years
    Thanks for posting your answer! Please be sure to read the FAQ on Self-Promotion carefully. Also note that it is required that you post a disclaimer every time you link to your own site/product.
  • Edin Dazdarevic
    Edin Dazdarevic about 11 years
    @AndrewBarber Thanks. I was not aware of this. I was just trying to help others who might have the same problem as I was having. Anyway, I'll a disclaimer.
  • Pawel
    Pawel over 8 years
    According to: helpsystems.com/intermapper/ipv6-address-validation and v6decode.com "1:2:3:4:5:6:1.2.3.4" is a Valid IPv6, but Ipv6.parse("1:2:3:4:5:6:1.2.3.4") throws IllegalArgumentException. :/
  • jgonian
    jgonian over 8 years
    For IPv6 addresses with embedded IPv4 addresses like in your example, the library should comply with tools.ietf.org/html/rfc4291#section-2.5.5 . Thus, it is either too strict compared to the websites or you might have found a bug. I'll investigate.
  • jgonian
    jgonian over 8 years
    @Pawel I've created github.com/jgonian/commons-ip-math/issues/2 in order to investigate
  • Pawel
    Pawel over 8 years
    I'm just trying to find replacement for sun.net.util.IPAddressUtil - after switching to Java 8 some of my tests failed. My test cases are taken from: download.dartware.com/thirdparty/test-ipv6-regex.pl (this should be helpful)
  • jgonian
    jgonian over 8 years
    I have released commons-ip-math:1.21 which has better support of IPv6 addresses with embedded IPv4 addresses. You can find it on maven central.
  • Pawel
    Pawel over 8 years
    "1111:2222:3333:4444:5555:6666::1.2.3.4" shouldn't be IPv6, but library parses it into "1111:2222:3333:4444:5555:6666:102:304"
  • jgonian
    jgonian over 8 years
    Thanks for spotting this out. I'll fix it as part of github.com/jgonian/commons-ip-math/issues/4
  • AhmedRana
    AhmedRana over 6 years
    Thanks for the brilliant library. Does your library supports the following. 1. Return list of IP Addresses in a subnet 2. Subnet a network e.g. 192.168.0.0/28 subnet it into two /29 networks. Can it return these both the subneted networks created?
  • Sean F
    Sean F over 6 years
    You're welcome. Yes, it can do those things, I updated the answer with the code for your example, in your example there are two subnets produced, each with 8 addresses. However, in answering your question, I see now that while it can get the list of subnets quite easily and efficiently, getting them as a list or set is easy but not efficient for large subnets (iterating through many addresses), so I'll add a prefix-block iterator method to do that more efficiently which would just iterate through the list of subnetted networks.
  • AhmedRana
    AhmedRana over 6 years
    Thanks Sean, Does any version of this library compatible with JRE 1.5 (or is there a way to make it compatible with 1.5) ? I am interested in IPv4 only.and I have a limitation that it must be run on the system which has Java 5
  • Sean F
    Sean F over 6 years
    @AhmedRana hi, the latest versions of IPAddress use a lot of lambdas (added in java 8) so it would not be easy to port the latest releases of IPAddress. Version 1.0.0 of IPAddress works with Java 7, but that is missing some of the features I've added to the librarysince. Not a lot was added to Java 7, so it would be easy to make that version work with Java 6, however, Java 6 was a major release of Java so it's hard for me to say if version 1.0.0 of IPAddress could be easily made to work with Java 5.
  • Sean F
    Sean F over 6 years
    I would suggest that you could take the code for version 1.0.0, see if you can make that work with Java 5, then if there are things in latest IPAddress that you wish to use, then port only those things. Porting the latest version of IPAddress to Java 5 might be a lot of work, mostly due to the lambda functions in the code.
  • Sean F
    Sean F over 6 years
    Alternatively, you could start with the latest version of IPAddress but port to Java 5 only the things you wish to use. Any lamba function could be replaced with an anonymous class instance with a single method.
  • AhmedRana
    AhmedRana over 6 years
    Thanks. I just re checked. The machine had Java version 1.5 while the websphere is running it's own java which is IBM 1.6 version. I tried porting v1.0 by compiling it in 1.5 but still the machines jvm threw this error. Java.lang.UnsupportedClassVersionError: JVMCFRE003 bad major version; class=inet/ipaddr/IPAddressString, offset=6
  • Sean F
    Sean F over 6 years
    That error means the classes have been compiled to a later java version. If you are using Eclipse to compile, you would need to go to Window->preferences->Java->compiler and change to 1.5 for Java 5. If you are using javac on command line, you need to use "-target 1.5". If Java 6 then the version is 1.6.
  • AhmedRana
    AhmedRana over 6 years
    Reagarding V1.0, Does it supports the following. 1. Return list of IP Addresses in a subnet 2. Subnet a network e.g. 192.168.0.0/28 subnet it into two /29 networks.Can it return these both the subnet networks created? 3. or Join two networks /29 to create single /28 network The examples you provided are not compatible V1.0
  • Sean F
    Sean F over 6 years
    Yeah, a lot was added since 1.0. Probably those things not in that version. 1 and 2 are supported in latest version, and I actually am adding a method to join subnets.