ip-subnet-calculator
Advanced tools
Comparing version 1.1.8 to 2.0.0
@@ -1,2 +0,2 @@ | ||
var ipsc = require( 'ip-subnet-calculator' ); | ||
const ipsc = require( 'ip-subnet-calculator' ); | ||
@@ -3,0 +3,0 @@ console.log( 'Is "127.0.0.1" an IP?', ipsc.isIp( '127.0.0.1' ) ); |
@@ -1,11 +0,8 @@ | ||
'use strict'; | ||
/** | ||
* @namespace | ||
* @author Aleksi Asikainen | ||
* @link https://github.com/franksrevenge/IPSubnetCalculator | ||
* @link https://github.com/salieri/IPSubnetCalculator | ||
* | ||
* IpSubnetCalculator 1.1.0 | ||
* IpSubnetCalculator 2.0.0 | ||
* | ||
* Copyright (c) 2013-2016, Aleksi Asikainen | ||
* Copyright (c) 2013-2024, Aleksi Asikainen | ||
* All rights reserved. | ||
@@ -16,3 +13,2 @@ * | ||
* | ||
* | ||
* Designed for: | ||
@@ -23,7 +19,7 @@ * | ||
* | ||
* E.g. range 10.0.1.255 - 10.0.3.255 should result in: | ||
* E.g. range `10.0.1.255 - 10.0.3.255` should result in: | ||
* | ||
* 10.0.1.255/32 | ||
* 10.0.2.0/24 | ||
* 10.0.3.0/24 | ||
* `10.0.1.255/32` | ||
* `10.0.2.0/24` | ||
* `10.0.3.0/24` | ||
* | ||
@@ -38,392 +34,310 @@ * 2) Calculating subnets from an IP and bitmask size | ||
*/ | ||
var IpSubnetCalculator = { | ||
/** | ||
* Calculates an optimal set of IP masks for the given IP address range | ||
* | ||
* @param {string|number} ipStart Lowest IP in the range to be calculated | ||
* @param {string|number} ipEnd Highest IP (inclusive) in the range to be calculated | ||
* | ||
* @return The function returns null in case of an error. Otherwise, an array containing one or more subnet | ||
* masks is returned: | ||
* | ||
* <code>var result = [ | ||
* { | ||
* ipLow : 2071689984, | ||
* ipLowStr : "123.123.123.0", | ||
* ipHigh : 2071690239, | ||
* ipHighStr : "123.123.123.255", | ||
* prefixMask : 4294967040, | ||
* prefixMaskStr : "255.255.255.0", | ||
* prefixSize : 24, | ||
* invertedMask : 255, | ||
* invertedMaskStr : "0.0.0.255", | ||
* invertedMaskSize : 8 | ||
* }, | ||
* | ||
* ... | ||
* ]; | ||
* </code> | ||
* @public | ||
*/ | ||
calculate : function( ipStart, ipEnd ) | ||
{ | ||
var ipStartNum, ipEndNum, ipCurNum; | ||
var rangeCollection = []; | ||
try | ||
{ | ||
ipStartNum = this.toDecimal( ipStart ); | ||
ipEndNum = this.toDecimal( ipEnd ); | ||
} | ||
catch( err ) | ||
{ | ||
return null; | ||
} | ||
if( ipEndNum < ipStartNum ) | ||
{ | ||
return null; | ||
} | ||
ipCurNum = ipStartNum; | ||
while( ipCurNum <= ipEndNum ) | ||
{ | ||
var optimalRange = this.getOptimalRange( ipCurNum, ipEndNum ); | ||
if( optimalRange === null ) | ||
{ | ||
return null; | ||
} | ||
rangeCollection.push( optimalRange ); | ||
ipCurNum = optimalRange.ipHigh + 1; | ||
} | ||
return rangeCollection; | ||
}, | ||
/** | ||
* Calculates a subnet mask from CIDR prefix. | ||
* | ||
* @param {string|number} ip IP address ("2.3.4.5") | ||
* @param {int} prefixSize Number of relevant bits in the subnet mask (24) | ||
* @return {object|null} Returns null in case of an error, and a subnet data object otherwise. | ||
* For details about the subnet data object, see documentation of | ||
* getMaskRange() | ||
* @public | ||
*/ | ||
calculateSubnetMask : function( ip, prefixSize ) | ||
{ | ||
var ipNum; | ||
try | ||
{ | ||
ipNum = this.toDecimal( ip ); | ||
} | ||
catch( err ) | ||
{ | ||
return null; | ||
} | ||
return this.getMaskRange( ipNum, prefixSize ); | ||
}, | ||
/** | ||
* Calculates a CIDR prefix from subnet mask. | ||
* | ||
* @param {string|number} ip IP address ("2.3.4.5") | ||
* @param {string|number} subnetMask IP subnet mask ("255.255.255.0") | ||
* @return {object|null} Returns `null` in case of an error, and a subnet data object otherwise. | ||
* For details about the subnet data object, see documentation of | ||
* getMaskRange() | ||
* @public | ||
*/ | ||
calculateCIDRPrefix : function( ip, subnetMask ) | ||
{ | ||
var ipNum, | ||
subnetMaskNum, | ||
prefix = 0, | ||
newPrefix = 0, | ||
prefixSize; | ||
try | ||
{ | ||
ipNum = this.toDecimal( ip ); | ||
subnetMaskNum = this.toDecimal( subnetMask ); | ||
} | ||
catch( err ) | ||
{ | ||
return null; | ||
} | ||
for( prefixSize = 0; prefixSize < 32; prefixSize++ ) | ||
{ | ||
newPrefix = ( prefix + ( 1 << ( 32 - ( prefixSize + 1 ) ) ) ) >>> 0; | ||
if( ( ( subnetMaskNum & newPrefix ) >>> 0 ) !== newPrefix ) | ||
{ | ||
break; | ||
} | ||
prefix = newPrefix; | ||
} | ||
return this.getMaskRange( ipNum, prefixSize ); | ||
}, | ||
/** | ||
* Finds the largest subnet mask that begins from ipNum and does not | ||
* exceed ipEndNum. | ||
* | ||
* @param {int} ipNum IP start point (inclusive) | ||
* @param {int} ipEndNum IP end point (inclusive) | ||
* @return {object|null} Returns `null` on failure, otherwise an object with the following fields: | ||
* | ||
* ipLow - Decimal representation of the lowest IP address in the subnet | ||
* ipLowStr - String representation of the lowest IP address in the subnet | ||
* ipHigh - Decimal representation of the highest IP address in the subnet | ||
* ipHighStr - String representation of the highest IP address in the subnet | ||
* prefixMask - Bitmask matching prefixSize | ||
* prefixMaskStr - String / IP representation of the bitmask | ||
* prefixSize - Size of the prefix | ||
* invertedMask - Bitmask matching the inverted subnet mask | ||
* invertedMaskStr - String / IP representation of the inverted mask | ||
* invertedSize - Number of relevant bits in the inverted mask | ||
* @private | ||
*/ | ||
getOptimalRange : function( ipNum, ipEndNum ) | ||
{ | ||
var prefixSize, | ||
optimalRange = null; | ||
for( prefixSize = 32; prefixSize >= 0; prefixSize-- ) | ||
{ | ||
var maskRange = this.getMaskRange( ipNum, prefixSize ); | ||
if( ( maskRange.ipLow === ipNum ) && ( maskRange.ipHigh <= ipEndNum ) ) | ||
{ | ||
optimalRange = maskRange; | ||
} | ||
else | ||
{ | ||
break; | ||
} | ||
} | ||
return optimalRange; | ||
}, | ||
/** | ||
* Calculates details of a CIDR subnet | ||
* | ||
* @param {int} ipNum Decimal IP address | ||
* @param {int} prefixSize Subnet mask size in bits | ||
* @return {object} Returns an object with the following fields: | ||
* | ||
* ipLow - Decimal representation of the lowest IP address in the subnet | ||
* ipLowStr - String representation of the lowest IP address in the subnet | ||
* ipHigh - Decimal representation of the highest IP address in the subnet | ||
* ipHighStr - String representation of the highest IP address in the subnet | ||
* prefixMask - Bitmask matching prefixSize | ||
* prefixMaskStr - String / IP representation of the bitmask | ||
* prefixSize - Size of the prefix | ||
* invertedMask - Bitmask matching the inverted subnet mask | ||
* invertedMaskStr - String / IP representation of the inverted mask | ||
* invertedSize - Number of relevant bits in the inverted mask | ||
* @private | ||
*/ | ||
getMaskRange : function( ipNum, prefixSize ) | ||
{ | ||
var prefixMask = this.getPrefixMask( prefixSize ), | ||
lowMask = this.getMask( 32 - prefixSize ), | ||
ipLow = ( ipNum & prefixMask ) >>> 0, | ||
ipHigh = ( ( ( ipNum & prefixMask ) >>> 0 ) + lowMask ) >>> 0; | ||
return { | ||
ipLow : ipLow, | ||
ipLowStr : this.toString( ipLow ), | ||
ipHigh : ipHigh, | ||
ipHighStr : this.toString( ipHigh ), | ||
prefixMask : prefixMask, | ||
prefixMaskStr : this.toString( prefixMask ), | ||
prefixSize : prefixSize, | ||
invertedMask : lowMask, | ||
invertedMaskStr : this.toString( lowMask ), | ||
invertedSize : 32 - prefixSize | ||
}; | ||
}, | ||
/** | ||
* Creates a bitmask with maskSize leftmost bits set to one | ||
* | ||
* @param {int} prefixSize Number of bits to be set | ||
* @return {int} Returns the bitmask | ||
* @private | ||
*/ | ||
getPrefixMask : function( prefixSize ) | ||
{ | ||
var mask = 0, | ||
i; | ||
for( i = 0; i < prefixSize; i++ ) | ||
{ | ||
mask += ( 1 << ( 32 - ( i + 1 ) ) ) >>> 0; | ||
} | ||
return mask; | ||
}, | ||
/** | ||
* Creates a bitmask with maskSize rightmost bits set to one | ||
* | ||
* @param {int} maskSize Number of bits to be set | ||
* @return {int} Returns the bitmask | ||
* @private | ||
*/ | ||
getMask : function( maskSize ) | ||
{ | ||
var mask = 0, | ||
i; | ||
for( i = 0; i < maskSize; i++ ) | ||
{ | ||
mask += ( 1 << i ) >>> 0; | ||
} | ||
return mask; | ||
}, | ||
/** | ||
* Test whether string is an IP address | ||
* @param {string} ip | ||
* @returns {boolean} | ||
* @public | ||
*/ | ||
isIp : function( ip ) | ||
{ | ||
if( typeof ip !== 'string' ) | ||
{ | ||
return false; | ||
} | ||
var parts = ip.match( /^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/ ); | ||
if( parts === null ) | ||
{ | ||
return false; | ||
} | ||
for( var i = 1; i <= 4; i++ ) | ||
{ | ||
var n = parseInt( parts[ i ], 10 ); | ||
if( ( n > 255 ) || ( n < 0 ) ) | ||
{ | ||
return false; | ||
} | ||
} | ||
return true; | ||
}, | ||
/** | ||
* Test whether number is an IP address | ||
* @param {number} ipNum | ||
* @returns {boolean} | ||
* @public | ||
*/ | ||
isDecimalIp : function( ipNum ) | ||
{ | ||
return ( | ||
( typeof ipNum === 'number' ) && // is this a number? | ||
( ipNum % 1 === 0 ) && // does the number have a decimal place? | ||
( ipNum >= 0 ) && | ||
( ipNum <= 4294967295 ) | ||
); | ||
}, | ||
/** | ||
* Converts string formatted IPs to decimal representation | ||
* | ||
* @link http://javascript.about.com/library/blipconvert.htm | ||
* @param {string|number} ipString IP address in string format. If a decimal representation given, it is returned unmodified. | ||
* @return {int} Returns the IP address in decimal format | ||
* @throws {Error} Throws an error, if `ipString` does not contain an IP address. | ||
* @private | ||
*/ | ||
toDecimal : function( ipString ) | ||
{ | ||
if( ( typeof ipString === 'number' ) && ( this.isDecimalIp( ipString ) === true ) ) | ||
{ | ||
return ipString; | ||
} | ||
if( this.isIp( ipString ) === false ) | ||
{ | ||
throw new Error( 'Not an IP address: ' + ipString ); | ||
} | ||
var d = ipString.split( '.' ); | ||
return ( ( ( ( ( ( +d[ 0 ] ) * 256 ) + ( +d [ 1 ] ) ) * 256 ) + ( +d[ 2 ] ) ) * 256 ) + ( +d[ 3 ] ); | ||
}, | ||
/** | ||
* Converts decimal IPs to string representation | ||
* | ||
* @link http://javascript.about.com/library/blipconvert.htm | ||
* @param {int} ipNum IP address in decimal format. If a string representation is given, it is returned unmodified. | ||
* @return {string} Returns the IP address in string format | ||
* @throws {Error} Throws an error, if `ipNum` is out of range, not a decimal, or not a number | ||
* @private | ||
*/ | ||
toString : function( ipNum ) | ||
{ | ||
if( ( typeof ipNum === 'string' ) && ( this.isIp( ipNum ) === true ) ) | ||
{ | ||
return ipNum; | ||
} | ||
if( this.isDecimalIp( ipNum ) === false ) | ||
{ | ||
throw new Error( 'Not a numeric IP address: ' + ipNum ); | ||
} | ||
var d = ipNum % 256; | ||
for( var i = 3; i > 0; i-- ) | ||
{ | ||
ipNum = Math.floor( ipNum / 256 ); | ||
d = ipNum % 256 + '.' + d; | ||
} | ||
return d; | ||
} | ||
/** | ||
* Creates a bitmask with maskSize leftmost bits set to one | ||
* | ||
* @param {int} prefixSize Number of bits to be set | ||
* @return {int} Returns the bitmask | ||
* @private | ||
*/ | ||
export const getPrefixMask = (prefixSize) => { | ||
let mask = 0; | ||
let i; | ||
for (i = 0; i < prefixSize; i += 1) { | ||
// eslint-disable-next-line no-bitwise | ||
mask += (1 << (32 - (i + 1))) >>> 0; | ||
} | ||
return mask; | ||
}; | ||
if( ( typeof define === 'function' ) && ( define.amd ) ) | ||
{ | ||
define( [], function() { return IpSubnetCalculator; } ); | ||
/** | ||
* Creates a bitmask with maskSize rightmost bits set to one | ||
* | ||
* @param {int} maskSize Number of bits to be set | ||
* @return {int} Returns the bitmask | ||
* @private | ||
*/ | ||
export const getMask = (maskSize) => { | ||
let mask = 0; | ||
let i; | ||
for (i = 0; i < maskSize; i += 1) { | ||
// eslint-disable-next-line no-bitwise | ||
mask += (1 << i) >>> 0; | ||
} | ||
return mask; | ||
}; | ||
/** | ||
* Test whether string is an IP address | ||
* @param {string} ip | ||
* @returns {boolean} | ||
* @public | ||
*/ | ||
export const isIp = (ip) => { | ||
if (typeof ip !== 'string') { | ||
return false; | ||
} | ||
const parts = ip.match(/^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/); | ||
if (parts === null) { | ||
return false; | ||
} | ||
for (let i = 1; i <= 4; i += 1) { | ||
const n = parseInt(parts[i], 10); | ||
if (n > 255 || n < 0) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
}; | ||
/** | ||
* Test whether number is an IP address | ||
* @param {number} ipNum | ||
* @returns {boolean} | ||
* @public | ||
*/ | ||
export const isDecimalIp = (ipNum) => { | ||
return (typeof ipNum === 'number' && // is this a number? | ||
ipNum % 1 === 0 && // does the number have a decimal place? | ||
ipNum >= 0 && | ||
ipNum <= 4294967295); | ||
}; | ||
/** | ||
* Converts string formatted IPs to decimal representation | ||
* | ||
* @link http://javascript.about.com/library/blipconvert.htm | ||
* @param {string|number} ipString IP address in string format. If a decimal representation given, it is returned unmodified. | ||
* @return {int} Returns the IP address in decimal format | ||
* @throws {Error} Throws an error, if `ipString` does not contain an IP address. | ||
* @private | ||
*/ | ||
export const toDecimal = (ipString) => { | ||
if (typeof ipString === 'number' && isDecimalIp(ipString)) { | ||
return ipString; | ||
} | ||
if (typeof ipString !== 'string' || !isIp(ipString)) { | ||
throw new Error(`Not an IP address: ${ipString}`); | ||
} | ||
const d = ipString.split('.'); | ||
return ((+d[0] * 256 + +d[1]) * 256 + +d[2]) * 256 + +d[3]; | ||
}; | ||
/** | ||
* Converts decimal IPs to string representation | ||
* | ||
* @link http://javascript.about.com/library/blipconvert.htm | ||
* @param {int} ipNum IP address in decimal format. If a string representation is given, it is returned unmodified. | ||
* @return {string} Returns the IP address in string format | ||
* @throws {Error} Throws an error, if `ipNum` is out of range, not a decimal, or not a number | ||
* @private | ||
*/ | ||
export const toString = (ipNum) => { | ||
if (typeof ipNum === 'string' && isIp(ipNum)) { | ||
return ipNum; | ||
} | ||
if (typeof ipNum !== 'number' || !isDecimalIp(ipNum)) { | ||
throw new Error(`Not a numeric IP address: ${ipNum}`); | ||
} | ||
let d = `${ipNum % 256}`; | ||
let curIp = ipNum; | ||
for (let i = 3; i > 0; i -= 1) { | ||
curIp = Math.floor(curIp / 256); | ||
d = `${curIp % 256}.${d}`; | ||
} | ||
return d; | ||
}; | ||
/** | ||
* Calculates details of a CIDR subnet | ||
* | ||
* @param {int} ipNum Decimal IP address | ||
* @param {int} prefixSize Subnet mask size in bits | ||
* @return {object} Returns an object with the following fields: | ||
* | ||
* ipLow - Decimal representation of the lowest IP address in the subnet | ||
* ipLowStr - String representation of the lowest IP address in the subnet | ||
* ipHigh - Decimal representation of the highest IP address in the subnet | ||
* ipHighStr - String representation of the highest IP address in the subnet | ||
* prefixMask - Bitmask matching prefixSize | ||
* prefixMaskStr - String / IP representation of the bitmask | ||
* prefixSize - Size of the prefix | ||
* invertedMask - Bitmask matching the inverted subnet mask | ||
* invertedMaskStr - String / IP representation of the inverted mask | ||
* invertedMaskSize - Number of relevant bits in the inverted mask | ||
* @private | ||
*/ | ||
export const getMaskRange = (ipNum, prefixSize) => { | ||
const prefixMask = getPrefixMask(prefixSize); | ||
const lowMask = getMask(32 - prefixSize); | ||
// eslint-disable-next-line no-bitwise | ||
const ipLow = (ipNum & prefixMask) >>> 0; | ||
// eslint-disable-next-line no-bitwise | ||
const ipHigh = (((ipNum & prefixMask) >>> 0) + lowMask) >>> 0; | ||
return { | ||
ipLow, | ||
ipLowStr: toString(ipLow), | ||
ipHigh, | ||
ipHighStr: toString(ipHigh), | ||
prefixMask, | ||
prefixMaskStr: toString(prefixMask), | ||
prefixSize, | ||
invertedMask: lowMask, | ||
invertedMaskStr: toString(lowMask), | ||
invertedMaskSize: 32 - prefixSize, | ||
}; | ||
}; | ||
/** | ||
* Finds the largest subnet mask that begins from ipNum and does not | ||
* exceed ipEndNum. | ||
* | ||
* @param {int} ipNum IP start point (inclusive) | ||
* @param {int} ipEndNum IP end point (inclusive) | ||
* @return {object|null} Returns `null` on failure, otherwise an object with the following fields: | ||
* | ||
* ipLow - Decimal representation of the lowest IP address in the subnet | ||
* ipLowStr - String representation of the lowest IP address in the subnet | ||
* ipHigh - Decimal representation of the highest IP address in the subnet | ||
* ipHighStr - String representation of the highest IP address in the subnet | ||
* prefixMask - Bitmask matching prefixSize | ||
* prefixMaskStr - String / IP representation of the bitmask | ||
* prefixSize - Size of the prefix | ||
* invertedMask - Bitmask matching the inverted subnet mask | ||
* invertedMaskStr - String / IP representation of the inverted mask | ||
* invertedMaskSize - Number of relevant bits in the inverted mask | ||
* @private | ||
*/ | ||
export const getOptimalRange = (ipNum, ipEndNum) => { | ||
let prefixSize; | ||
let optimalRange = null; | ||
for (prefixSize = 32; prefixSize >= 0; prefixSize -= 1) { | ||
const maskRange = getMaskRange(ipNum, prefixSize); | ||
if (maskRange.ipLow === ipNum && maskRange.ipHigh <= ipEndNum) { | ||
optimalRange = maskRange; | ||
} | ||
else { | ||
break; | ||
} | ||
} | ||
return optimalRange; | ||
}; | ||
/** | ||
* Calculates an optimal set of IP masks for the given IP address range | ||
* | ||
* @param {string|number} ipStart Lowest IP in the range to be calculated | ||
* @param {string|number} ipEnd Highest IP (inclusive) in the range to be calculated | ||
* | ||
* @return The function returns `null` in case of an error. Otherwise, an array containing one or more subnet | ||
* masks is returned: | ||
* | ||
* ``` | ||
* const result = [ | ||
* { | ||
* ipLow : 2071689984, | ||
* ipLowStr : "123.123.123.0", | ||
* ipHigh : 2071690239, | ||
* ipHighStr : "123.123.123.255", | ||
* prefixMask : 4294967040, | ||
* prefixMaskStr : "255.255.255.0", | ||
* prefixSize : 24, | ||
* invertedMask : 255, | ||
* invertedMaskStr : "0.0.0.255", | ||
* invertedMaskSize : 8 | ||
* }, | ||
* | ||
* ... | ||
* ]; | ||
* ``` | ||
* @public | ||
*/ | ||
export const calculate = (ipStart, ipEnd) => { | ||
let ipStartNum; | ||
let ipEndNum; | ||
let ipCurNum; | ||
const rangeCollection = []; | ||
try { | ||
ipStartNum = toDecimal(ipStart); | ||
ipEndNum = toDecimal(ipEnd); | ||
} | ||
catch (err) { | ||
return null; | ||
} | ||
if (ipEndNum < ipStartNum) { | ||
return null; | ||
} | ||
ipCurNum = ipStartNum; | ||
while (ipCurNum <= ipEndNum) { | ||
const optimalRange = getOptimalRange(ipCurNum, ipEndNum); | ||
if (optimalRange === null) { | ||
return null; | ||
} | ||
rangeCollection.push(optimalRange); | ||
ipCurNum = optimalRange.ipHigh + 1; | ||
} | ||
return rangeCollection; | ||
}; | ||
/** | ||
* Calculates a subnet mask from CIDR prefix. | ||
* | ||
* @param {string|number} ip IP address ("2.3.4.5") | ||
* @param {int} prefixSize Number of relevant bits in the subnet mask (24) | ||
* @return {SubnetAnalysis|null} Returns null in case of an error, and a subnet data object otherwise. | ||
* For details about the subnet data object, see documentation of | ||
* getMaskRange() | ||
* @public | ||
*/ | ||
export const calculateSubnetMask = (ip, prefixSize) => { | ||
let ipNum; | ||
try { | ||
ipNum = toDecimal(ip); | ||
} | ||
catch (err) { | ||
return null; | ||
} | ||
return getMaskRange(ipNum, prefixSize); | ||
}; | ||
/** | ||
* Calculates a CIDR prefix from subnet mask. | ||
* | ||
* @param {string|number} ip IP address ("2.3.4.5") | ||
* @param {string|number} subnetMask IP subnet mask ("255.255.255.0") | ||
* @return {SubnetAnalysis|null} Returns `null` in case of an error, and a subnet data object otherwise. | ||
* For details about the subnet data object, see documentation of | ||
* getMaskRange() | ||
* @public | ||
*/ | ||
export const calculateCIDRPrefix = (ip, subnetMask) => { | ||
let ipNum; | ||
let subnetMaskNum; | ||
let prefix = 0; | ||
let newPrefix = 0; | ||
let prefixSize; | ||
try { | ||
ipNum = toDecimal(ip); | ||
subnetMaskNum = toDecimal(subnetMask); | ||
} | ||
catch (err) { | ||
return null; | ||
} | ||
for (prefixSize = 0; prefixSize < 32; prefixSize += 1) { | ||
// eslint-disable-next-line no-bitwise | ||
newPrefix = (prefix + (1 << (32 - (prefixSize + 1)))) >>> 0; | ||
// eslint-disable-next-line no-bitwise | ||
if ((subnetMaskNum & newPrefix) >>> 0 !== newPrefix) { | ||
break; | ||
} | ||
prefix = newPrefix; | ||
} | ||
return getMaskRange(ipNum, prefixSize); | ||
}; | ||
// @ts-expect-error browser export | ||
if (typeof window !== 'undefined') { | ||
// @ts-expect-error browser export | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access | ||
window.IPSubnetCalculator = { | ||
calculate, | ||
calculateSubnetMask, | ||
calculateCIDRPrefix, | ||
getOptimalRange, | ||
getMaskRange, | ||
toString, | ||
toDecimal, | ||
isDecimalIp, | ||
isIp, | ||
getMask, | ||
getPrefixMask, | ||
}; | ||
} | ||
else if( typeof exports === 'object' ) | ||
{ | ||
module.exports = IpSubnetCalculator; | ||
} | ||
@@ -5,9 +5,11 @@ { | ||
"description": "Calculate optimal subnet masks for standard and non-standard IP ranges", | ||
"homepage": "https://github.com/franksrevenge/IPSubnetCalculator", | ||
"version": "1.1.8", | ||
"homepage": "https://github.com/salieri/IPSubnetCalculator", | ||
"version": "2.0.0", | ||
"files": [ | ||
"lib", | ||
"examples" | ||
"examples", | ||
"README.md" | ||
], | ||
"main": "lib/ip-subnet-calculator.js", | ||
"types": "lib/ip-subnet-calculator.d.ts", | ||
"keywords": [ | ||
@@ -28,18 +30,40 @@ "ip", | ||
"devDependencies": { | ||
"coveralls": "^2.11.9", | ||
"istanbul": "^0.4.3", | ||
"lodash": "^4.12.0", | ||
"mocha": "^2.4.0", | ||
"mocha-istanbul": "^0.2.0", | ||
"mocha-lcov-reporter": "^1.2.0", | ||
"should": "^8.3.0" | ||
"@types/lodash": "^4.14.202", | ||
"@types/mocha": "^10.0.6", | ||
"@typescript-eslint/eslint-plugin": "^7.0.1", | ||
"@typescript-eslint/parser": "^7.0.1", | ||
"esbuild": "^0.20.1", | ||
"eslint": "^8.56.0", | ||
"eslint-import-resolver-typescript": "^3.6.1", | ||
"eslint-plugin-import": "^2.29.1", | ||
"eslint-plugin-jest": "^27.9.0", | ||
"eslint-config-airbnb-base": "^15.0.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"eslint-plugin-prefer-arrow": "^1.2.3", | ||
"eslint-plugin-prettier": "^5.1.3", | ||
"eslint-plugin-promise": "^6.1.1", | ||
"eslint-plugin-simple-import-sort": "^12.0.0", | ||
"eslint-plugin-unicorn": "^51.0.1", | ||
"lodash": "^4.17.21", | ||
"mocha": "^10.3.0", | ||
"should": "^13.2.3", | ||
"prettier": "^3.2.5", | ||
"rimraf": "^5.0.5", | ||
"ts-node": "^10.9.1", | ||
"typescript": "^5.3.3" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/franksrevenge/IPSubnetCalculator.git" | ||
"url": "git://github.com/salieri/IPSubnetCalculator.git" | ||
}, | ||
"scripts": { | ||
"test": "mocha" | ||
"test": "mocha", | ||
"prebuild": "rimraf dist", | ||
"build": "tsc --project tsconfig.build.json && esbuild ./lib/ip-subnet-calculator.js --bundle --outfile=./lib/ip-subnet-calculator.browser.js --minify --platform=browser", | ||
"build:watch": "tsc --watch", | ||
"lint": "npm run lint:eslint", | ||
"lint:eslint": "eslint './src/**/*.ts?(x)' --max-warnings 0", | ||
"start": "npx http-server ." | ||
}, | ||
"tonicExampleFilename": "examples/tonic.js" | ||
} |
144
README.md
IP Subnet Calculator | ||
================= | ||
JavaScript class for calculating optimal subnet masks for non-standard IP ranges, e.g. 5.4.3.21 - 6.7.8.9 | ||
JavaScript class for calculating optimal subnet masks for non-standard IP ranges, e.g. `5.4.3.21 - 6.7.8.9` | ||
[View demo](http://franksrevenge.github.io/IPSubnetCalculator/) | ||
[View demo](http://salieri.github.io/IPSubnetCalculator/) | ||
[![Build Status](https://travis-ci.org/franksrevenge/IPSubnetCalculator.svg?branch=master)](https://travis-ci.org/franksrevenge/IPSubnetCalculator) [![Coverage Status](https://coveralls.io/repos/github/franksrevenge/IPSubnetCalculator/badge.svg?branch=master)](https://coveralls.io/github/franksrevenge/IPSubnetCalculator?branch=master) [![Dependency Status](https://david-dm.org/franksrevenge/IPSubnetCalculator/status.svg)](https://david-dm.org/franksrevenge/IPSubnetCalculator#info=dependencies&view=table) [![Dev Dependency Status](https://david-dm.org/franksrevenge/IPSubnetCalculator/dev-status.svg)](https://david-dm.org/franksrevenge/IPSubnetCalculator#info=devDependencies&view=table) | ||
What does it do? | ||
@@ -15,5 +13,3 @@ ---------------- | ||
* Calculates subnet masks for standard and non-standard IP ranges. For example, `10.0.0.5 - 10.0.0.23` will result in `10.0.0.5/32, 10.0.0.6/31, 10.0.0.8/29, 10.0.0.16/29`. | ||
* Calculates CIDR prefixes from subnet masks, e.g. `10.0.0.5/255.255.128.0` will result in `10.0.0.0/17`. | ||
* Calculates subnet masks from CIDR prefixes, e.g. `10.0.0.5/17` will result in `255.255.128.0`. | ||
@@ -26,3 +22,2 @@ | ||
* Node.js | ||
* RequireJS | ||
* Direct browser use | ||
@@ -35,4 +30,2 @@ | ||
```sh | ||
> bower install ip-subnet-calculator | ||
> npm install ip-subnet-calculator | ||
@@ -44,41 +37,23 @@ ``` | ||
------- | ||
```javascript | ||
var IpSubnetCalculator = require( 'ip-subnet-calculator' ); | ||
import * as IPSubnetCalculator from 'ip-subnet-calculator'; | ||
// or: const IPSubnetCalculator = require('ip-subnet-calculator'); | ||
console.log( IpSubnetCalculator.isIp( '127.0.0.1' ) ); // "true" | ||
console.log( IpSubnetCalculator.toDecimal( '127.0.0.1' ) ); // "2130706433" | ||
console.log(IpSubnetCalculator.isIp('127.0.0.1')); // true | ||
console.log(IpSubnetCalculator.toDecimal('127.0.0.1')); // 2130706433 | ||
console.log( IpSubnetCalculator.calculate( '5.4.3.21', '6.7.8.9' ) ); | ||
console.log(IpSubnetCalculator.calculate('5.4.3.21', '6.7.8.9')); | ||
``` | ||
RequireJS | ||
--------- | ||
```javascript | ||
require( [ 'ip-subnet-calculator' ], | ||
function( IpSubnetCalculator ) | ||
{ | ||
console.log( IpSubnetCalculator.isIp( '127.0.0.1' ) ); // "true" | ||
console.log( IpSubnetCalculator.toDecimal( '127.0.0.1' ) ); // "2130706433" | ||
console.log( IpSubnetCalculator.calculate( '5.4.3.21', '6.7.8.9' ) ); | ||
} ); | ||
``` | ||
Direct browser use | ||
------------------ | ||
```html | ||
<script src='lib/ip-subnet-calculator.js'></script> | ||
<script src='lib/ip-subnet-calculator.browser.js'></script> | ||
<script> | ||
console.log( IpSubnetCalculator.isIp( '127.0.0.1' ) ); // "true" | ||
console.log( IpSubnetCalculator.toDecimal( '127.0.0.1' ) ); // "2130706433" | ||
console.log(isIp( 127.0.0.1')); // true | ||
console.log(toDecimal('127.0.0.1')); // 2130706433 | ||
console.log( IpSubnetCalculator.calculate( '5.4.3.21', '6.7.8.9' ) ); | ||
console.log(calculate( '5.4.3.21', '6.7.8.9' )); | ||
</script> | ||
@@ -90,11 +65,10 @@ ``` | ||
--- | ||
### IpSubnetCalculator.calculate(ipStart, ipEnd) ### | ||
### IpSubnetCalculator.calculate( ipStart, ipEnd ) ### | ||
Calculates an optimal set of IP masks for the given IP address range. | ||
*ipStart* (string|number) Lowest IP in the range to be calculated in string (`123.123.123.0`) or numeric (`2071689984`) format. | ||
> *ipStart* (`string|number`) Lowest IP in the range to be calculated in string (`123.123.123.0`) or numeric (`2071689984`) format. | ||
> | ||
> *ipEnd* (`string|number`) Highest IP (inclusive) in the range to be calculated in string (`123.123.123.255`) or numeric (`2071690239`) format. | ||
*ipEnd* (string|number) Highest IP (inclusive) in the range to be calculated in string (`123.123.123.255`) or numeric (`2071690239`) format. | ||
The function returns `null` in case of an error. Otherwise, an array containing one or more subnet | ||
@@ -104,17 +78,17 @@ masks is returned: | ||
```javascript | ||
var result = [ | ||
{ | ||
ipLow : 2071689984, | ||
ipLowStr : "123.123.123.0", | ||
ipHigh : 2071690239, | ||
ipHighStr : "123.123.123.255", | ||
prefixMask : 4294967040, | ||
prefixMaskStr : "255.255.255.0", | ||
prefixSize : 24, | ||
invertedMask : 255, | ||
invertedMaskStr : "0.0.0.255", | ||
invertedMaskSize : 8 | ||
}, | ||
... | ||
const result = [ | ||
{ | ||
ipLow : 2071689984, | ||
ipLowStr : "123.123.123.0", | ||
ipHigh : 2071690239, | ||
ipHighStr : "123.123.123.255", | ||
prefixMask : 4294967040, | ||
prefixMaskStr : "255.255.255.0", | ||
prefixSize : 24, | ||
invertedMask : 255, | ||
invertedMaskStr : "0.0.0.255", | ||
invertedMaskSize : 8 | ||
}, | ||
... | ||
]; | ||
@@ -125,35 +99,35 @@ ``` | ||
| Property | Use | | ||
:----------------------|:---------------------------------------------------------------| | ||
| ipLow | Decimal representation of the lowest IP address in the range | | ||
| ipLowStr | String representation of the lowest IP address in the range | | ||
| ipHigh | Decimal representation of the highest IP address in the range | | ||
| ipHighStr | String representation of the highest IP address in the range | | ||
| prefixMask | Decimal representation of the prefix (subnet) mask | | ||
| prefixMaskStr | String representation of the prefix (subnet) mask | | ||
| prefixSize | Size of the prefix (subnet) mask in bits | | ||
| invertedMask | Decimal representation of the inverted prefix mask | | ||
| invertedMaskStr | String representation of the inverted prefix mask | | ||
| invertedSize | Size of the inverted prefix max in bits | | ||
| Property | Use | | ||
:------------------|:---------------------------------------------------------------| | ||
| `ipLow` | Decimal representation of the lowest IP address in the range | | ||
| `ipLowStr` | String representation of the lowest IP address in the range | | ||
| `ipHigh` | Decimal representation of the highest IP address in the range | | ||
| `ipHighStr` | String representation of the highest IP address in the range | | ||
| `prefixMask` | Decimal representation of the prefix (subnet) mask | | ||
| `prefixMaskStr` | String representation of the prefix (subnet) mask | | ||
| `prefixSize` | Size of the prefix (subnet) mask in bits | | ||
| `invertedMask` | Decimal representation of the inverted prefix mask | | ||
| `invertedMaskStr` | String representation of the inverted prefix mask | | ||
| `invertedSize` | Size of the inverted prefix max in bits | | ||
### IpSubnetCalculator.calculateSubnetMask( ip, prefixSize ) ### | ||
### IpSubnetCalculator.calculateSubnetMask(ip, prefixSize) ### | ||
Calculates a subnet mask from CIDR prefix. | ||
*ip* (string|number) IP address in string or numeric format | ||
> *ip* (`string|number`) IP address in string or numeric format | ||
> | ||
> *prefixSize* (`number`) Number of relevant bits in the subnet mask | ||
*prefixSize* Number of relevant bits in the subnet mask | ||
The function returns an object containing full description of the IP range, as described in `IpSubnetCalculator.calculate()`. | ||
### IpSubnetCalculator.calculateCIDRPrefix( ip, subnetMask ) ### | ||
### IpSubnetCalculator.calculateCIDRPrefix(ip, subnetMask) ### | ||
Calculates a CIDR prefix from subnet mask. | ||
*ip* (string|number) IP address in string or numeric format | ||
> *ip* (`string|number`) IP address in string or numeric format | ||
> | ||
> *subnetMask* (`string|number`) IP subnet mask in string or numeric format | ||
*subnetMask* (string|number) IP subnet mask in string or numeric format | ||
The function returns an object containing full description of the IP range, as described in `IpSubnetCalculator.calculate()`. | ||
@@ -164,15 +138,15 @@ | ||
### IpSubnetCalculator.isIp( ipStr ) ### | ||
### IpSubnetCalculator.isIp(ipStr) ### | ||
Tests whether string is an IP address. | ||
*ipStr* (string) A string | ||
> *ipStr* (`string`) A string | ||
The function returns a `true` if the string is an IP address, `false` otherwise. | ||
### IpSubnetCalculator.isDecimalIp( ipNum ) ### | ||
### IpSubnetCalculator.isDecimalIp(ipNum) ### | ||
Tests whether string is an IP address. | ||
Tests whether `ipNum` is a decimal IP address. | ||
*ipNum* (number) A number | ||
> *ipNum* (`number`) A number | ||
@@ -184,7 +158,7 @@ The function returns a `true` if the number is an IP address, `false` otherwise. | ||
### IpSubnetCalculator.toDecimal( ip ) ### | ||
### IpSubnetCalculator.toDecimal(ip) ### | ||
Calculates a decimal integer from an string IP address. | ||
*ip* (string|number) IP address in string format | ||
> *ip* (`string|number`) IP address in string format | ||
@@ -197,5 +171,5 @@ The function returns a decimal representation of an IP address as an integer. If a valid numeric representation | ||
### IpSubnetCalculator.toString( num ) ### | ||
### IpSubnetCalculator.toString(num) ### | ||
*num* (number|string) Decimal representation of an IP address. | ||
> *num* (`number|string`) Decimal representation of an IP address. | ||
@@ -202,0 +176,0 @@ The function returns an IP address as a string. If a valid string representation of an IP is passed to this function, |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
35919
9
541
23
178
2