In the age of IPv4 things were easy, because an IPv4 address could be converted into a simple 32-bit integer and then used for all kinds of comparative calculations.
With IPv6 it is a bit more awkward, because for one thing, 128-bit integers are not natively supported by JavaScript, and their conversion isn't straightforward at all. Which only leaves the option of dealing with a string presentation for IPv6.
How to convert an IPv6 address of any known format into a comparable string(s)?
A < B
must produce true
in JavaScript. Similar logic must be valid for the rest of comparisons: ===
, <=
, >
and >=
.Conversion of simplified IPv6 address format to the full format is not too difficult. There are only 3 rules that allows addresses to be simplified. The following are the rules listed in the order they must be undone to convert the address back to the full format:
Dotted-quad notation (IPv4 address embedded inside IPv6 address)
Leading zeros may be omitted
Groups of zeros may be abbreviated with ::
Technically, depending on how you do your processing, 2 and 3 may be swapped.
So here's a simple converter that only converts valid IPv6 addresses (it's guaranteed to fail miserably if you feed it invalid IPv6 address because I'm not doing any validation):
function full_IPv6 (ip_string) {
// replace ipv4 address if any
var ipv4 = ip_string.match(/(.*:)([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$)/);
if (ipv4) {
var ip_string = ipv4[1];
ipv4 = ipv4[2].match(/[0-9]+/g);
for (var i = 0;i < 4;i ++) {
var byte = parseInt(ipv4[i],10);
ipv4[i] = ("0" + byte.toString(16)).substr(-2);
}
ip_string += ipv4[0] + ipv4[1] + ':' + ipv4[2] + ipv4[3];
}
// take care of leading and trailing ::
ip_string = ip_string.replace(/^:|:$/g, '');
var ipv6 = ip_string.split(':');
for (var i = 0; i < ipv6.length; i ++) {
var hex = ipv6[i];
if (hex != "") {
// normalize leading zeros
ipv6[i] = ("0000" + hex).substr(-4);
}
else {
// normalize grouped zeros ::
hex = [];
for (var j = ipv6.length; j <= 8; j ++) {
hex.push('0000');
}
ipv6[i] = hex.join(':');
}
}
return ipv6.join(':');
}
You can probably do the embedded IPv4 processing after the .split(':')
but I've already written it with regexp in mind. As can be seen from the code above, each step of the process is fairly simple. The only thing that tripped me was an off-by-one error in the j<=8
condition in the last for loop.