'use strict'; exports = module.exports = { isValid, isValidCIDR, isEqual, includes, }; const assert = require('node:assert'), net = require('node:net'); function isValid(ip) { assert.strictEqual(typeof ip, 'string'); const type = net.isIP(ip); return type === 4 || type === 6; } function isValidCIDR(cidr) { assert.strictEqual(typeof cidr, 'string'); const parts = cidr.split('/'); if (parts.length !== 2) return false; const [ ip, prefixString ] = parts; const type = net.isIP(ip); if (type === 0) return false; const prefix = Number.parseInt(prefixString, 10); if (!Number.isInteger(prefix) || prefix < 0 || (prefix > (type === 4 ? 32 : 128)) || String(prefix) !== prefixString) return false; return true; } function isEqual(ip1, ip2) { assert.strictEqual(typeof ip1, 'string'); assert.strictEqual(typeof ip2, 'string'); if (ip1 === ip2) return true; const type1 = net.isIP(ip1), type2 = net.isIP(ip2); if (type1 === 0 || type2 === 0) return false; // otherwise, it will throw invalid socket address below // use blocklist to compare since strings may not be in RFC 5952 format const blockList = new net.BlockList(); blockList.addAddress(ip1, `ipv${type1}`); return blockList.check(ip2, `ipv${type2}`); } function includes(cidr, ip) { assert.strictEqual(typeof cidr, 'string'); assert.strictEqual(typeof ip, 'string'); const type = net.isIP(ip); const [ subnet, prefix ] = cidr.split('/'); const subnetType = net.isIP(subnet); const blockList = new net.BlockList(); blockList.addSubnet(subnet, parseInt(prefix, 10), `ipv${subnetType}`); return blockList.check(ip, `ipv${type}`); }