-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IPv6Address with prefix length and zone to Inet6Address conversion issue #48
Comments
As you've indicated, InetAddress and Inet6Address do not accept addresses with prefix length aka subnet mask (the /64). I can add code to drop the prefix length first before attempting the conversion. As a workaround, you can do so as well, you can call However, after dropping the prefix length, the address string that is used by the code at that line above has wildcards (fe80:0:0:0:*:*:*:* and not fe80:0:0:0:0:0:0:0). So that causes an exception too. So I will add code to handle that as well. Thirdly, it seems the interface name must match an interface on the system (ie there must be an eth13). I assume it does in your case, but if not, that would also cause an exception. So as a work-around, the following can work: IPAddressString str = new IPAddressString("fe80::%eth13/64");
IPAddress addr = str.getAddress();
InetAddress inetAddr = addr.withoutPrefixLength().getLower().toInetAddress(); // drop /64 and take lower address
System.out.println(inetAddr);
inetAddr = addr.getLower().withoutPrefixLength().toInetAddress(); // or change order of calls
System.out.println(inetAddr); Output:
|
I have already found the workaround to drop the prefix length for the address that works fine now. I can't really say what I expected but the behavior seems to be different for ipv4 addresses with a prefix length therefore I wondered why the code worked for ipv4 addresses but not ipv6. |
Yes, well I will be fixing this because the method should not fail the conversion, it should use the lower address without the prefix length to generate the InetAddress, that is the intended and expected behaviour. That is what happens with IPv4 (there are no scopes or zones but it does drop the prefix length). For IPv4, since there are no scopes or zones, the code is a bit different and works correctly. |
Just wanted to note that the conversion from IPAddress to InetAddress for ipv6 with zones is a "heavy" operation because the Inet6Address JRE class calls "initstr" in the constructor which will do a NetworkInterface.getByName call which can take a couple of cycles. In loops or performance critical areas it is therefore not a good idea to call "toInetAddress" very often. private static InetAddress toInetAddress(InetAddress origin, IPAddress libAddress) {
InetAddress inetAddress;
// the Inet6Address constructor used by the IPAddress library for IPv6 needs a native network interface lookup when a scroped interface is set which is a
// pretty heavy operation
// therefore we use our custom method for those cases
if (origin instanceof Inet6Address) {
Inet6Address inet6Address = (Inet6Address) origin;
try {
inetAddress = Inet6Address.getByAddress(null, libAddress.getBytes(), inet6Address.getScopedInterface());
} catch (UnknownHostException e) {
inetAddress = null;
}
} else {
inetAddress = libAddress.toInetAddress();
}
return inetAddress;
} By calling the Inet6Address constructor which takes a NetworkInterface there is no lookup cost. |
Thanks for that info. The network interface lookup is indeed excessively costly and I am thinking of better integration of IPv6Address with NetworkInterface to avoid this lookup when it is not necessary. |
I've addressed these issues in the latest version 5.3.3. If you create addresses with zones from strings, then the library will look up the interface, just once for each interface. If you create addresses directly, you can supply an IPv6Zone object, which can be shared amongst addresses. May operations retain the zone, but if you use operations that do not (like merge or span operations), then you can add back the zone with setZone following the operation. Since zone objects are shared, and they hold NetworkInterface objects, that will ensure NetworkInterface.getByName is not repeatedly called. Also, the original issue is fixed, the issue of converting an address with zone to Inet6Address. |
When an ipv6 address with a zone and a associated prefix length is converted to an JRE Inet6Address null is returned because the JRE can't parse the subnet mask. E.g. when an address like this is constructed:
"fe80::%eth13/64"
Then an exception is thrown here because the zone is not numeric (eth13):
https://github.com/seancfoley/IPAddress/blob/master/IPAddress/src/inet.ipaddr/inet/ipaddr/ipv6/IPv6Address.java#L1781
and converted to a normalized string which is "fe80:0:0:0:0:0:0:0%eth13/64" which will result in an UnknownHostException from the JRE because of following error:
"java.net.UnknownHostException: no such interface eth13/64"
The text was updated successfully, but these errors were encountered: