finalize subnet mask changes and small code cleanup

This commit is contained in:
anonion 2024-09-09 20:23:51 +00:00
parent c4ed768c11
commit b58cc6b219
2 changed files with 69 additions and 27 deletions

View file

@ -25,7 +25,7 @@ export function ipv4CidrRange(cidr, includeNetworkInfo, enumerateAddresses, allo
cidrRange = parseInt(cidr[2], 10); cidrRange = parseInt(cidr[2], 10);
let output = ""; let output = "";
if (cidrRange < 0 || cidrRange > 31) { if (!validateCidr(cidrRange)) {
throw new OperationError("IPv4 CIDR must be less than 32"); throw new OperationError("IPv4 CIDR must be less than 32");
} }
@ -192,38 +192,40 @@ export function ipv6HyphenatedRange(range, includeNetworkInfo) {
/** /**
* Parses an IPv4 subnet mask (e.g. 192.168.0.0/255.255.255.0) and displays information about it. * Parses an IPv4 subnet mask (e.g. 192.168.0.0/255.255.255.0) and displays information about it.
* *
* @param {RegExp} subnetMask * @param {RegExp} match
* @param {boolean} includeNetworkInfo * @param {boolean} includeNetworkInfo
* @param {boolean} enumerateAddresses * @param {boolean} enumerateAddresses
* @param {boolean} allowLargeList * @param {boolean} allowLargeList
* @returns {string} * @returns {string}
*/ */
export function ipv4SubnetMask(subnetMask, includeNetworkInfo, enumerateAddresses, allowLargeList) { export function ipv4SubnetMask(match, includeNetworkInfo, enumerateAddresses, allowLargeList) {
const network = strToIpv4(subnetMask[1]), const network = strToIpv4(match[1]),
mask = subnetMask[2]; mask = strToIpv4(match[2]);
let output = ""; let output = "",
maskCalculate = mask,
cidr = 0;
// Validate the subnet mask
if (!validateSubnetMask(mask)) {
throw new OperationError("Invalid subnet mask");
}
// Calculate the CIDR // Calculate the CIDR
const octets = mask.split(".").map(Number); while (maskCalculate) {
let cidr = 0; cidr += maskCalculate & 1;
for (let i = 0; i < octets.length; i++) { maskCalculate >>>= 1;
let octet = octets[i];
while (octet) {
cidr += (octet & 1); // Check if the last bit is 1
octet >>= 1; // Shift bits to the right
}
} }
if (cidr < 0 || cidr > 31) { if (!validateCidr(cidr)) {
throw new OperationError("IPv4 CIDR must be less than 32"); throw new OperationError("IPv4 CIDR must be less than 32");
} }
const ip1 = network & strToIpv4(mask), const ip1 = network & mask,
ip2 = ip1 | ~strToIpv4(mask); ip2 = ip1 | ~mask;
if (includeNetworkInfo) { if (includeNetworkInfo) {
output += "Network: " + ipv4ToStr(network) + "\n"; output += "Network: " + ipv4ToStr(network) + "\n";
output += "CIDR: " + cidr + "\n"; output += "CIDR: " + cidr + "\n";
output += "Mask: " + mask + "\n"; output += "Mask: " + ipv4ToStr(mask) + "\n";
output += "Range: " + ipv4ToStr(ip1) + " - " + ipv4ToStr(ip2) + "\n"; output += "Range: " + ipv4ToStr(ip1) + " - " + ipv4ToStr(ip2) + "\n";
output += "Total addresses in range: " + (((ip2 - ip1) >>> 0) + 1) + "\n\n"; output += "Total addresses in range: " + (((ip2 - ip1) >>> 0) + 1) + "\n\n";
} }
@ -256,15 +258,27 @@ export function ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, a
const ipv4CidrList = ipv4List.filter(function(a) { const ipv4CidrList = ipv4List.filter(function(a) {
return a.includes("/"); return a.includes("/");
}); });
const cidrCheck = /^\d\d?$/;
for (let i = 0; i < ipv4CidrList.length; i++) { for (let i = 0; i < ipv4CidrList.length; i++) {
const network = strToIpv4(ipv4CidrList[i].split("/")[0]); const network = strToIpv4(ipv4CidrList[i].split("/")[0]);
const cidrRange = parseInt(ipv4CidrList[i].split("/")[1], 10); const cidr = ipv4CidrList[i].split("/")[1];
if (cidrRange < 0 || cidrRange > 31) { let mask;
throw new OperationError("IPv4 CIDR must be less than 32");
// Check if this is a CIDR or subnet mask
if (cidrCheck.exec(cidr)) {
const cidrRange = parseInt(cidr, 10);
if (!validateCidr(cidrRange)) {
throw new OperationError("IPv4 CIDR must be less than 32");
}
mask = ~(0xFFFFFFFF >>> cidrRange);
} else {
mask = strToIpv4(cidr);
if (!validateSubnetMask(mask)) {
throw new OperationError("Invalid subnet mask");
}
} }
const mask = ~(0xFFFFFFFF >>> cidrRange), const cidrIp1 = network & mask;
cidrIp1 = network & mask, const cidrIp2 = cidrIp1 | ~mask;
cidrIp2 = cidrIp1 | ~mask;
ipv4List.splice(ipv4List.indexOf(ipv4CidrList[i]), 1); ipv4List.splice(ipv4List.indexOf(ipv4CidrList[i]), 1);
ipv4List.push(ipv4ToStr(cidrIp1), ipv4ToStr(cidrIp2)); ipv4List.push(ipv4ToStr(cidrIp1), ipv4ToStr(cidrIp2));
} }
@ -558,6 +572,34 @@ export function ipv6Compare(a, b) {
} }
return 0; return 0;
} }
/**
* Validates a given subnet mask
*
* @param {string} mask
* @returns {boolean}
*/
export function validateSubnetMask (mask) {
for (; mask !== 0; mask <<= 1) {
if ((mask & (1<<31)) === 0) {
return false;
}
}
return true;
}
/**
* Validates a given CIDR
*
* @param {string} cidr
* @returns {boolean}
*/
export function validateCidr (cidr) {
if (cidr < 0 || cidr > 31) {
return false;
} else {
return true;
}
}
const _LARGE_RANGE_ERROR = "The specified range contains more than 65,536 addresses. Running this query could crash your browser. If you want to run it, select the \"Allow large queries\" option. You are advised to turn off \"Auto Bake\" whilst editing large ranges."; const _LARGE_RANGE_ERROR = "The specified range contains more than 65,536 addresses. Running this query could crash your browser. If you want to run it, select the \"Allow large queries\" option. You are advised to turn off \"Auto Bake\" whilst editing large ranges.";

View file

@ -22,7 +22,7 @@ class ParseIPRange extends Operation {
this.name = "Parse IP range"; this.name = "Parse IP range";
this.module = "Default"; this.module = "Default";
this.description = "Given a CIDR range (e.g. <code>10.0.0.0/24</code>), hyphenated range (e.g. <code>10.0.0.0 - 10.0.1.0</code>), or a list of IPs and/or CIDR ranges (separated by a new line), this operation provides network information and enumerates all IP addresses in the range.<br><br>IPv6 is supported but will not be enumerated."; this.description = "Given a CIDR range (e.g. <code>10.0.0.0/24</code>), IP and subnet mask (e.g <code>10.0.0.0/255.255.255.0</code>), hyphenated range (e.g. <code>10.0.0.0 - 10.0.1.0</code>), or a list of IPs and/or CIDR ranges/subnet masks (separated by a new line), this operation provides network information and enumerates all IP addresses in the range.<br><br>IPv6 is supported but will not be enumerated.";
this.infoURL = "https://wikipedia.org/wiki/Subnetwork"; this.infoURL = "https://wikipedia.org/wiki/Subnetwork";
this.inputType = "string"; this.inputType = "string";
this.outputType = "string"; this.outputType = "string";
@ -61,7 +61,7 @@ class ParseIPRange extends Operation {
const ipv4CidrRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/, const ipv4CidrRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/,
ipv4RangeRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/, ipv4RangeRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/,
ipv4SubnetMaskRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/((?:\d{1,3}\.){3}\d{1,3})\s*$/, ipv4SubnetMaskRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/((?:\d{1,3}\.){3}\d{1,3})\s*$/,
ipv4ListRegex = /^\s*(((?:\d{1,3}\.){3}\d{1,3})(\/(\d\d?))?(\n|$)(\n*))+\s*$/, ipv4ListRegex = /^\s*(((?:\d{1,3}\.){3}\d{1,3})(\/((?:\d\d?)|(?:\d{1,3}\.){3}\d{1,3}))?(\n|$)(\n*))+\s*$/,
ipv6CidrRegex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i, ipv6CidrRegex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i,
ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i, ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i,
ipv6ListRegex = /^\s*((((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))(\/(\d\d?\d?))?(\n|$)(\n*))+\s*$/i; ipv6ListRegex = /^\s*((((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))(\/(\d\d?\d?))?(\n|$)(\n*))+\s*$/i;
@ -82,7 +82,7 @@ class ParseIPRange extends Operation {
} else if ((match = ipv6ListRegex.exec(input))) { } else if ((match = ipv6ListRegex.exec(input))) {
return ipv6ListedRange(match, includeNetworkInfo); return ipv6ListedRange(match, includeNetworkInfo);
} else { } else {
throw new OperationError("Invalid input.\n\nEnter either a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0). IPv6 also supported."); throw new OperationError("Invalid input.\n\nThe following input strings are supported:\nCIDR range (e.g. 10.0.0.0/24)\nSubnet mask (e.g. 10.0.0.0/255.255.255.0)\nHyphenated range (e.g. 10.0.0.0 - 10.0.1.0)\nIPv6 also supported.");
} }
} }