From 9c73f3eda9b23eab5a934765ee98c520191d7d9d Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 26 Mar 2023 16:10:25 +0700 Subject: [PATCH] Initial commit --- app.js | 60 ++++++++++++++++++++++++++++++++++++++ index.html | 27 ++++++++++++++++++ ipclass.js | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 app.js create mode 100644 index.html create mode 100644 ipclass.js diff --git a/app.js b/app.js new file mode 100644 index 0000000..fc44680 --- /dev/null +++ b/app.js @@ -0,0 +1,60 @@ +"use strict"; + +let ip_input = null; +let mask_input = null; +let subnets_input = null; +let info_output = null; + +const dataChanged = function() { + try { + const ipData = ip_input.value; + const [fo, se, to, lo] = ipData.split(".").map(e => parseInt(e)); + console.log([fo, se, to, lo]); + if (fo === undefined || se === undefined || to === undefined || lo === undefined || + fo < 0 || se < 0 || to < 0 || lo < 0 || + fo > 255 || se > 255 || to > 255 || lo > 255) { + throw new Error("Wrong IP format"); + } + + const mask = ~~mask_input.value; + if (mask < 0 || mask > 31) { + throw new Error("Wrong mask (in range [0..32))"); + } + + const networkCapacity = Math.pow(2, 32 - mask); + const subnets = subnets_input.value.split(" ").map(e => ~e); + let cumNetSize = 0; + subnets.forEach(e => { + cumNetSize += e; + }); + if (cumNetSize > networkCapacity) { + throw new Error(`Cannot fit ${cumNetSize} in this subnet`); + } + + const ip = new IP(fo, se, to, lo); + const net = new Subnet(ip, mask); + + // info_output.textContent = `Subnet info for ${subnet.gateway.toString()}/${mask}\n`; + // info_output.textContent += `Subnet mask: ${subnet.mask.toString()}\n`; + // info_output.textContent += `Subnet capacity: ${subnet.subnetCapacity.toString()} addresses\n\n`; + // info_output.textContent += `First IP: ${subnet.firstIP.toString()}\n`; + // info_output.textContent += `Last IP: ${subnet.lastIP.toString()}\n`; + // info_output.textContent += `Broadcast IP: ${subnet.broadcastIP.toString()}\n`; + } catch (e) { + info_output.textContent = `Error:\n${e.message}`; + } +} + + +const init = function() { + ip_input = document.getElementById("ip"); + mask_input = document.getElementById("mask"); + subnets_input = document.getElementById("subnets"); + info_output = document.getElementById("subnects-info"); + + ip_input.addEventListener("input", dataChanged); + mask_input.addEventListener("input", dataChanged); + subnets_input.addEventListener("input", dataChanged); +} + +document.addEventListener("DOMContentLoaded", init); diff --git a/index.html b/index.html new file mode 100644 index 0000000..bf807dd --- /dev/null +++ b/index.html @@ -0,0 +1,27 @@ + + + + + + + Document + + + + + +
+

Net

+ / +
+
+

Subnets list

+ +
+
+

Subnets info

+
+        
+
+ + \ No newline at end of file diff --git a/ipclass.js b/ipclass.js new file mode 100644 index 0000000..3d6f7bb --- /dev/null +++ b/ipclass.js @@ -0,0 +1,84 @@ +"use strict"; + +class IP { + /** + * + * @param {Number} fo First octet + * @param {Number} se Second octet + * @param {Number} to Third octet + * @param {Number} lo Last octet + */ + constructor(fo, se, to, lo) { + this.raw = BigInt(fo) << 24n | BigInt(se) << 16n | BigInt(to) << 8n | BigInt(lo); + } + + /** + * + * @param {BigInt} num Amount to add + */ + add(num=1n) { + if (typeof(num) !== typeof(0n)) { + num = BigInt(num); + } + this.raw += num; + } + + /** + * + * @param {BigInt} num Amount to sub + */ + sub(num=1n) { + if (typeof(num) !== typeof(0n)) { + num = BigInt(num); + } + this.raw -= num; + } + + /** + * + * @param {Number} num Which octet to pull (0-based) + */ + octet(num) { + if (typeof(num) !== typeof(0n)) { + num = BigInt(num); + } + if (num > 3n) throw new Error("Four octets in IPv4 IP-address"); + + return this.raw >> (8n * (3n - num)) & 0xFFn; + } + + toString() { + return `${this.raw >> 24n & 0xFFn}.${this.raw >> 16n & 0xFFn}.${this.raw >> 8n & 0xFFn}.${this.raw & 0xFFn}`; + } + + clone() { + return new IP(this.octet(0n), this.octet(1n), this.octet(2n), this.octet(3n)); + } +} + +class Subnet { + /** + * + * @param {IP} ip + * @param {Number} subnetMask + */ + constructor(ip, subnetMask) { + this.subnetCapacity = Math.pow(2, 32 - subnetMask); + this.gateway = ip; + + const bmask = "".padStart(32 - subnetMask, 0).padStart(32, 1); + const fo = parseInt(bmask.substr(0, 8), 2); + const se = parseInt(bmask.substr(8, 8), 2); + const to = parseInt(bmask.substr(16, 8), 2); + const lo = parseInt(bmask.substr(24, 8), 2); + this.mask = new IP(fo, se, to, lo); + + this.firstIP = this.gateway.clone(); + this.firstIP.add(1); + this.lastIP = this.firstIP.clone(); + this.lastIP.add(this.subnetCapacity); + this.lastIP.sub(3); + this.broadcastIP = this.lastIP.clone(); + this.broadcastIP.add(1); + } +} \ No newline at end of file