Search code examples
javaipipv6inetaddress

Manipulating IPv6 Addresses in Java


I know similar questions have been asked before, but I haven't been able to find a specific answer which seems to work. I am basically trying to write a function which will take an IPv6 address and add or subtract an arbitrary number of IP addresses to it.

I think I am hitting an issue with byte ordering as it works for some IPv6 addresses but not for others. However, I need some help in trying to work out the problem as I am stuck.

I have provided an SSCCE below which demonstrates the problem - it basically converts from an InetAddress to a BigInteger and back again - the idea is to perform the addition or subtraction from the BigInteger in the middle:

import java.math.*;
import java.net.*;

public class SSCCE {
  public static void main(String[] args) {
    String sIPv6 = "::00D3:0:2F3B:02AA:00FF:0";

    try {
      BigInteger n = new BigInteger(InetAddress.getByName(sIPv6).getAddress());
      byte[] bytes = n.toByteArray();

      System.out.println("Original = " + sIPv6);
      System.out.println("New = " + InetAddress.getByAddress(bytes).getHostAddress());
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

When I run this I get the following output:

Original = ::00D3:0:2F3B:02AA:00FF:0
java.net.UnknownHostException: addr is of illegal length
        at java.net.InetAddress.getByAddress(Unknown Source)
        at java.net.InetAddress.getByAddress(Unknown Source)
        at SSCCE.main(SSCCE.java:12)

However, if I change the IPv6 address to "2001::00D3:0:2F3B:02AA:00FF:0" then it works fine.


Solution

  • The problem is here

      BigInteger n = new BigInteger(InetAddress.getByName(sIPv6).getAddress());
      byte[] bytes = n.toByteArray();
    

    When you invoke toByteArray() the returned array is only large enough to contain all the significant bits of the address. Since your address starts with 0:0:... the returned byte array will be too short (14). You must left-pad it with binary zeros to make it 128 bits long (16 bytes).