From 39ba83eefb803f8613857630ef8bc8501b704b71 Mon Sep 17 00:00:00 2001 From: Callum Fraser Date: Tue, 15 May 2018 23:30:35 +0100 Subject: [PATCH 01/10] Created a Ip for now which contains all the helper functions, they may be moved into their corrosponding files in the future --- src/core/lib/Ip.mjs | 398 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 398 insertions(+) create mode 100644 src/core/lib/Ip.mjs diff --git a/src/core/lib/Ip.mjs b/src/core/lib/Ip.mjs new file mode 100644 index 00000000..66a713c7 --- /dev/null +++ b/src/core/lib/Ip.mjs @@ -0,0 +1,398 @@ +import Utils from "../Utils"; + +/** + * Parses an IPv4 CIDR range (e.g. 192.168.0.0/24) and displays information about it. + * + * @private + * @param {RegExp} cidr + * @param {boolean} includeNetworkInfo + * @param {boolean} enumerateAddresses + * @param {boolean} allowLargeList + * @returns {string} + */ +export function _ipv4CidrRange(cidr, includeNetworkInfo, enumerateAddresses, allowLargeList) { + const network = _strToIpv4(cidr[1]), + cidrRange = parseInt(cidr[2], 10); + let output = ""; + + if (cidrRange < 0 || cidrRange > 31) { + return "IPv4 CIDR must be less than 32"; + } + + const mask = ~(0xFFFFFFFF >>> cidrRange), + ip1 = network & mask, + ip2 = ip1 | ~mask; + + if (includeNetworkInfo) { + output += "Network: " + _ipv4ToStr(network) + "\n"; + output += "CIDR: " + cidrRange + "\n"; + output += "Mask: " + _ipv4ToStr(mask) + "\n"; + output += "Range: " + _ipv4ToStr(ip1) + " - " + _ipv4ToStr(ip2) + "\n"; + output += "Total addresses in range: " + (((ip2 - ip1) >>> 0) + 1) + "\n\n"; + } + + if (enumerateAddresses) { + if (cidrRange >= 16 || allowLargeList) { + output += _generateIpv4Range(ip1, ip2).join("\n"); + } else { + output += _LARGE_RANGE_ERROR; + } + } + return output; +} + + /** + * Parses an IPv6 CIDR range (e.g. ff00::/48) and displays information about it. + * + * @private + * @param {RegExp} cidr + * @param {boolean} includeNetworkInfo + * @returns {string} + */ +export function _ipv6CidrRange(cidr, includeNetworkInfo) { + let output = ""; + const network = _strToIpv6(cidr[1]), + cidrRange = parseInt(cidr[cidr.length-1], 10); + + if (cidrRange < 0 || cidrRange > 127) { + return "IPv6 CIDR must be less than 128"; + } + + const ip1 = new Array(8), + ip2 = new Array(8), + total = new Array(128); + + const mask = _genIpv6Mask(cidrRange); + let totalDiff = ""; + + + for (let i = 0; i < 8; i++) { + ip1[i] = network[i] & mask[i]; + ip2[i] = ip1[i] | (~mask[i] & 0x0000FFFF); + totalDiff = (ip2[i] - ip1[i]).toString(2); + + if (totalDiff !== "0") { + for (let n = 0; n < totalDiff.length; n++) { + total[i*16 + 16-(totalDiff.length-n)] = totalDiff[n]; + } + } + } + + if (includeNetworkInfo) { + output += "Network: " + _ipv6ToStr(network) + "\n"; + output += "Shorthand: " + _ipv6ToStr(network, true) + "\n"; + output += "CIDR: " + cidrRange + "\n"; + output += "Mask: " + _ipv6ToStr(mask) + "\n"; + output += "Range: " + _ipv6ToStr(ip1) + " - " + _ipv6ToStr(ip2) + "\n"; + output += "Total addresses in range: " + (parseInt(total.join(""), 2) + 1) + "\n\n"; + } + + return output; +} + + /** + * Parses an IPv4 hyphenated range (e.g. 192.168.0.0 - 192.168.0.255) and displays information + * about it. + * + * @private + * @param {RegExp} range + * @param {boolean} includeNetworkInfo + * @param {boolean} enumerateAddresses + * @param {boolean} allowLargeList + * @returns {string} + */ +export function _ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList) { + const ip1 = _strToIpv4(range[1]), + ip2 = _strToIpv4(range[2]); + + let output = ""; + // Calculate mask + let diff = ip1 ^ ip2, + cidr = 32, + mask = 0; + + while (diff !== 0) { + diff >>= 1; + cidr--; + mask = (mask << 1) | 1; + } + + mask = ~mask >>> 0; + const network = ip1 & mask, + subIp1 = network & mask, + subIp2 = subIp1 | ~mask; + + if (includeNetworkInfo) { + output += "Minimum subnet required to hold this range:\n"; + output += "\tNetwork: " + _ipv4ToStr(network) + "\n"; + output += "\tCIDR: " + cidr + "\n"; + output += "\tMask: " + _ipv4ToStr(mask) + "\n"; + output += "\tSubnet range: " + _ipv4ToStr(subIp1) + " - " + _ipv4ToStr(subIp2) + "\n"; + output += "\tTotal addresses in subnet: " + (((subIp2 - subIp1) >>> 0) + 1) + "\n\n"; + output += "Range: " + _ipv4ToStr(ip1) + " - " + _ipv4ToStr(ip2) + "\n"; + output += "Total addresses in range: " + (((ip2 - ip1) >>> 0) + 1) + "\n\n"; + } + + if (enumerateAddresses) { + if (((ip2 - ip1) >>> 0) <= 65536 || allowLargeList) { + output += _generateIpv4Range(ip1, ip2).join("\n"); + } else { + output += _LARGE_RANGE_ERROR; + } + } + return output; +} + + + /** + * Parses an IPv6 hyphenated range (e.g. ff00:: - ffff::) and displays information about it. + * + * @private + * @param {RegExp} range + * @param {boolean} includeNetworkInfo + * @returns {string} + */ +export function _ipv6HyphenatedRange(range, includeNetworkInfo) { + const ip1 = _strToIpv6(range[1]), + ip2 = _strToIpv6(range[14]), + total = new Array(128).fill(); + + let output = "", + t = "", + i; + + for (i = 0; i < 8; i++) { + t = (ip2[i] - ip1[i]).toString(2); + if (t !== "0") { + for (let n = 0; n < t.length; n++) { + total[i*16 + 16-(t.length-n)] = t[n]; + } + } + } + + if (includeNetworkInfo) { + output += "Range: " + _ipv6ToStr(ip1) + " - " + _ipv6ToStr(ip2) + "\n"; + output += "Shorthand range: " + _ipv6ToStr(ip1, true) + " - " + _ipv6ToStr(ip2, true) + "\n"; + output += "Total addresses in range: " + (parseInt(total.join(""), 2) + 1) + "\n\n"; + } + + return output; +} + + /** + * Converts an IPv4 address from string format to numerical format. + * + * @private + * @param {string} ipStr + * @returns {number} + * + * @example + * // returns 168427520 + * _strToIpv4("10.10.0.0"); + */ +export function _strToIpv4(ipStr) { + const blocks = ipStr.split("."), + numBlocks = parseBlocks(blocks); + let result = 0; + + result += numBlocks[0] << 24; + result += numBlocks[1] << 16; + result += numBlocks[2] << 8; + result += numBlocks[3]; + + return result; + + /** + * Converts a list of 4 numeric strings in the range 0-255 to a list of numbers. + */ + function parseBlocks(blocks) { + if (blocks.length !== 4) + throw "More than 4 blocks."; + + const numBlocks = []; + for (let i = 0; i < 4; i++) { + numBlocks[i] = parseInt(blocks[i], 10); + if (numBlocks[i] < 0 || numBlocks[i] > 255) + throw "Block out of range."; + } + return numBlocks; + } +} + + + /** + * Converts an IPv4 address from numerical format to string format. + * + * @private + * @param {number} ipInt + * @returns {string} + * + * @example + * // returns "10.10.0.0" + * _ipv4ToStr(168427520); + */ +export function _ipv4ToStr(ipInt) { + const blockA = (ipInt >> 24) & 255, + blockB = (ipInt >> 16) & 255, + blockC = (ipInt >> 8) & 255, + blockD = ipInt & 255; + + return blockA + "." + blockB + "." + blockC + "." + blockD; +} + + + /** + * Converts an IPv6 address from string format to numerical array format. + * + * @private + * @param {string} ipStr + * @returns {number[]} + * + * @example + * // returns [65280, 0, 0, 0, 0, 0, 4369, 8738] + * _strToIpv6("ff00::1111:2222"); + */ +export function _strToIpv6(ipStr) { + let j = 0; + const blocks = ipStr.split(":"), + numBlocks = parseBlocks(blocks), + ipv6 = new Array(8); + + for (let i = 0; i < 8; i++) { + if (isNaN(numBlocks[j])) { + ipv6[i] = 0; + if (i === (8-numBlocks.slice(j).length)) j++; + } else { + ipv6[i] = numBlocks[j]; + j++; + } + } + return ipv6; + + /** + * Converts a list of 3-8 numeric hex strings in the range 0-65535 to a list of numbers. + */ + function parseBlocks(blocks) { + if (blocks.length < 3 || blocks.length > 8) + throw "Badly formatted IPv6 address."; + const numBlocks = []; + for (let i = 0; i < blocks.length; i++) { + numBlocks[i] = parseInt(blocks[i], 16); + if (numBlocks[i] < 0 || numBlocks[i] > 65535) + throw "Block out of range."; + } + return numBlocks; + } +} + + + /** + * Converts an IPv6 address from numerical array format to string format. + * + * @private + * @param {number[]} ipv6 + * @param {boolean} compact - Whether or not to return the address in shorthand or not + * @returns {string} + * + * @example + * // returns "ff00::1111:2222" + * _ipv6ToStr([65280, 0, 0, 0, 0, 0, 4369, 8738], true); + * + * // returns "ff00:0000:0000:0000:0000:0000:1111:2222" + * _ipv6ToStr([65280, 0, 0, 0, 0, 0, 4369, 8738], false); + */ +export function _ipv6ToStr(ipv6, compact) { + let output = "", + i = 0; + + if (compact) { + let start = -1, + end = -1, + s = 0, + e = -1; + + for (i = 0; i < 8; i++) { + if (ipv6[i] === 0 && e === (i-1)) { + e = i; + } else if (ipv6[i] === 0) { + s = i; e = i; + } + if (e >= 0 && (e-s) > (end - start)) { + start = s; + end = e; + } + } + + for (i = 0; i < 8; i++) { + if (i !== start) { + output += Utils.hex(ipv6[i], 1) + ":"; + } else { + output += ":"; + i = end; + if (end === 7) output += ":"; + } + } + if (output[0] === ":") + output = ":" + output; + } else { + for (i = 0; i < 8; i++) { + output += Utils.hex(ipv6[i], 4) + ":"; + } + } + return output.slice(0, output.length-1); +} + + /** + * Generates a list of IPv4 addresses in string format between two given numerical values. + * + * @private + * @param {number} ip + * @param {number} endIp + * @returns {string[]} + * + * @example + * // returns ["0.0.0.1", "0.0.0.2", "0.0.0.3"] + * IP._generateIpv4Range(1, 3); + */ +export function _generateIpv4Range(ip, endIp) { + const range = []; + if (endIp >= ip) { + for (; ip <= endIp; ip++) { + range.push(_ipv4ToStr(ip)); + } + } else { + range[0] = "Second IP address smaller than first."; + } + return range; +} + + /** + * Generates an IPv6 subnet mask given a CIDR value. + * + * @private + * @param {number} cidr + * @returns {number[]} + */ +export function _genIpv6Mask(cidr) { + const mask = new Array(8); + let shift; + + for (let i = 0; i < 8; i++) { + if (cidr > ((i+1)*16)) { + mask[i] = 0x0000FFFF; + } else { + shift = cidr-(i*16); + if (shift < 0) shift = 0; + mask[i] = ~((0x0000FFFF >>> shift) | 0xFFFF0000); + } + } + + return mask; +} + + /** + * @constant + * @default + * @private + */ +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."; From 5b6d57fd47fd862744ebecc571dc418909a32822 Mon Sep 17 00:00:00 2001 From: Callum Fraser Date: Tue, 15 May 2018 23:31:03 +0100 Subject: [PATCH 02/10] Ported "Parse IP Range". --- src/core/operations/ParseIPRange.mjs | 78 ++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/core/operations/ParseIPRange.mjs diff --git a/src/core/operations/ParseIPRange.mjs b/src/core/operations/ParseIPRange.mjs new file mode 100644 index 00000000..30ebf3d2 --- /dev/null +++ b/src/core/operations/ParseIPRange.mjs @@ -0,0 +1,78 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import {_ipv4CidrRange, _ipv4HyphenatedRange, _ipv6CidrRange, _ipv6HyphenatedRange} from "../lib/Ip"; + +/** + * Parse IP range operation + */ +class ParseIPRange extends Operation { + + /** + * ParseIPRange constructor + */ + constructor() { + super(); + + this.name = "Parse IP range"; + this.module = "JSBN"; + this.description = "Given a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0), this operation provides network information and enumerates all IP addresses in the range.

IPv6 is supported but will not be enumerated."; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Include network info", + "type": "boolean", + "value": "IP.INCLUDE_NETWORK_INFO" + }, + { + "name": "Enumerate IP addresses", + "type": "boolean", + "value": "IP.ENUMERATE_ADDRESSES" + }, + { + "name": "Allow large queries", + "type": "boolean", + "value": "IP.ALLOW_LARGE_LIST" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const includeNetworkInfo = args[0], + enumerateAddresses = args[1], + allowLargeList = args[2]; + + // Check what type of input we are looking at + 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*$/, + 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; + let match; + + if ((match = ipv4CidrRegex.exec(input))) { + return _ipv4CidrRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); + } else if ((match = ipv4RangeRegex.exec(input))) { + return _ipv4HyphenatedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); + } else if ((match = ipv6CidrRegex.exec(input))) { + return _ipv6CidrRange(match, includeNetworkInfo); + } else if ((match = ipv6RangeRegex.exec(input))) { + return _ipv6HyphenatedRange(match, includeNetworkInfo); + } else { + return "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."; + } + } + +} + + +export default ParseIPRange; From 8d2adfaae78b26983551ef0506fa5e04154a6494 Mon Sep 17 00:00:00 2001 From: Callum Fraser Date: Tue, 15 May 2018 23:48:18 +0100 Subject: [PATCH 03/10] Updated the Ip core file with more required functions/variables --- src/core/lib/Ip.mjs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/core/lib/Ip.mjs b/src/core/lib/Ip.mjs index 66a713c7..e844562e 100644 --- a/src/core/lib/Ip.mjs +++ b/src/core/lib/Ip.mjs @@ -390,9 +390,19 @@ export function _genIpv6Mask(cidr) { return mask; } - /** - * @constant - * @default - * @private - */ +/** +* @constant +* @default +* @private +*/ 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."; +/** +* @constant +* @default +*/ +export const IPV4_REGEX = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/; +/** +* @constant +* @default +*/ +export const IPV6_REGEX = /^\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*$/i; From 654596ea79f22946d6055a853652be504d30def8 Mon Sep 17 00:00:00 2001 From: Callum Fraser Date: Tue, 15 May 2018 23:48:33 +0100 Subject: [PATCH 04/10] Ported "Parse IPv6 Address" --- src/core/operations/ParseIPv6Address.mjs | 191 +++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 src/core/operations/ParseIPv6Address.mjs diff --git a/src/core/operations/ParseIPv6Address.mjs b/src/core/operations/ParseIPv6Address.mjs new file mode 100644 index 00000000..8eadc13b --- /dev/null +++ b/src/core/operations/ParseIPv6Address.mjs @@ -0,0 +1,191 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {_strToIpv6, _ipv6ToStr, _ipv4ToStr, IPV6_REGEX} from "../lib/Ip"; +import BigInteger from "jsbn"; + +/** + * Parse IPv6 address operation + */ +class ParseIPv6Address extends Operation { + + /** + * ParseIPv6Address constructor + */ + constructor() { + super(); + + this.name = "Parse IPv6 address"; + this.module = "JSBN"; + this.description = "Displays the longhand and shorthand versions of a valid IPv6 address.

Recognises all reserved ranges and parses encapsulated or tunnelled addresses including Teredo and 6to4."; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let match, + output = ""; + + if ((match = IPV6_REGEX.exec(input))) { + const ipv6 = _strToIpv6(match[1]), + longhand = _ipv6ToStr(ipv6), + shorthand = _ipv6ToStr(ipv6, true); + + output += "Longhand: " + longhand + "\nShorthand: " + shorthand + "\n"; + + // Detect reserved addresses + if (shorthand === "::") { + // Unspecified address + output += "\nUnspecified address corresponding to 0.0.0.0/32 in IPv4."; + output += "\nUnspecified address range: ::/128"; + } else if (shorthand === "::1") { + // Loopback address + output += "\nLoopback address to the local host corresponding to 127.0.0.1/8 in IPv4."; + output += "\nLoopback addresses range: ::1/128"; + } else if (ipv6[0] === 0 && ipv6[1] === 0 && ipv6[2] === 0 && + ipv6[3] === 0 && ipv6[4] === 0 && ipv6[5] === 0xffff) { + // IPv4-mapped IPv6 address + output += "\nIPv4-mapped IPv6 address detected. IPv6 clients will be handled natively by default, and IPv4 clients appear as IPv6 clients at their IPv4-mapped IPv6 address."; + output += "\nMapped IPv4 address: " + _ipv4ToStr((ipv6[6] << 16) + ipv6[7]); + output += "\nIPv4-mapped IPv6 addresses range: ::ffff:0:0/96"; + } else if (ipv6[0] === 0 && ipv6[1] === 0 && ipv6[2] === 0 && + ipv6[3] === 0 && ipv6[4] === 0xffff && ipv6[5] === 0) { + // IPv4-translated address + output += "\nIPv4-translated address detected. Used by Stateless IP/ICMP Translation (SIIT). See RFCs 6145 and 6052 for more details."; + output += "\nTranslated IPv4 address: " + _ipv4ToStr((ipv6[6] << 16) + ipv6[7]); + output += "\nIPv4-translated addresses range: ::ffff:0:0:0/96"; + } else if (ipv6[0] === 0x100) { + // Discard prefix per RFC 6666 + output += "\nDiscard prefix detected. This is used when forwarding traffic to a sinkhole router to mitigate the effects of a denial-of-service attack. See RFC 6666 for more details."; + output += "\nDiscard range: 100::/64"; + } else if (ipv6[0] === 0x64 && ipv6[1] === 0xff9b && ipv6[2] === 0 && + ipv6[3] === 0 && ipv6[4] === 0 && ipv6[5] === 0) { + // IPv4/IPv6 translation per RFC 6052 + output += "\n'Well-Known' prefix for IPv4/IPv6 translation detected. See RFC 6052 for more details."; + output += "\nTranslated IPv4 address: " + _ipv4ToStr((ipv6[6] << 16) + ipv6[7]); + output += "\n'Well-Known' prefix range: 64:ff9b::/96"; + } else if (ipv6[0] === 0x2001 && ipv6[1] === 0) { + // Teredo tunneling + output += "\nTeredo tunneling IPv6 address detected\n"; + const serverIpv4 = (ipv6[2] << 16) + ipv6[3], + udpPort = (~ipv6[5]) & 0xffff, + clientIpv4 = ~((ipv6[6] << 16) + ipv6[7]), + flagCone = (ipv6[4] >>> 15) & 1, + flagR = (ipv6[4] >>> 14) & 1, + flagRandom1 = (ipv6[4] >>> 10) & 15, + flagUg = (ipv6[4] >>> 8) & 3, + flagRandom2 = ipv6[4] & 255; + + output += "\nServer IPv4 address: " + _ipv4ToStr(serverIpv4) + + "\nClient IPv4 address: " + _ipv4ToStr(clientIpv4) + + "\nClient UDP port: " + udpPort + + "\nFlags:" + + "\n\tCone: " + flagCone; + + if (flagCone) { + output += " (Client is behind a cone NAT)"; + } else { + output += " (Client is not behind a cone NAT)"; + } + + output += "\n\tR: " + flagR; + + if (flagR) { + output += " Error: This flag should be set to 0. See RFC 5991 and RFC 4380."; + } + + output += "\n\tRandom1: " + Utils.bin(flagRandom1, 4) + + "\n\tUG: " + Utils.bin(flagUg, 2); + + if (flagUg) { + output += " Error: This flag should be set to 00. See RFC 4380."; + } + + output += "\n\tRandom2: " + Utils.bin(flagRandom2, 8); + + if (!flagR && !flagUg && flagRandom1 && flagRandom2) { + output += "\n\nThis is a valid Teredo address which complies with RFC 4380 and RFC 5991."; + } else if (!flagR && !flagUg) { + output += "\n\nThis is a valid Teredo address which complies with RFC 4380, however it does not comply with RFC 5991 (Teredo Security Updates) as there are no randomised bits in the flag field."; + } else { + output += "\n\nThis is an invalid Teredo address."; + } + output += "\n\nTeredo prefix range: 2001::/32"; + } else if (ipv6[0] === 0x2001 && ipv6[1] === 0x2 && ipv6[2] === 0) { + // Benchmarking + output += "\nAssigned to the Benchmarking Methodology Working Group (BMWG) for benchmarking IPv6. Corresponds to 198.18.0.0/15 for benchmarking IPv4. See RFC 5180 for more details."; + output += "\nBMWG range: 2001:2::/48"; + } else if (ipv6[0] === 0x2001 && ipv6[1] >= 0x10 && ipv6[1] <= 0x1f) { + // ORCHIDv1 + output += "\nDeprecated, previously ORCHIDv1 (Overlay Routable Cryptographic Hash Identifiers).\nORCHIDv1 range: 2001:10::/28\nORCHIDv2 now uses 2001:20::/28."; + } else if (ipv6[0] === 0x2001 && ipv6[1] >= 0x20 && ipv6[1] <= 0x2f) { + // ORCHIDv2 + output += "\nORCHIDv2 (Overlay Routable Cryptographic Hash Identifiers).\nThese are non-routed IPv6 addresses used for Cryptographic Hash Identifiers."; + output += "\nORCHIDv2 range: 2001:20::/28"; + } else if (ipv6[0] === 0x2001 && ipv6[1] === 0xdb8) { + // Documentation + output += "\nThis is a documentation IPv6 address. This range should be used whenever an example IPv6 address is given or to model networking scenarios. Corresponds to 192.0.2.0/24, 198.51.100.0/24, and 203.0.113.0/24 in IPv4."; + output += "\nDocumentation range: 2001:db8::/32"; + } else if (ipv6[0] === 0x2002) { + // 6to4 + output += "\n6to4 transition IPv6 address detected. See RFC 3056 for more details." + + "\n6to4 prefix range: 2002::/16"; + + const v4Addr = _ipv4ToStr((ipv6[1] << 16) + ipv6[2]), + slaId = ipv6[3], + interfaceIdStr = ipv6[4].toString(16) + ipv6[5].toString(16) + ipv6[6].toString(16) + ipv6[7].toString(16), + interfaceId = new BigInteger(interfaceIdStr, 16); + + output += "\n\nEncapsulated IPv4 address: " + v4Addr + + "\nSLA ID: " + slaId + + "\nInterface ID (base 16): " + interfaceIdStr + + "\nInterface ID (base 10): " + interfaceId.toString(); + } else if (ipv6[0] >= 0xfc00 && ipv6[0] <= 0xfdff) { + // Unique local address + output += "\nThis is a unique local address comparable to the IPv4 private addresses 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16. See RFC 4193 for more details."; + output += "\nUnique local addresses range: fc00::/7"; + } else if (ipv6[0] >= 0xfe80 && ipv6[0] <= 0xfebf) { + // Link-local address + output += "\nThis is a link-local address comparable to the auto-configuration addresses 169.254.0.0/16 in IPv4."; + output += "\nLink-local addresses range: fe80::/10"; + } else if (ipv6[0] >= 0xff00) { + // Multicast + output += "\nThis is a reserved multicast address."; + output += "\nMulticast addresses range: ff00::/8"; + } + + + // Detect possible EUI-64 addresses + if ((ipv6[5] & 0xff === 0xff) && (ipv6[6] >>> 8 === 0xfe)) { + output += "\n\nThis IPv6 address contains a modified EUI-64 address, identified by the presence of FF:FE in the 12th and 13th octets."; + + const intIdent = Utils.hex(ipv6[4] >>> 8) + ":" + Utils.hex(ipv6[4] & 0xff) + ":" + + Utils.hex(ipv6[5] >>> 8) + ":" + Utils.hex(ipv6[5] & 0xff) + ":" + + Utils.hex(ipv6[6] >>> 8) + ":" + Utils.hex(ipv6[6] & 0xff) + ":" + + Utils.hex(ipv6[7] >>> 8) + ":" + Utils.hex(ipv6[7] & 0xff), + mac = Utils.hex((ipv6[4] >>> 8) ^ 2) + ":" + Utils.hex(ipv6[4] & 0xff) + ":" + + Utils.hex(ipv6[5] >>> 8) + ":" + Utils.hex(ipv6[6] & 0xff) + ":" + + Utils.hex(ipv6[7] >>> 8) + ":" + Utils.hex(ipv6[7] & 0xff); + output += "\nInterface identifier: " + intIdent + + "\nMAC address: " + mac; + } + } else { + return "Invalid IPv6 address"; + } + return output; + } + +} + +export default ParseIPv6Address; From 1920e9c7fb2eb79a144488bb684e31cfa6291d77 Mon Sep 17 00:00:00 2001 From: Callum Fraser Date: Wed, 16 May 2018 21:37:48 +0100 Subject: [PATCH 05/10] Added more content to the Ip.mjs file, required for other functions. --- src/core/lib/Ip.mjs | 180 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) diff --git a/src/core/lib/Ip.mjs b/src/core/lib/Ip.mjs index e844562e..f63c3f9d 100644 --- a/src/core/lib/Ip.mjs +++ b/src/core/lib/Ip.mjs @@ -406,3 +406,183 @@ export const IPV4_REGEX = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/; * @default */ export const IPV6_REGEX = /^\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*$/i; + +/** + * Lookup table for Internet Protocols. + * Taken from https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml + * + * @private + * @constant + */ +export const _protocolLookup = { + 0: {keyword: "HOPOPT", protocol: "IPv6 Hop-by-Hop Option"}, + 1: {keyword: "ICMP", protocol: "Internet Control Message"}, + 2: {keyword: "IGMP", protocol: "Internet Group Management"}, + 3: {keyword: "GGP", protocol: "Gateway-to-Gateway"}, + 4: {keyword: "IPv4", protocol: "IPv4 encapsulation"}, + 5: {keyword: "ST", protocol: "Stream"}, + 6: {keyword: "TCP", protocol: "Transmission Control"}, + 7: {keyword: "CBT", protocol: "CBT"}, + 8: {keyword: "EGP", protocol: "Exterior Gateway Protocol"}, + 9: {keyword: "IGP", protocol: "any private interior gateway (used by Cisco for their IGRP)"}, + 10: {keyword: "BBN-RCC-MON", protocol: "BBN RCC Monitoring"}, + 11: {keyword: "NVP-II", protocol: "Network Voice Protocol"}, + 12: {keyword: "PUP", protocol: "PUP"}, + 13: {keyword: "ARGUS (deprecated)", protocol: "ARGUS"}, + 14: {keyword: "EMCON", protocol: "EMCON"}, + 15: {keyword: "XNET", protocol: "Cross Net Debugger"}, + 16: {keyword: "CHAOS", protocol: "Chaos"}, + 17: {keyword: "UDP", protocol: "User Datagram"}, + 18: {keyword: "MUX", protocol: "Multiplexing"}, + 19: {keyword: "DCN-MEAS", protocol: "DCN Measurement Subsystems"}, + 20: {keyword: "HMP", protocol: "Host Monitoring"}, + 21: {keyword: "PRM", protocol: "Packet Radio Measurement"}, + 22: {keyword: "XNS-IDP", protocol: "XEROX NS IDP"}, + 23: {keyword: "TRUNK-1", protocol: "Trunk-1"}, + 24: {keyword: "TRUNK-2", protocol: "Trunk-2"}, + 25: {keyword: "LEAF-1", protocol: "Leaf-1"}, + 26: {keyword: "LEAF-2", protocol: "Leaf-2"}, + 27: {keyword: "RDP", protocol: "Reliable Data Protocol"}, + 28: {keyword: "IRTP", protocol: "Internet Reliable Transaction"}, + 29: {keyword: "ISO-TP4", protocol: "ISO Transport Protocol Class 4"}, + 30: {keyword: "NETBLT", protocol: "Bulk Data Transfer Protocol"}, + 31: {keyword: "MFE-NSP", protocol: "MFE Network Services Protocol"}, + 32: {keyword: "MERIT-INP", protocol: "MERIT Internodal Protocol"}, + 33: {keyword: "DCCP", protocol: "Datagram Congestion Control Protocol"}, + 34: {keyword: "3PC", protocol: "Third Party Connect Protocol"}, + 35: {keyword: "IDPR", protocol: "Inter-Domain Policy Routing Protocol"}, + 36: {keyword: "XTP", protocol: "XTP"}, + 37: {keyword: "DDP", protocol: "Datagram Delivery Protocol"}, + 38: {keyword: "IDPR-CMTP", protocol: "IDPR Control Message Transport Proto"}, + 39: {keyword: "TP++", protocol: "TP++ Transport Protocol"}, + 40: {keyword: "IL", protocol: "IL Transport Protocol"}, + 41: {keyword: "IPv6", protocol: "IPv6 encapsulation"}, + 42: {keyword: "SDRP", protocol: "Source Demand Routing Protocol"}, + 43: {keyword: "IPv6-Route", protocol: "Routing Header for IPv6"}, + 44: {keyword: "IPv6-Frag", protocol: "Fragment Header for IPv6"}, + 45: {keyword: "IDRP", protocol: "Inter-Domain Routing Protocol"}, + 46: {keyword: "RSVP", protocol: "Reservation Protocol"}, + 47: {keyword: "GRE", protocol: "Generic Routing Encapsulation"}, + 48: {keyword: "DSR", protocol: "Dynamic Source Routing Protocol"}, + 49: {keyword: "BNA", protocol: "BNA"}, + 50: {keyword: "ESP", protocol: "Encap Security Payload"}, + 51: {keyword: "AH", protocol: "Authentication Header"}, + 52: {keyword: "I-NLSP", protocol: "Integrated Net Layer Security TUBA"}, + 53: {keyword: "SWIPE (deprecated)", protocol: "IP with Encryption"}, + 54: {keyword: "NARP", protocol: "NBMA Address Resolution Protocol"}, + 55: {keyword: "MOBILE", protocol: "IP Mobility"}, + 56: {keyword: "TLSP", protocol: "Transport Layer Security Protocol using Kryptonet key management"}, + 57: {keyword: "SKIP", protocol: "SKIP"}, + 58: {keyword: "IPv6-ICMP", protocol: "ICMP for IPv6"}, + 59: {keyword: "IPv6-NoNxt", protocol: "No Next Header for IPv6"}, + 60: {keyword: "IPv6-Opts", protocol: "Destination Options for IPv6"}, + 61: {keyword: "", protocol: "any host internal protocol"}, + 62: {keyword: "CFTP", protocol: "CFTP"}, + 63: {keyword: "", protocol: "any local network"}, + 64: {keyword: "SAT-EXPAK", protocol: "SATNET and Backroom EXPAK"}, + 65: {keyword: "KRYPTOLAN", protocol: "Kryptolan"}, + 66: {keyword: "RVD", protocol: "MIT Remote Virtual Disk Protocol"}, + 67: {keyword: "IPPC", protocol: "Internet Pluribus Packet Core"}, + 68: {keyword: "", protocol: "any distributed file system"}, + 69: {keyword: "SAT-MON", protocol: "SATNET Monitoring"}, + 70: {keyword: "VISA", protocol: "VISA Protocol"}, + 71: {keyword: "IPCV", protocol: "Internet Packet Core Utility"}, + 72: {keyword: "CPNX", protocol: "Computer Protocol Network Executive"}, + 73: {keyword: "CPHB", protocol: "Computer Protocol Heart Beat"}, + 74: {keyword: "WSN", protocol: "Wang Span Network"}, + 75: {keyword: "PVP", protocol: "Packet Video Protocol"}, + 76: {keyword: "BR-SAT-MON", protocol: "Backroom SATNET Monitoring"}, + 77: {keyword: "SUN-ND", protocol: "SUN ND PROTOCOL-Temporary"}, + 78: {keyword: "WB-MON", protocol: "WIDEBAND Monitoring"}, + 79: {keyword: "WB-EXPAK", protocol: "WIDEBAND EXPAK"}, + 80: {keyword: "ISO-IP", protocol: "ISO Internet Protocol"}, + 81: {keyword: "VMTP", protocol: "VMTP"}, + 82: {keyword: "SECURE-VMTP", protocol: "SECURE-VMTP"}, + 83: {keyword: "VINES", protocol: "VINES"}, + 84: {keyword: "TTP", protocol: "Transaction Transport Protocol"}, + 85: {keyword: "NSFNET-IGP", protocol: "NSFNET-IGP"}, + 86: {keyword: "DGP", protocol: "Dissimilar Gateway Protocol"}, + 87: {keyword: "TCF", protocol: "TCF"}, + 88: {keyword: "EIGRP", protocol: "EIGRP"}, + 89: {keyword: "OSPFIGP", protocol: "OSPFIGP"}, + 90: {keyword: "Sprite-RPC", protocol: "Sprite RPC Protocol"}, + 91: {keyword: "LARP", protocol: "Locus Address Resolution Protocol"}, + 92: {keyword: "MTP", protocol: "Multicast Transport Protocol"}, + 93: {keyword: "AX.25", protocol: "AX.25 Frames"}, + 94: {keyword: "IPIP", protocol: "IP-within-IP Encapsulation Protocol"}, + 95: {keyword: "MICP (deprecated)", protocol: "Mobile Internetworking Control Pro."}, + 96: {keyword: "SCC-SP", protocol: "Semaphore Communications Sec. Pro."}, + 97: {keyword: "ETHERIP", protocol: "Ethernet-within-IP Encapsulation"}, + 98: {keyword: "ENCAP", protocol: "Encapsulation Header"}, + 99: {keyword: "", protocol: "any private encryption scheme"}, + 100: {keyword: "GMTP", protocol: "GMTP"}, + 101: {keyword: "IFMP", protocol: "Ipsilon Flow Management Protocol"}, + 102: {keyword: "PNNI", protocol: "PNNI over IP"}, + 103: {keyword: "PIM", protocol: "Protocol Independent Multicast"}, + 104: {keyword: "ARIS", protocol: "ARIS"}, + 105: {keyword: "SCPS", protocol: "SCPS"}, + 106: {keyword: "QNX", protocol: "QNX"}, + 107: {keyword: "A/N", protocol: "Active Networks"}, + 108: {keyword: "IPComp", protocol: "IP Payload Compression Protocol"}, + 109: {keyword: "SNP", protocol: "Sitara Networks Protocol"}, + 110: {keyword: "Compaq-Peer", protocol: "Compaq Peer Protocol"}, + 111: {keyword: "IPX-in-IP", protocol: "IPX in IP"}, + 112: {keyword: "VRRP", protocol: "Virtual Router Redundancy Protocol"}, + 113: {keyword: "PGM", protocol: "PGM Reliable Transport Protocol"}, + 114: {keyword: "", protocol: "any 0-hop protocol"}, + 115: {keyword: "L2TP", protocol: "Layer Two Tunneling Protocol"}, + 116: {keyword: "DDX", protocol: "D-II Data Exchange (DDX)"}, + 117: {keyword: "IATP", protocol: "Interactive Agent Transfer Protocol"}, + 118: {keyword: "STP", protocol: "Schedule Transfer Protocol"}, + 119: {keyword: "SRP", protocol: "SpectraLink Radio Protocol"}, + 120: {keyword: "UTI", protocol: "UTI"}, + 121: {keyword: "SMP", protocol: "Simple Message Protocol"}, + 122: {keyword: "SM (deprecated)", protocol: "Simple Multicast Protocol"}, + 123: {keyword: "PTP", protocol: "Performance Transparency Protocol"}, + 124: {keyword: "ISIS over IPv4", protocol: ""}, + 125: {keyword: "FIRE", protocol: ""}, + 126: {keyword: "CRTP", protocol: "Combat Radio Transport Protocol"}, + 127: {keyword: "CRUDP", protocol: "Combat Radio User Datagram"}, + 128: {keyword: "SSCOPMCE", protocol: ""}, + 129: {keyword: "IPLT", protocol: ""}, + 130: {keyword: "SPS", protocol: "Secure Packet Shield"}, + 131: {keyword: "PIPE", protocol: "Private IP Encapsulation within IP"}, + 132: {keyword: "SCTP", protocol: "Stream Control Transmission Protocol"}, + 133: {keyword: "FC", protocol: "Fibre Channel"}, + 134: {keyword: "RSVP-E2E-IGNORE", protocol: ""}, + 135: {keyword: "Mobility Header", protocol: ""}, + 136: {keyword: "UDPLite", protocol: ""}, + 137: {keyword: "MPLS-in-IP", protocol: ""}, + 138: {keyword: "manet", protocol: "MANET Protocols"}, + 139: {keyword: "HIP", protocol: "Host Identity Protocol"}, + 140: {keyword: "Shim6", protocol: "Shim6 Protocol"}, + 141: {keyword: "WESP", protocol: "Wrapped Encapsulating Security Payload"}, + 142: {keyword: "ROHC", protocol: "Robust Header Compression"}, + 253: {keyword: "", protocol: "Use for experimentation and testing"}, + 254: {keyword: "", protocol: "Use for experimentation and testing"}, + 255: {keyword: "Reserved", protocol: ""} +}; + + +/** + * Generates an checksum, based upon provided raw input, for use with TCP/IP. + * + * @private + * @param {byteArray} input + * @returns {string} + */ +export function calculateTCPIPChecksum(input){ + let csum = 0; + + for (let i = 0; i < input.length; i++) { + if (i % 2 === 0) { + csum += (input[i] << 8); + } else { + csum += input[i]; + } + } + + csum = (csum >> 16) + (csum & 0xffff); + + return Utils.hex(0xffff - csum); +} From 161f89c03819860d002a2cb2566f20dba6d7fce8 Mon Sep 17 00:00:00 2001 From: Callum Fraser Date: Wed, 16 May 2018 21:50:48 +0100 Subject: [PATCH 06/10] Ported the TCPIPChecksum operation. Main content has been moved to the IP lib file, as it is used in multiple files. Changed the name, due to it originally containing a backslash, which caused issues with the script. --- src/core/operations/TCPIPChecksum.mjs | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/core/operations/TCPIPChecksum.mjs diff --git a/src/core/operations/TCPIPChecksum.mjs b/src/core/operations/TCPIPChecksum.mjs new file mode 100644 index 00000000..e31cb511 --- /dev/null +++ b/src/core/operations/TCPIPChecksum.mjs @@ -0,0 +1,40 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import {calculateTCPIPChecksum} from "../lib/Ip"; + +/** + * TCP/IP Checksum operation + */ +class TCPIPChecksum extends Operation { + + /** + * TCP/IPChecksum constructor + */ + constructor() { + super(); + + this.name = "TCP/IP Checksum"; + this.module = "Hashing"; + this.description = "Calculates the checksum for a TCP (Transport Control Protocol) or IP (Internet Protocol) header from an input of raw bytes."; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return calculateTCPIPChecksum(input); + } + +} + +export default TCPIPChecksum; From 792218df9c5952aa75615f439e7badac82682cec Mon Sep 17 00:00:00 2001 From: Callum Fraser Date: Wed, 16 May 2018 21:51:04 +0100 Subject: [PATCH 07/10] Ported the ChangeIPFormat operation. --- src/core/operations/ChangeIPFormat.mjs | 121 +++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/core/operations/ChangeIPFormat.mjs diff --git a/src/core/operations/ChangeIPFormat.mjs b/src/core/operations/ChangeIPFormat.mjs new file mode 100644 index 00000000..af3f8fc7 --- /dev/null +++ b/src/core/operations/ChangeIPFormat.mjs @@ -0,0 +1,121 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {fromHex} from "../lib/Hex"; + +/** + * Change IP format operation + */ +class ChangeIPFormat extends Operation { + + /** + * ChangeIPFormat constructor + */ + constructor() { + super(); + + this.name = "Change IP format"; + this.module = "JSBN"; + this.description = "Convert an IP address from one format to another, e.g. 172.20.23.54 to ac141736"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Input format", + "type": "option", + "value": ["Hex", "Raw"] + }, + { + "name": "Output format", + "type": "option", + "value": ["Hex", "Raw"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const inFormat = args[0], + outFormat = args[1], + lines = input.split("\n"); + let output = "", + j = 0; + + + for (let i = 0; i < lines.length; i++) { + if (lines[i] === "") continue; + let baIp = []; + let octets; + let decimal; + + if (inFormat === outFormat) { + output += lines[i] + "\n"; + continue; + } + + // Convert to byte array IP from input format + switch (inFormat) { + case "Dotted Decimal": + octets = lines[i].split("."); + for (j = 0; j < octets.length; j++) { + baIp.push(parseInt(octets[j], 10)); + } + break; + case "Decimal": + decimal = lines[i].toString(); + baIp.push(decimal >> 24 & 255); + baIp.push(decimal >> 16 & 255); + baIp.push(decimal >> 8 & 255); + baIp.push(decimal & 255); + break; + case "Hex": + baIp = fromHex(lines[i]); + break; + default: + throw "Unsupported input IP format"; + } + + let ddIp; + let decIp; + let hexIp; + + // Convert byte array IP to output format + switch (outFormat) { + case "Dotted Decimal": + ddIp = ""; + for (j = 0; j < baIp.length; j++) { + ddIp += baIp[j] + "."; + } + output += ddIp.slice(0, ddIp.length-1) + "\n"; + break; + case "Decimal": + decIp = ((baIp[0] << 24) | (baIp[1] << 16) | (baIp[2] << 8) | baIp[3]) >>> 0; + output += decIp.toString() + "\n"; + break; + case "Hex": + hexIp = ""; + for (j = 0; j < baIp.length; j++) { + hexIp += Utils.hex(baIp[j]); + } + output += hexIp + "\n"; + break; + default: + throw "Unsupported output IP format"; + } + } + + return output.slice(0, output.length-1); + } + +} + +export default ChangeIPFormat; From b7bdd4eed6a3d712b129d798b100ac6d080a166b Mon Sep 17 00:00:00 2001 From: Callum Fraser Date: Wed, 16 May 2018 21:51:24 +0100 Subject: [PATCH 08/10] Ported the GroupIPAddresses operation. --- src/core/operations/GroupIPAddresses.mjs | 134 +++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/core/operations/GroupIPAddresses.mjs diff --git a/src/core/operations/GroupIPAddresses.mjs b/src/core/operations/GroupIPAddresses.mjs new file mode 100644 index 00000000..6ff5023b --- /dev/null +++ b/src/core/operations/GroupIPAddresses.mjs @@ -0,0 +1,134 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {_ipv6ToStr, _genIpv6Mask, IPV4_REGEX, _strToIpv6, _ipv4ToStr, IPV6_REGEX, _strToIpv4} from "../lib/Ip"; + +/** + * Group IP addresses operation + */ +class GroupIPAddresses extends Operation { + + /** + * GroupIPAddresses constructor + */ + constructor() { + super(); + + this.name = "Group IP addresses"; + this.module = "JSBN"; + this.description = "Groups a list of IP addresses into subnets. Supports both IPv4 and IPv6 addresses."; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Delimiter", + "type": "option", + "value": ["Line feed", "CRLF", "Space", "Comma", "Semi-colon"] + }, + { + "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, + ipv6Mask = _genIpv6Mask(cidr), + ips = input.split(delim), + ipv4Networks = {}, + ipv6Networks = {}; + let match = null, + output = "", + ip = null, + network = null, + networkStr = "", + i; + + if (cidr < 0 || cidr > 127) { + return "CIDR must be less than 32 for IPv4 or 128 for IPv6"; + } + + // Parse all IPs and add to network dictionary + for (i = 0; i < ips.length; i++) { + if ((match = IPV4_REGEX.exec(ips[i]))) { + ip = _strToIpv4(match[1]) >>> 0; + network = ip & ipv4Mask; + + if (ipv4Networks.hasOwnProperty(network)) { + ipv4Networks[network].push(ip); + } else { + ipv4Networks[network] = [ip]; + } + } else if ((match = IPV6_REGEX.exec(ips[i]))) { + ip = _strToIpv6(match[1]); + network = []; + networkStr = ""; + + for (let j = 0; j < 8; j++) { + network.push(ip[j] & ipv6Mask[j]); + } + + networkStr = _ipv6ToStr(network, true); + + if (ipv6Networks.hasOwnProperty(networkStr)) { + ipv6Networks[networkStr].push(ip); + } else { + ipv6Networks[networkStr] = [ip]; + } + } + } + + // Sort IPv4 network dictionaries and print + for (network in ipv4Networks) { + ipv4Networks[network] = ipv4Networks[network].sort(); + + output += _ipv4ToStr(network) + "/" + cidr + "\n"; + + if (!onlySubnets) { + for (i = 0; i < ipv4Networks[network].length; i++) { + output += " " + _ipv4ToStr(ipv4Networks[network][i]) + "\n"; + } + output += "\n"; + } + } + + // Sort IPv6 network dictionaries and print + for (networkStr in ipv6Networks) { + //ipv6Networks[networkStr] = ipv6Networks[networkStr].sort(); TODO + + output += networkStr + "/" + cidr + "\n"; + + if (!onlySubnets) { + for (i = 0; i < ipv6Networks[networkStr].length; i++) { + output += " " + _ipv6ToStr(ipv6Networks[networkStr][i], true) + "\n"; + } + output += "\n"; + } + } + + return output; + } + +} + +export default GroupIPAddresses; From c17e89767415dd72bae3e70ee4f00e29d47dab5e Mon Sep 17 00:00:00 2001 From: Callum Fraser Date: Wed, 16 May 2018 21:51:51 +0100 Subject: [PATCH 09/10] Ported the ParseIPv4Header operation. --- src/core/operations/ParseIPv4Header.mjs | 127 ++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 src/core/operations/ParseIPv4Header.mjs diff --git a/src/core/operations/ParseIPv4Header.mjs b/src/core/operations/ParseIPv4Header.mjs new file mode 100644 index 00000000..d88d6f60 --- /dev/null +++ b/src/core/operations/ParseIPv4Header.mjs @@ -0,0 +1,127 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {fromHex, toHex} from "../lib/Hex"; +import {_ipv4ToStr, _protocolLookup, calculateTCPIPChecksum} from "../lib/Ip"; + +/** + * Parse IPv4 header operation + */ +class ParseIPv4Header extends Operation { + + /** + * ParseIPv4Header constructor + */ + constructor() { + super(); + + this.name = "Parse IPv4 header"; + this.module = "JSBN"; + this.description = "Given an IPv4 header, this operations parses and displays each field in an easily readable format."; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + "name": "Input format", + "type": "option", + "value": ["Hex", "Raw"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const format = args[0]; + let output; + + if (format === "Hex") { + input = fromHex(input); + } else if (format === "Raw") { + input = Utils.strToByteArray(input); + } else { + return "Unrecognised input format."; + } + + let ihl = input[0] & 0x0f; + const dscp = (input[1] >>> 2) & 0x3f, + ecn = input[1] & 0x03, + length = input[2] << 8 | input[3], + identification = input[4] << 8 | input[5], + flags = (input[6] >>> 5) & 0x07, + fragOffset = (input[6] & 0x1f) << 8 | input[7], + ttl = input[8], + protocol = input[9], + checksum = input[10] << 8 | input[11], + srcIP = input[12] << 24 | input[13] << 16 | input[14] << 8 | input[15], + dstIP = input[16] << 24 | input[17] << 16 | input[18] << 8 | input[19], + checksumHeader = input.slice(0, 10).concat([0, 0]).concat(input.slice(12, 20)); + let version = (input[0] >>> 4) & 0x0f, + options = []; + + + // Version + if (version !== 4) { + version = version + " (Error: for IPv4 headers, this should always be set to 4)"; + } + + // IHL + if (ihl < 5) { + ihl = ihl + " (Error: this should always be at least 5)"; + } else if (ihl > 5) { + // sort out options... + const optionsLen = ihl * 4 - 20; + options = input.slice(20, optionsLen + 20); + } + + // Protocol + const protocolInfo = _protocolLookup[protocol] || {keyword: "", protocol: ""}; + + // Checksum + const correctChecksum = calculateTCPIPChecksum(checksumHeader), + givenChecksum = Utils.hex(checksum); + let checksumResult; + if (correctChecksum === givenChecksum) { + checksumResult = givenChecksum + " (correct)"; + } else { + checksumResult = givenChecksum + " (incorrect, should be " + correctChecksum + ")"; + } + + output = "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + if (ihl > 5) { + output += ""; + } + + return output + "
FieldValue
Version" + version + "
Internet Header Length (IHL)" + ihl + " (" + (ihl * 4) + " bytes)
Differentiated Services Code Point (DSCP)" + dscp + "
Explicit Congestion Notification (ECN)" + ecn + "
Total length" + length + " bytes" + + "\n IP header: " + (ihl * 4) + " bytes" + + "\n Data: " + (length - ihl * 4) + " bytes
Identification0x" + Utils.hex(identification) + " (" + identification + ")
Flags0x" + Utils.hex(flags, 2) + + "\n Reserved bit:" + (flags >> 2) + " (must be 0)" + + "\n Don't fragment:" + (flags >> 1 & 1) + + "\n More fragments:" + (flags & 1) + "
Fragment offset" + fragOffset + "
Time-To-Live" + ttl + "
Protocol" + protocol + ", " + protocolInfo.protocol + " (" + protocolInfo.keyword + ")
Header checksum" + checksumResult + "
Source IP address" + _ipv4ToStr(srcIP) + "
Destination IP address" + _ipv4ToStr(dstIP) + "
Options" + toHex(options) + "
"; + } + +} + +export default ParseIPv4Header; From 3ba12ae9ac7fe16cb36c36cee5fb664dfa923512 Mon Sep 17 00:00:00 2001 From: Callum Fraser Date: Wed, 16 May 2018 22:32:46 +0100 Subject: [PATCH 10/10] Made variables non-private, and followed convention for the references to the IP lib. --- src/core/lib/Ip.mjs | 80 ++++++++++++------------ src/core/operations/ChangeIPFormat.mjs | 2 +- src/core/operations/GroupIPAddresses.mjs | 16 ++--- src/core/operations/ParseIPRange.mjs | 10 +-- src/core/operations/ParseIPv4Header.mjs | 10 +-- src/core/operations/ParseIPv6Address.mjs | 20 +++--- src/core/operations/TCPIPChecksum.mjs | 2 +- 7 files changed, 70 insertions(+), 70 deletions(-) diff --git a/src/core/lib/Ip.mjs b/src/core/lib/Ip.mjs index f63c3f9d..67e69c03 100644 --- a/src/core/lib/Ip.mjs +++ b/src/core/lib/Ip.mjs @@ -10,8 +10,8 @@ import Utils from "../Utils"; * @param {boolean} allowLargeList * @returns {string} */ -export function _ipv4CidrRange(cidr, includeNetworkInfo, enumerateAddresses, allowLargeList) { - const network = _strToIpv4(cidr[1]), +export function ipv4CidrRange(cidr, includeNetworkInfo, enumerateAddresses, allowLargeList) { + const network = strToIpv4(cidr[1]), cidrRange = parseInt(cidr[2], 10); let output = ""; @@ -24,16 +24,16 @@ export function _ipv4CidrRange(cidr, includeNetworkInfo, enumerateAddresses, all ip2 = ip1 | ~mask; if (includeNetworkInfo) { - output += "Network: " + _ipv4ToStr(network) + "\n"; + output += "Network: " + ipv4ToStr(network) + "\n"; output += "CIDR: " + cidrRange + "\n"; - output += "Mask: " + _ipv4ToStr(mask) + "\n"; - output += "Range: " + _ipv4ToStr(ip1) + " - " + _ipv4ToStr(ip2) + "\n"; + output += "Mask: " + ipv4ToStr(mask) + "\n"; + output += "Range: " + ipv4ToStr(ip1) + " - " + ipv4ToStr(ip2) + "\n"; output += "Total addresses in range: " + (((ip2 - ip1) >>> 0) + 1) + "\n\n"; } if (enumerateAddresses) { if (cidrRange >= 16 || allowLargeList) { - output += _generateIpv4Range(ip1, ip2).join("\n"); + output += generateIpv4Range(ip1, ip2).join("\n"); } else { output += _LARGE_RANGE_ERROR; } @@ -49,9 +49,9 @@ export function _ipv4CidrRange(cidr, includeNetworkInfo, enumerateAddresses, all * @param {boolean} includeNetworkInfo * @returns {string} */ -export function _ipv6CidrRange(cidr, includeNetworkInfo) { +export function ipv6CidrRange(cidr, includeNetworkInfo) { let output = ""; - const network = _strToIpv6(cidr[1]), + const network = strToIpv6(cidr[1]), cidrRange = parseInt(cidr[cidr.length-1], 10); if (cidrRange < 0 || cidrRange > 127) { @@ -62,7 +62,7 @@ export function _ipv6CidrRange(cidr, includeNetworkInfo) { ip2 = new Array(8), total = new Array(128); - const mask = _genIpv6Mask(cidrRange); + const mask = genIpv6Mask(cidrRange); let totalDiff = ""; @@ -79,11 +79,11 @@ export function _ipv6CidrRange(cidr, includeNetworkInfo) { } if (includeNetworkInfo) { - output += "Network: " + _ipv6ToStr(network) + "\n"; - output += "Shorthand: " + _ipv6ToStr(network, true) + "\n"; + output += "Network: " + ipv6ToStr(network) + "\n"; + output += "Shorthand: " + ipv6ToStr(network, true) + "\n"; output += "CIDR: " + cidrRange + "\n"; - output += "Mask: " + _ipv6ToStr(mask) + "\n"; - output += "Range: " + _ipv6ToStr(ip1) + " - " + _ipv6ToStr(ip2) + "\n"; + output += "Mask: " + ipv6ToStr(mask) + "\n"; + output += "Range: " + ipv6ToStr(ip1) + " - " + ipv6ToStr(ip2) + "\n"; output += "Total addresses in range: " + (parseInt(total.join(""), 2) + 1) + "\n\n"; } @@ -101,9 +101,9 @@ export function _ipv6CidrRange(cidr, includeNetworkInfo) { * @param {boolean} allowLargeList * @returns {string} */ -export function _ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList) { - const ip1 = _strToIpv4(range[1]), - ip2 = _strToIpv4(range[2]); +export function ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList) { + const ip1 = strToIpv4(range[1]), + ip2 = strToIpv4(range[2]); let output = ""; // Calculate mask @@ -124,18 +124,18 @@ export function _ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddress if (includeNetworkInfo) { output += "Minimum subnet required to hold this range:\n"; - output += "\tNetwork: " + _ipv4ToStr(network) + "\n"; + output += "\tNetwork: " + ipv4ToStr(network) + "\n"; output += "\tCIDR: " + cidr + "\n"; - output += "\tMask: " + _ipv4ToStr(mask) + "\n"; - output += "\tSubnet range: " + _ipv4ToStr(subIp1) + " - " + _ipv4ToStr(subIp2) + "\n"; + output += "\tMask: " + ipv4ToStr(mask) + "\n"; + output += "\tSubnet range: " + ipv4ToStr(subIp1) + " - " + ipv4ToStr(subIp2) + "\n"; output += "\tTotal addresses in subnet: " + (((subIp2 - subIp1) >>> 0) + 1) + "\n\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"; } if (enumerateAddresses) { if (((ip2 - ip1) >>> 0) <= 65536 || allowLargeList) { - output += _generateIpv4Range(ip1, ip2).join("\n"); + output += generateIpv4Range(ip1, ip2).join("\n"); } else { output += _LARGE_RANGE_ERROR; } @@ -152,9 +152,9 @@ export function _ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddress * @param {boolean} includeNetworkInfo * @returns {string} */ -export function _ipv6HyphenatedRange(range, includeNetworkInfo) { - const ip1 = _strToIpv6(range[1]), - ip2 = _strToIpv6(range[14]), +export function ipv6HyphenatedRange(range, includeNetworkInfo) { + const ip1 = strToIpv6(range[1]), + ip2 = strToIpv6(range[14]), total = new Array(128).fill(); let output = "", @@ -171,8 +171,8 @@ export function _ipv6HyphenatedRange(range, includeNetworkInfo) { } if (includeNetworkInfo) { - output += "Range: " + _ipv6ToStr(ip1) + " - " + _ipv6ToStr(ip2) + "\n"; - output += "Shorthand range: " + _ipv6ToStr(ip1, true) + " - " + _ipv6ToStr(ip2, true) + "\n"; + output += "Range: " + ipv6ToStr(ip1) + " - " + ipv6ToStr(ip2) + "\n"; + output += "Shorthand range: " + ipv6ToStr(ip1, true) + " - " + ipv6ToStr(ip2, true) + "\n"; output += "Total addresses in range: " + (parseInt(total.join(""), 2) + 1) + "\n\n"; } @@ -188,9 +188,9 @@ export function _ipv6HyphenatedRange(range, includeNetworkInfo) { * * @example * // returns 168427520 - * _strToIpv4("10.10.0.0"); + * strToIpv4("10.10.0.0"); */ -export function _strToIpv4(ipStr) { +export function strToIpv4(ipStr) { const blocks = ipStr.split("."), numBlocks = parseBlocks(blocks); let result = 0; @@ -229,9 +229,9 @@ export function _strToIpv4(ipStr) { * * @example * // returns "10.10.0.0" - * _ipv4ToStr(168427520); + * ipv4ToStr(168427520); */ -export function _ipv4ToStr(ipInt) { +export function ipv4ToStr(ipInt) { const blockA = (ipInt >> 24) & 255, blockB = (ipInt >> 16) & 255, blockC = (ipInt >> 8) & 255, @@ -250,9 +250,9 @@ export function _ipv4ToStr(ipInt) { * * @example * // returns [65280, 0, 0, 0, 0, 0, 4369, 8738] - * _strToIpv6("ff00::1111:2222"); + * strToIpv6("ff00::1111:2222"); */ -export function _strToIpv6(ipStr) { +export function strToIpv6(ipStr) { let j = 0; const blocks = ipStr.split(":"), numBlocks = parseBlocks(blocks), @@ -296,12 +296,12 @@ export function _strToIpv6(ipStr) { * * @example * // returns "ff00::1111:2222" - * _ipv6ToStr([65280, 0, 0, 0, 0, 0, 4369, 8738], true); + * ipv6ToStr([65280, 0, 0, 0, 0, 0, 4369, 8738], true); * * // returns "ff00:0000:0000:0000:0000:0000:1111:2222" - * _ipv6ToStr([65280, 0, 0, 0, 0, 0, 4369, 8738], false); + * ipv6ToStr([65280, 0, 0, 0, 0, 0, 4369, 8738], false); */ -export function _ipv6ToStr(ipv6, compact) { +export function ipv6ToStr(ipv6, compact) { let output = "", i = 0; @@ -352,13 +352,13 @@ export function _ipv6ToStr(ipv6, compact) { * * @example * // returns ["0.0.0.1", "0.0.0.2", "0.0.0.3"] - * IP._generateIpv4Range(1, 3); + * IP.generateIpv4Range(1, 3); */ -export function _generateIpv4Range(ip, endIp) { +export function generateIpv4Range(ip, endIp) { const range = []; if (endIp >= ip) { for (; ip <= endIp; ip++) { - range.push(_ipv4ToStr(ip)); + range.push(ipv4ToStr(ip)); } } else { range[0] = "Second IP address smaller than first."; @@ -373,7 +373,7 @@ export function _generateIpv4Range(ip, endIp) { * @param {number} cidr * @returns {number[]} */ -export function _genIpv6Mask(cidr) { +export function genIpv6Mask(cidr) { const mask = new Array(8); let shift; @@ -414,7 +414,7 @@ export const IPV6_REGEX = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|) * @private * @constant */ -export const _protocolLookup = { +export const protocolLookup = { 0: {keyword: "HOPOPT", protocol: "IPv6 Hop-by-Hop Option"}, 1: {keyword: "ICMP", protocol: "Internet Control Message"}, 2: {keyword: "IGMP", protocol: "Internet Group Management"}, diff --git a/src/core/operations/ChangeIPFormat.mjs b/src/core/operations/ChangeIPFormat.mjs index af3f8fc7..fcc43dea 100644 --- a/src/core/operations/ChangeIPFormat.mjs +++ b/src/core/operations/ChangeIPFormat.mjs @@ -6,7 +6,7 @@ import Operation from "../Operation"; import Utils from "../Utils"; -import {fromHex} from "../lib/Hex"; +import {fromHex} from "../lib/Hex.mjs"; /** * Change IP format operation diff --git a/src/core/operations/GroupIPAddresses.mjs b/src/core/operations/GroupIPAddresses.mjs index 6ff5023b..423f1b33 100644 --- a/src/core/operations/GroupIPAddresses.mjs +++ b/src/core/operations/GroupIPAddresses.mjs @@ -6,7 +6,7 @@ import Operation from "../Operation"; import Utils from "../Utils"; -import {_ipv6ToStr, _genIpv6Mask, IPV4_REGEX, _strToIpv6, _ipv4ToStr, IPV6_REGEX, _strToIpv4} from "../lib/Ip"; +import {ipv6ToStr, genIpv6Mask, IPV4_REGEX, strToIpv6, ipv4ToStr, IPV6_REGEX, strToIpv4} from "../lib/Ip.mjs"; /** * Group IP addresses operation @@ -53,7 +53,7 @@ class GroupIPAddresses extends Operation { cidr = args[1], onlySubnets = args[2], ipv4Mask = cidr < 32 ? ~(0xFFFFFFFF >>> cidr) : 0xFFFFFFFF, - ipv6Mask = _genIpv6Mask(cidr), + ipv6Mask = genIpv6Mask(cidr), ips = input.split(delim), ipv4Networks = {}, ipv6Networks = {}; @@ -71,7 +71,7 @@ class GroupIPAddresses extends Operation { // Parse all IPs and add to network dictionary for (i = 0; i < ips.length; i++) { if ((match = IPV4_REGEX.exec(ips[i]))) { - ip = _strToIpv4(match[1]) >>> 0; + ip = strToIpv4(match[1]) >>> 0; network = ip & ipv4Mask; if (ipv4Networks.hasOwnProperty(network)) { @@ -80,7 +80,7 @@ class GroupIPAddresses extends Operation { ipv4Networks[network] = [ip]; } } else if ((match = IPV6_REGEX.exec(ips[i]))) { - ip = _strToIpv6(match[1]); + ip = strToIpv6(match[1]); network = []; networkStr = ""; @@ -88,7 +88,7 @@ class GroupIPAddresses extends Operation { network.push(ip[j] & ipv6Mask[j]); } - networkStr = _ipv6ToStr(network, true); + networkStr = ipv6ToStr(network, true); if (ipv6Networks.hasOwnProperty(networkStr)) { ipv6Networks[networkStr].push(ip); @@ -102,11 +102,11 @@ class GroupIPAddresses extends Operation { for (network in ipv4Networks) { ipv4Networks[network] = ipv4Networks[network].sort(); - output += _ipv4ToStr(network) + "/" + cidr + "\n"; + output += ipv4ToStr(network) + "/" + cidr + "\n"; if (!onlySubnets) { for (i = 0; i < ipv4Networks[network].length; i++) { - output += " " + _ipv4ToStr(ipv4Networks[network][i]) + "\n"; + output += " " + ipv4ToStr(ipv4Networks[network][i]) + "\n"; } output += "\n"; } @@ -120,7 +120,7 @@ class GroupIPAddresses extends Operation { if (!onlySubnets) { for (i = 0; i < ipv6Networks[networkStr].length; i++) { - output += " " + _ipv6ToStr(ipv6Networks[networkStr][i], true) + "\n"; + output += " " + ipv6ToStr(ipv6Networks[networkStr][i], true) + "\n"; } output += "\n"; } diff --git a/src/core/operations/ParseIPRange.mjs b/src/core/operations/ParseIPRange.mjs index 30ebf3d2..dbc09ef8 100644 --- a/src/core/operations/ParseIPRange.mjs +++ b/src/core/operations/ParseIPRange.mjs @@ -5,7 +5,7 @@ */ import Operation from "../Operation"; -import {_ipv4CidrRange, _ipv4HyphenatedRange, _ipv6CidrRange, _ipv6HyphenatedRange} from "../lib/Ip"; +import {ipv4CidrRange, ipv4HyphenatedRange, ipv6CidrRange, ipv6HyphenatedRange} from "../lib/Ip"; /** * Parse IP range operation @@ -60,13 +60,13 @@ class ParseIPRange extends Operation { let match; if ((match = ipv4CidrRegex.exec(input))) { - return _ipv4CidrRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); + return ipv4CidrRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); } else if ((match = ipv4RangeRegex.exec(input))) { - return _ipv4HyphenatedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); + return ipv4HyphenatedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); } else if ((match = ipv6CidrRegex.exec(input))) { - return _ipv6CidrRange(match, includeNetworkInfo); + return ipv6CidrRange(match, includeNetworkInfo); } else if ((match = ipv6RangeRegex.exec(input))) { - return _ipv6HyphenatedRange(match, includeNetworkInfo); + return ipv6HyphenatedRange(match, includeNetworkInfo); } else { return "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."; } diff --git a/src/core/operations/ParseIPv4Header.mjs b/src/core/operations/ParseIPv4Header.mjs index d88d6f60..db1cc926 100644 --- a/src/core/operations/ParseIPv4Header.mjs +++ b/src/core/operations/ParseIPv4Header.mjs @@ -6,8 +6,8 @@ import Operation from "../Operation"; import Utils from "../Utils"; -import {fromHex, toHex} from "../lib/Hex"; -import {_ipv4ToStr, _protocolLookup, calculateTCPIPChecksum} from "../lib/Ip"; +import {fromHex, toHex} from "../lib/Hex.mjs"; +import {ipv4ToStr, protocolLookup, calculateTCPIPChecksum} from "../lib/Ip.mjs"; /** * Parse IPv4 header operation @@ -83,7 +83,7 @@ class ParseIPv4Header extends Operation { } // Protocol - const protocolInfo = _protocolLookup[protocol] || {keyword: "", protocol: ""}; + const protocolInfo = protocolLookup[protocol] || {keyword: "", protocol: ""}; // Checksum const correctChecksum = calculateTCPIPChecksum(checksumHeader), @@ -112,8 +112,8 @@ class ParseIPv4Header extends Operation { "Time-To-Live" + ttl + "" + "Protocol" + protocol + ", " + protocolInfo.protocol + " (" + protocolInfo.keyword + ")" + "Header checksum" + checksumResult + "" + - "Source IP address" + _ipv4ToStr(srcIP) + "" + - "Destination IP address" + _ipv4ToStr(dstIP) + ""; + "Source IP address" + ipv4ToStr(srcIP) + "" + + "Destination IP address" + ipv4ToStr(dstIP) + ""; if (ihl > 5) { output += "Options" + toHex(options) + ""; diff --git a/src/core/operations/ParseIPv6Address.mjs b/src/core/operations/ParseIPv6Address.mjs index 8eadc13b..eca7a46e 100644 --- a/src/core/operations/ParseIPv6Address.mjs +++ b/src/core/operations/ParseIPv6Address.mjs @@ -6,7 +6,7 @@ import Operation from "../Operation"; import Utils from "../Utils"; -import {_strToIpv6, _ipv6ToStr, _ipv4ToStr, IPV6_REGEX} from "../lib/Ip"; +import {strToIpv6, ipv6ToStr, ipv4ToStr, IPV6_REGEX} from "../lib/Ip.mjs"; import BigInteger from "jsbn"; /** @@ -38,9 +38,9 @@ class ParseIPv6Address extends Operation { output = ""; if ((match = IPV6_REGEX.exec(input))) { - const ipv6 = _strToIpv6(match[1]), - longhand = _ipv6ToStr(ipv6), - shorthand = _ipv6ToStr(ipv6, true); + const ipv6 = strToIpv6(match[1]), + longhand = ipv6ToStr(ipv6), + shorthand = ipv6ToStr(ipv6, true); output += "Longhand: " + longhand + "\nShorthand: " + shorthand + "\n"; @@ -57,13 +57,13 @@ class ParseIPv6Address extends Operation { ipv6[3] === 0 && ipv6[4] === 0 && ipv6[5] === 0xffff) { // IPv4-mapped IPv6 address output += "\nIPv4-mapped IPv6 address detected. IPv6 clients will be handled natively by default, and IPv4 clients appear as IPv6 clients at their IPv4-mapped IPv6 address."; - output += "\nMapped IPv4 address: " + _ipv4ToStr((ipv6[6] << 16) + ipv6[7]); + output += "\nMapped IPv4 address: " + ipv4ToStr((ipv6[6] << 16) + ipv6[7]); output += "\nIPv4-mapped IPv6 addresses range: ::ffff:0:0/96"; } else if (ipv6[0] === 0 && ipv6[1] === 0 && ipv6[2] === 0 && ipv6[3] === 0 && ipv6[4] === 0xffff && ipv6[5] === 0) { // IPv4-translated address output += "\nIPv4-translated address detected. Used by Stateless IP/ICMP Translation (SIIT). See RFCs 6145 and 6052 for more details."; - output += "\nTranslated IPv4 address: " + _ipv4ToStr((ipv6[6] << 16) + ipv6[7]); + output += "\nTranslated IPv4 address: " + ipv4ToStr((ipv6[6] << 16) + ipv6[7]); output += "\nIPv4-translated addresses range: ::ffff:0:0:0/96"; } else if (ipv6[0] === 0x100) { // Discard prefix per RFC 6666 @@ -73,7 +73,7 @@ class ParseIPv6Address extends Operation { ipv6[3] === 0 && ipv6[4] === 0 && ipv6[5] === 0) { // IPv4/IPv6 translation per RFC 6052 output += "\n'Well-Known' prefix for IPv4/IPv6 translation detected. See RFC 6052 for more details."; - output += "\nTranslated IPv4 address: " + _ipv4ToStr((ipv6[6] << 16) + ipv6[7]); + output += "\nTranslated IPv4 address: " + ipv4ToStr((ipv6[6] << 16) + ipv6[7]); output += "\n'Well-Known' prefix range: 64:ff9b::/96"; } else if (ipv6[0] === 0x2001 && ipv6[1] === 0) { // Teredo tunneling @@ -87,8 +87,8 @@ class ParseIPv6Address extends Operation { flagUg = (ipv6[4] >>> 8) & 3, flagRandom2 = ipv6[4] & 255; - output += "\nServer IPv4 address: " + _ipv4ToStr(serverIpv4) + - "\nClient IPv4 address: " + _ipv4ToStr(clientIpv4) + + output += "\nServer IPv4 address: " + ipv4ToStr(serverIpv4) + + "\nClient IPv4 address: " + ipv4ToStr(clientIpv4) + "\nClient UDP port: " + udpPort + "\nFlags:" + "\n\tCone: " + flagCone; @@ -142,7 +142,7 @@ class ParseIPv6Address extends Operation { output += "\n6to4 transition IPv6 address detected. See RFC 3056 for more details." + "\n6to4 prefix range: 2002::/16"; - const v4Addr = _ipv4ToStr((ipv6[1] << 16) + ipv6[2]), + const v4Addr = ipv4ToStr((ipv6[1] << 16) + ipv6[2]), slaId = ipv6[3], interfaceIdStr = ipv6[4].toString(16) + ipv6[5].toString(16) + ipv6[6].toString(16) + ipv6[7].toString(16), interfaceId = new BigInteger(interfaceIdStr, 16); diff --git a/src/core/operations/TCPIPChecksum.mjs b/src/core/operations/TCPIPChecksum.mjs index e31cb511..cc673777 100644 --- a/src/core/operations/TCPIPChecksum.mjs +++ b/src/core/operations/TCPIPChecksum.mjs @@ -5,7 +5,7 @@ */ import Operation from "../Operation"; -import {calculateTCPIPChecksum} from "../lib/Ip"; +import {calculateTCPIPChecksum} from "../lib/Ip.mjs"; /** * TCP/IP Checksum operation