IPv6 as a comparable JavaScript string?

拜拜、爱过 提交于 2019-12-04 20:19:38
slebetman

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:

  1. Dotted-quad notation (IPv4 address embedded inside IPv6 address)

  2. Leading zeros may be omitted

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

You don't indicate whether or not third-party libraries are acceptable for your solution, but if they are, I believe you could use the ip-address library and its dependency jsbn to parse each address as a v6 object, call v6.bigInteger() to get the address as a jsbn BigInteger object, then use BigInteger.compareTo to compare the addresses.

Just convert an IPv6 address to four 32-bit unsigned integers and loop over the four integers. I do this all the time:

There are only two things you need for manipulating either IPv4 or IPv6 addresses: the address and the mask. Both of these are the same length per protocol (IPv4=32 bits, IPv6=128 bits). Since I don't have 128-bit unsigned integers, I use an array of four 32-bit unsigned integers for both the IPv6 address and mask. Everything else can be built from those two values.

IPv6 is even easier than IPv4 in finding the first and last addresses since, in IPv6, the first address is the subnet, and the last address is the subnet plus the inverse mask.

Use the ip6 npm package to normalize the IPv6 addresses and then compare them directly.

let ip6 = require('ip6')

console.log(ip6.normalize('2404:6800:4003:808::200e'));
// 2404:6800:4003:0808:0000:0000:0000:200e 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!