IPFreely.uk site logo

Niche open source software libraries that treat IP addresses as mathematical types.

Use for arithmetic, bitwise operations, iteration, and arbitrary sets and ranges of IP addresses. Useful for implementing network element management systems, DOCSIS provisioning systems, etc. Supports IPv4 & IPv6.

These libraries do not perform any network I/O but enable conversion to/from standard types that do. Types tend towards immutable values and type safety via generics. Implementations are available for the Java and Go languages.

Implementations 🔗

Java

Feature Java
API documentation Javadoc/javadoc.io
License Apache License Version 2.0
Compatibiliy Java 8 and above
Dependency Hint uk.ipfreely:addresses
Source Code Java Maven Project
Distribution Maven Central

Go

Feature Go
API documentation pkg.go.dev Go Reference
License Apache License Version 2.0
Compatibiliy Go 1.23.1 and above
Dependency Hint github.com/ipfreely-uk/go
Source Code Go Module
Distribution GitHub

Examples 🔗

This Go code picks a random address from a subnet:


// Random IP address from CIDR block
func randFrom[A ip.Int[A]](b ipset.Block[A]) A {
  netAddr := b.First()
  maskComplement := b.Mask().Not()
  f := netAddr.Family()
  slice := make([]byte, f.Width()/8)
  _, _ = rand.Read(slice)
  r := f.MustFromBytes(slice...)
  return r.And(maskComplement).Or(netAddr)
}
    

This Java code subdivides an address block into subnets with a minumum number of allocatable addresses:


/**
 * @param initial   available range
 * @param count     min number of allocatable addresses required
 * @return          stream of subnets
 * @param <A> address family
 */
 static <A extends Addr<A>> Stream<Block<A>> subdivide(Block<A> initial, BigInteger count) {
  Family<A> f = initial.first().family();
  Subnets<A> s = f.subnets();
  // IPv4 networks have 2 reserved numbers
  BigInteger min = (f == Family.v4())
                 ? count.add(BigInteger.valueOf(2))
                 : count;
  int bits = f.width();
  int maskBits = IntStream.rangeClosed(0, bits)
                          .map(i -> bits - i)
                          .filter(m -> s.count(m).compareTo(min) >= 0)
                          .findFirst()
                          .orElseThrow(IllegalArgumentException::new);
  return initial.subnets(maskBits);
}