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.
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).