2018-05-16 22:51:24 +02:00
|
|
|
/**
|
|
|
|
* @author n1474335 [n1474335@gmail.com]
|
|
|
|
* @copyright Crown Copyright 2016
|
|
|
|
* @license Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2019-07-09 13:23:59 +02:00
|
|
|
import Operation from "../Operation.mjs";
|
|
|
|
import Utils from "../Utils.mjs";
|
|
|
|
import OperationError from "../errors/OperationError.mjs";
|
|
|
|
import {IP_DELIM_OPTIONS} from "../lib/Delim.mjs";
|
|
|
|
import {ipv6ToStr, genIpv6Mask, IPV4_REGEX, strToIpv6, ipv4ToStr, IPV6_REGEX, strToIpv4} from "../lib/IP.mjs";
|
2018-05-16 22:51:24 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Group IP addresses operation
|
|
|
|
*/
|
|
|
|
class GroupIPAddresses extends Operation {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GroupIPAddresses constructor
|
|
|
|
*/
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
|
|
|
|
this.name = "Group IP addresses";
|
2018-12-26 00:58:00 +01:00
|
|
|
this.module = "Default";
|
2018-05-16 22:51:24 +02:00
|
|
|
this.description = "Groups a list of IP addresses into subnets. Supports both IPv4 and IPv6 addresses.";
|
2018-08-21 20:07:13 +02:00
|
|
|
this.infoURL = "https://wikipedia.org/wiki/Subnetwork";
|
2018-05-16 22:51:24 +02:00
|
|
|
this.inputType = "string";
|
|
|
|
this.outputType = "string";
|
|
|
|
this.args = [
|
|
|
|
{
|
|
|
|
"name": "Delimiter",
|
|
|
|
"type": "option",
|
2018-05-29 01:48:30 +02:00
|
|
|
"value": IP_DELIM_OPTIONS
|
2018-05-16 22:51:24 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "Subnet (CIDR)",
|
|
|
|
"type": "number",
|
|
|
|
"value": 24
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "Only show the subnets",
|
|
|
|
"type": "boolean",
|
|
|
|
"value": false,
|
|
|
|
}
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {string} input
|
|
|
|
* @param {Object[]} args
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
|
|
|
run(input, args) {
|
|
|
|
const delim = Utils.charRep(args[0]),
|
|
|
|
cidr = args[1],
|
|
|
|
onlySubnets = args[2],
|
|
|
|
ipv4Mask = cidr < 32 ? ~(0xFFFFFFFF >>> cidr) : 0xFFFFFFFF,
|
2018-05-16 23:32:46 +02:00
|
|
|
ipv6Mask = genIpv6Mask(cidr),
|
2018-05-16 22:51:24 +02:00
|
|
|
ips = input.split(delim),
|
|
|
|
ipv4Networks = {},
|
|
|
|
ipv6Networks = {};
|
|
|
|
let match = null,
|
|
|
|
output = "",
|
|
|
|
ip = null,
|
|
|
|
network = null,
|
|
|
|
networkStr = "",
|
|
|
|
i;
|
|
|
|
|
|
|
|
if (cidr < 0 || cidr > 127) {
|
2018-05-29 01:48:30 +02:00
|
|
|
throw new OperationError("CIDR must be less than 32 for IPv4 or 128 for IPv6");
|
2018-05-16 22:51:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Parse all IPs and add to network dictionary
|
|
|
|
for (i = 0; i < ips.length; i++) {
|
|
|
|
if ((match = IPV4_REGEX.exec(ips[i]))) {
|
2018-05-16 23:32:46 +02:00
|
|
|
ip = strToIpv4(match[1]) >>> 0;
|
2018-05-16 22:51:24 +02:00
|
|
|
network = ip & ipv4Mask;
|
|
|
|
|
2019-07-05 13:22:52 +02:00
|
|
|
if (network in ipv4Networks) {
|
2018-05-16 22:51:24 +02:00
|
|
|
ipv4Networks[network].push(ip);
|
|
|
|
} else {
|
|
|
|
ipv4Networks[network] = [ip];
|
|
|
|
}
|
|
|
|
} else if ((match = IPV6_REGEX.exec(ips[i]))) {
|
2018-05-16 23:32:46 +02:00
|
|
|
ip = strToIpv6(match[1]);
|
2018-05-16 22:51:24 +02:00
|
|
|
network = [];
|
|
|
|
networkStr = "";
|
|
|
|
|
|
|
|
for (let j = 0; j < 8; j++) {
|
|
|
|
network.push(ip[j] & ipv6Mask[j]);
|
|
|
|
}
|
|
|
|
|
2018-05-16 23:32:46 +02:00
|
|
|
networkStr = ipv6ToStr(network, true);
|
2018-05-16 22:51:24 +02:00
|
|
|
|
2019-07-05 13:22:52 +02:00
|
|
|
if (networkStr in ipv6Networks) {
|
2018-05-16 22:51:24 +02:00
|
|
|
ipv6Networks[networkStr].push(ip);
|
|
|
|
} else {
|
|
|
|
ipv6Networks[networkStr] = [ip];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort IPv4 network dictionaries and print
|
|
|
|
for (network in ipv4Networks) {
|
|
|
|
ipv4Networks[network] = ipv4Networks[network].sort();
|
|
|
|
|
2018-05-16 23:32:46 +02:00
|
|
|
output += ipv4ToStr(network) + "/" + cidr + "\n";
|
2018-05-16 22:51:24 +02:00
|
|
|
|
|
|
|
if (!onlySubnets) {
|
|
|
|
for (i = 0; i < ipv4Networks[network].length; i++) {
|
2018-05-16 23:32:46 +02:00
|
|
|
output += " " + ipv4ToStr(ipv4Networks[network][i]) + "\n";
|
2018-05-16 22:51:24 +02:00
|
|
|
}
|
|
|
|
output += "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort IPv6 network dictionaries and print
|
|
|
|
for (networkStr in ipv6Networks) {
|
2019-11-14 09:55:27 +01:00
|
|
|
// ipv6Networks[networkStr] = ipv6Networks[networkStr].sort(); TODO
|
2018-05-16 22:51:24 +02:00
|
|
|
|
|
|
|
output += networkStr + "/" + cidr + "\n";
|
|
|
|
|
|
|
|
if (!onlySubnets) {
|
|
|
|
for (i = 0; i < ipv6Networks[networkStr].length; i++) {
|
2018-05-16 23:32:46 +02:00
|
|
|
output += " " + ipv6ToStr(ipv6Networks[networkStr][i], true) + "\n";
|
2018-05-16 22:51:24 +02:00
|
|
|
}
|
|
|
|
output += "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
export default GroupIPAddresses;
|