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.
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! :)
Maybe CIDRUtils can help you. It enables you to convert CIDR notation to an IP range.
Disclaimer: I am the author of CIDRUtils.
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
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]
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
The InetAddress class, and related subclasses, would be a very good place to start:
http://java.sun.com/j2se/1.4.2/docs/api/java/net/InetAddress.html