Wednesday, October 12, 2011

A Java library for IPv6

A while ago, I wrote a library to work with IPv4 concepts (IPv4 addresses, networks, network masks, prefix lengths, ranges of addresses etc) in Scala. Along those lines, I recently created a similar library to work with IPv6 concepts. This time though, I used good old Java.

If you simply need to make IPv6 connections, java.net.Inet6Address will be sufficient. However when doing things a little bit more advanced with the addresses themselves, I find java.net.InetAddress (both Inet4Address and Inet6Address) lacking a lot of functionality.

Here is a short overview of what can be done with my java-ipv6 library.

IPv6Address


The class IPv6Address represents an IPv6 address.

final IPv6Address iPv6Address = IPv6Address.fromString("fe80::226:2dff:fefa:cd1f");
Internally, the IPv6Address class uses two long values to store the IPv6 address. This makes for an optimized implementation, and a lot of bit twiddling fun for me while writing it...

IPv6Address can be used to make simple calculations on IPv6 addresses, such as addition and subtraction.

final IPv6Address iPv6Address = IPv6Address.fromString("fe80::226:2dff:fefa:cd1f");
final IPv6Address next = iPv6Address.add(1);
final IPv6Address previous = iPv6Address.subtract(1);
System.out.println(next.toString()); // prints fe80::226:2dff:fefa:cd20
System.out.println(previous.toString()); // prints fe80::226:2dff:fefa:cd1e

IPv6AddressRange


The class IPv6AddressRange represents a continuous range of consecutive IPv6 addresses.

final IPv6AddressRange range = new IPv6AddressRange(IPv6Address.fromString("fe80::226:2dff:fefa:cd1f"),
                                                    IPv6Address.fromString("fe80::226:2dff:fefa:ffff"));
System.out.println(range.contains(IPv6Address.fromString("fe80::226:2dff:fefa:dcba"))); // prints true
IPv6AddressRange contains methods to iterate over all the addresses in the range. Ranges can be compared with other ranges by checking if they overlap or if one range contains the other range.

IPv6Network


An IPv6Network is a range (extends IPv6AddressRange) that can be expressed as a network address and a prefix length.

final IPv6Network range = new IPv6Network(IPv6Address.fromString("fe80::226:2dff:fefa:0"),
                                          IPv6Address.fromString("fe80::226:2dff:fefa:ffff"));
final IPv6Network network = IPv6Network.fromString("fe80::226:2dff:fefa:0/112");
System.out.println(range.equals(network)); // prints true
Note that every IPv6Network is also an IPv6AddressRange, but not all IPv6AddressRanges are valid IPv6Networks. That is why, when constructing an IPv6Network from a range in between a first address and a last address, the smallest possible IPv6Network (i.e. the one with the longest prefix length) will be constructed.

IPv6AddressPool


An IPv6AddressPool is like a range (extends IPv6AddressRange) of which certain subnets are "allocated" and other are "free".

final IPv6AddressPool pool = new IPv6AddressPool(IPv6Address.fromString("fe80::226:2dff:fefa:0"),
                                                 IPv6Address.fromString("fe80::226:2dff:fefa:ffff"), 120);
System.out.println(pool.isFree(IPv6Network.fromString("fe80::226:2dff:fefa:5ff/120"))); // prints true
final IPv6AddressPool newPool = pool.allocate(IPv6Network.fromString("fe80::226:2dff:fefa:5ff/120"));
System.out.println(newPool.isFree(IPv6Network.fromString("fe80::226:2dff:fefa:5ff/120"))); // prints false

This was only a short introduction. Much more can be done with these types. I invite you to have a look at the javadoc and of course the actual source code.


Immutable


I decided to make all types immutable. For things like IPv6Address and IPv6Network, this obviously makes sense because they represent immutable concepts. For IPv6AddressPool, I was in doubt whether immutability was the right choice. When allocating an address in a pool, immutability means I have to return a new IPv6AddressPool instance. Internally the IPv6AddressPool maintains a SortedSet of all ranges of addresses that are still available in the pool. This SortedSet (TreeSet) thus has to be copied each time a new IPv6AddressPool is to be created. It is not a deep copy (the IPv6AddressRanges in the SortedSet are immutable themselves), but still constructing new TreeSet instances each time seems sub optimal. It would be nice to investigate if I can improve the situation using some kind of persistent data structure to replace the TreeSet. I had a quick look at pcollections, but it doesn't seem to provide an alternative to TreeSet with SortedSet semantics. Other suggestions are much appreciated!