| "use strict";
|
|
|
| var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
| if (k2 === undefined) k2 = k;
|
| var desc = Object.getOwnPropertyDescriptor(m, k);
|
| if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
| desc = { enumerable: true, get: function() { return m[k]; } };
|
| }
|
| Object.defineProperty(o, k2, desc);
|
| }) : (function(o, m, k, k2) {
|
| if (k2 === undefined) k2 = k;
|
| o[k2] = m[k];
|
| }));
|
| var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
| Object.defineProperty(o, "default", { enumerable: true, value: v });
|
| }) : function(o, v) {
|
| o["default"] = v;
|
| });
|
| var __importStar = (this && this.__importStar) || function (mod) {
|
| if (mod && mod.__esModule) return mod;
|
| var result = {};
|
| if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
| __setModuleDefault(result, mod);
|
| return result;
|
| };
|
| Object.defineProperty(exports, "__esModule", { value: true });
|
| exports.Address4 = void 0;
|
| const common = __importStar(require("./common"));
|
| const constants = __importStar(require("./v4/constants"));
|
| const address_error_1 = require("./address-error");
|
| const isCorrect4 = common.isCorrect(constants.BITS);
|
| |
| |
| |
|
|
| class Address4 {
|
| constructor(address) {
|
| this.groups = constants.GROUPS;
|
| this.parsedAddress = [];
|
| this.parsedSubnet = '';
|
| this.subnet = '/32';
|
| this.subnetMask = 32;
|
| this.v4 = true;
|
| |
| |
| |
|
|
| this.isCorrect = isCorrect4;
|
| |
| |
| |
|
|
| this.isInSubnet = common.isInSubnet;
|
| this.address = address;
|
| const subnet = constants.RE_SUBNET_STRING.exec(address);
|
| if (subnet) {
|
| this.parsedSubnet = subnet[0].replace('/', '');
|
| this.subnetMask = parseInt(this.parsedSubnet, 10);
|
| this.subnet = `/${this.subnetMask}`;
|
| if (this.subnetMask < 0 || this.subnetMask > constants.BITS) {
|
| throw new address_error_1.AddressError('Invalid subnet mask.');
|
| }
|
| address = address.replace(constants.RE_SUBNET_STRING, '');
|
| }
|
| this.addressMinusSuffix = address;
|
| this.parsedAddress = this.parse(address);
|
| }
|
| |
| |
| |
| |
| |
| |
|
|
| static isValid(address) {
|
| try {
|
|
|
| new Address4(address);
|
| return true;
|
| }
|
| catch (e) {
|
| return false;
|
| }
|
| }
|
| |
| |
| |
| |
| |
|
|
| parse(address) {
|
| const groups = address.split('.');
|
| if (!address.match(constants.RE_ADDRESS)) {
|
| throw new address_error_1.AddressError('Invalid IPv4 address.');
|
| }
|
| return groups;
|
| }
|
| |
| |
| |
| |
|
|
| correctForm() {
|
| return this.parsedAddress.map((part) => parseInt(part, 10)).join('.');
|
| }
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| static fromAddressAndMask(address, mask) {
|
| const bits = common.prefixLengthFromMask(new Address4(mask).bigInt(), constants.BITS);
|
| return new Address4(`${address}/${bits}`);
|
| }
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| static fromAddressAndWildcardMask(address, wildcardMask) {
|
| const wildcard = new Address4(wildcardMask).bigInt();
|
| const allOnes = (BigInt(1) << BigInt(constants.BITS)) - BigInt(1);
|
|
|
| const mask = wildcard ^ allOnes;
|
| const bits = common.prefixLengthFromMask(mask, constants.BITS);
|
| return new Address4(`${address}/${bits}`);
|
| }
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| static fromWildcard(input) {
|
| const groups = input.split('.');
|
| if (groups.length !== constants.GROUPS) {
|
| throw new address_error_1.AddressError('Wildcard pattern must have 4 octets');
|
| }
|
| let firstWildcard = -1;
|
| for (let i = 0; i < groups.length; i++) {
|
| if (groups[i] === '*') {
|
| if (firstWildcard === -1) {
|
| firstWildcard = i;
|
| }
|
| }
|
| else if (firstWildcard !== -1) {
|
| throw new address_error_1.AddressError('Wildcard `*` must only appear in trailing octets (e.g. `192.168.0.*`)');
|
| }
|
| }
|
| const trailing = firstWildcard === -1 ? 0 : groups.length - firstWildcard;
|
| const replaced = groups.map((g) => (g === '*' ? '0' : g));
|
| const subnetBits = constants.BITS - trailing * 8;
|
| return new Address4(`${replaced.join('.')}/${subnetBits}`);
|
| }
|
| |
| |
| |
| |
| |
| |
|
|
| static fromHex(hex) {
|
| const stripped = hex.replace(/:/g, '');
|
| if (!/^[0-9a-fA-F]{8}$/.test(stripped)) {
|
| throw new address_error_1.AddressError('IPv4 hex must be exactly 8 hex digits');
|
| }
|
| const groups = [];
|
| for (let i = 0; i < 8; i += 2) {
|
| groups.push(parseInt(stripped.slice(i, i + 2), 16));
|
| }
|
| return new Address4(groups.join('.'));
|
| }
|
| |
| |
| |
| |
| |
| |
|
|
| static fromInteger(integer) {
|
| if (!Number.isInteger(integer) || integer < 0 || integer > 0xffffffff) {
|
| throw new address_error_1.AddressError('IPv4 integer must be in the range 0 to 2**32 - 1');
|
| }
|
| return Address4.fromHex(integer.toString(16).padStart(8, '0'));
|
| }
|
| |
| |
| |
| |
| |
| |
| |
|
|
| static fromArpa(arpaFormAddress) {
|
|
|
| const leader = arpaFormAddress.replace(/(\.in-addr\.arpa)?\.$/, '');
|
| const address = leader.split('.').reverse().join('.');
|
| return new Address4(address);
|
| }
|
| |
| |
| |
|
|
| toHex() {
|
| return this.parsedAddress.map((part) => common.stringToPaddedHex(part)).join(':');
|
| }
|
| |
| |
| |
| |
| |
|
|
| toArray() {
|
| return this.parsedAddress.map((part) => parseInt(part, 10));
|
| }
|
| |
| |
| |
|
|
| toGroup6() {
|
| const output = [];
|
| let i;
|
| for (i = 0; i < constants.GROUPS; i += 2) {
|
| output.push(`${common.stringToPaddedHex(this.parsedAddress[i])}${common.stringToPaddedHex(this.parsedAddress[i + 1])}`);
|
| }
|
| return output.join(':');
|
| }
|
| |
| |
| |
|
|
| bigInt() {
|
| return BigInt(`0x${this.parsedAddress.map((n) => common.stringToPaddedHex(n)).join('')}`);
|
| }
|
| |
| |
| |
|
|
| _startAddress() {
|
| return BigInt(`0b${this.mask() + '0'.repeat(constants.BITS - this.subnetMask)}`);
|
| }
|
| |
| |
| |
| |
|
|
| startAddress() {
|
| return Address4.fromBigInt(this._startAddress());
|
| }
|
| |
| |
| |
| |
|
|
| startAddressExclusive() {
|
| const adjust = BigInt('1');
|
| return Address4.fromBigInt(this._startAddress() + adjust);
|
| }
|
| |
| |
| |
|
|
| _endAddress() {
|
| return BigInt(`0b${this.mask() + '1'.repeat(constants.BITS - this.subnetMask)}`);
|
| }
|
| |
| |
| |
| |
|
|
| endAddress() {
|
| return Address4.fromBigInt(this._endAddress());
|
| }
|
| |
| |
| |
| |
|
|
| endAddressExclusive() {
|
| const adjust = BigInt('1');
|
| return Address4.fromBigInt(this._endAddress() - adjust);
|
| }
|
| |
| |
| |
| |
|
|
| subnetMaskAddress() {
|
| return Address4.fromBigInt(BigInt(`0b${'1'.repeat(this.subnetMask)}${'0'.repeat(constants.BITS - this.subnetMask)}`));
|
| }
|
| |
| |
| |
| |
| |
|
|
| wildcardMask() {
|
| return Address4.fromBigInt(BigInt(`0b${'0'.repeat(this.subnetMask)}${'1'.repeat(constants.BITS - this.subnetMask)}`));
|
| }
|
| |
| |
| |
| |
| |
|
|
| networkForm() {
|
| return `${this.startAddress().correctForm()}/${this.subnetMask}`;
|
| }
|
| |
| |
| |
| |
| |
|
|
| static fromBigInt(bigInt) {
|
| if (bigInt < 0n || bigInt > 0xffffffffn) {
|
| throw new address_error_1.AddressError('IPv4 BigInt must be in the range 0 to 2**32 - 1');
|
| }
|
| return Address4.fromHex(bigInt.toString(16).padStart(8, '0'));
|
| }
|
| |
| |
| |
| |
| |
| |
|
|
| static fromByteArray(bytes) {
|
| if (bytes.length !== 4) {
|
| throw new address_error_1.AddressError('IPv4 addresses require exactly 4 bytes');
|
| }
|
|
|
| for (let i = 0; i < bytes.length; i++) {
|
| if (!Number.isInteger(bytes[i]) || bytes[i] < 0 || bytes[i] > 255) {
|
| throw new address_error_1.AddressError('All bytes must be integers between 0 and 255');
|
| }
|
| }
|
| return this.fromUnsignedByteArray(bytes);
|
| }
|
| |
| |
| |
| |
|
|
| static fromUnsignedByteArray(bytes) {
|
| if (bytes.length !== 4) {
|
| throw new address_error_1.AddressError('IPv4 addresses require exactly 4 bytes');
|
| }
|
| const address = bytes.join('.');
|
| return new Address4(address);
|
| }
|
| |
| |
| |
| |
|
|
| mask(mask) {
|
| if (mask === undefined) {
|
| mask = this.subnetMask;
|
| }
|
| return this.getBitsBase2(0, mask);
|
| }
|
| |
| |
| |
|
|
| getBitsBase2(start, end) {
|
| return this.binaryZeroPad().slice(start, end);
|
| }
|
| |
| |
| |
| |
| |
|
|
| reverseForm(options) {
|
| if (!options) {
|
| options = {};
|
| }
|
| const reversed = this.correctForm().split('.').reverse().join('.');
|
| if (options.omitSuffix) {
|
| return reversed;
|
| }
|
| return `${reversed}.in-addr.arpa.`;
|
| }
|
| |
| |
| |
|
|
| isMulticast() {
|
| return this.isInSubnet(MULTICAST_V4);
|
| }
|
| |
| |
| |
|
|
| isPrivate() {
|
| return PRIVATE_V4.some((subnet) => this.isInSubnet(subnet));
|
| }
|
| |
| |
| |
|
|
| isLoopback() {
|
| return this.isInSubnet(LOOPBACK_V4);
|
| }
|
| |
| |
| |
|
|
| isLinkLocal() {
|
| return this.isInSubnet(LINK_LOCAL_V4);
|
| }
|
| |
| |
| |
|
|
| isUnspecified() {
|
| return this.isInSubnet(UNSPECIFIED_V4);
|
| }
|
| |
| |
| |
|
|
| isBroadcast() {
|
| return this.isInSubnet(BROADCAST_V4);
|
| }
|
| |
| |
| |
|
|
| isCGNAT() {
|
| return this.isInSubnet(CGNAT_V4);
|
| }
|
| |
| |
| |
|
|
| binaryZeroPad() {
|
| if (this._binaryZeroPad === undefined) {
|
| this._binaryZeroPad = this.bigInt().toString(2).padStart(constants.BITS, '0');
|
| }
|
| return this._binaryZeroPad;
|
| }
|
| |
| |
| |
|
|
| groupForV6() {
|
| const segments = this.parsedAddress;
|
| return this.address.replace(constants.RE_ADDRESS, `<span class="hover-group group-v4 group-6">${segments
|
| .slice(0, 2)
|
| .join('.')}</span>.<span class="hover-group group-v4 group-7">${segments
|
| .slice(2, 4)
|
| .join('.')}</span>`);
|
| }
|
| }
|
| exports.Address4 = Address4;
|
| const MULTICAST_V4 = new Address4('224.0.0.0/4');
|
| const PRIVATE_V4 = [
|
| new Address4('10.0.0.0/8'),
|
| new Address4('172.16.0.0/12'),
|
| new Address4('192.168.0.0/16'),
|
| ];
|
| const LOOPBACK_V4 = new Address4('127.0.0.0/8');
|
| const LINK_LOCAL_V4 = new Address4('169.254.0.0/16');
|
| const UNSPECIFIED_V4 = new Address4('0.0.0.0/32');
|
| const BROADCAST_V4 = new Address4('255.255.255.255/32');
|
| const CGNAT_V4 = new Address4('100.64.0.0/10');
|
| |