From 4aa6a13c1de98667a208e6d3b733558b0c4345d5 Mon Sep 17 00:00:00 2001 From: Eric Vyncke Date: Tue, 30 Jan 2024 20:56:19 +0900 Subject: [PATCH] Add commonPrefixLength() Compute the length of the longest prefix match. --- lib/ipaddr.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/lib/ipaddr.js b/lib/ipaddr.js index d203f0e..5912a53 100644 --- a/lib/ipaddr.js +++ b/lib/ipaddr.js @@ -129,6 +129,30 @@ return true; } + function matchLength(first, second) { + if (first.length !== second.length) { + throw new Error('ipaddr: cannot matchLength for objects with different lengths'); + } + let offset = 0 ; + let length = 0 ; + while (offset < first.length && first[offset] == second[offset]) { + offset++ ; + length += 8 ; + } + let bit = 0x80 ; + let index = 0 ; + if (offset < first.length) { + let a = first[offset] ; + let b = second[offset] ; + while (index < 8 && (a & bit) == (b & bit)) { + index ++ ; + bit = bit >> 1 ; + } + return length + index ; + } else + return length ; + } + function parseIntAuto (string) { // Hexadedimal base 16 (0x#) if (hexRegex.test(string)) { @@ -240,6 +264,15 @@ return matchCIDR(this.octets, other.octets, 8, cidrRange); }; + IPv4.prototype.commonPrefixLength = function (other) { + if (other.kind() !== 'ipv4') { + throw new Error('ipaddr: cannot match ipv6 address with non-ipv6 one'); + } + + return matchLength(this.toByteArray(), other.toByteArray()) ; + } + + // returns a number of leading ones in IPv4 address, making sure that // the rest is a solid sequence of 0's (valid netmask) // returns either the CIDR length or null if mask is not valid @@ -602,6 +635,14 @@ return matchCIDR(this.parts, other.parts, 16, cidrRange); }; + IPv6.prototype.commonPrefixLength = function (other) { + if (other.kind() !== 'ipv6') { + throw new Error('ipaddr: cannot match ipv6 address with non-ipv6 one'); + } + + return matchLength(this.toByteArray(), other.toByteArray()) ; + } + // returns a number of leading ones in IPv6 address, making sure that // the rest is a solid sequence of 0's (valid netmask) // returns either the CIDR length or null if mask is not valid