11cb0ef41Sopenharmony_ci"use strict"; 21cb0ef41Sopenharmony_ci/* eslint-disable prefer-destructuring */ 31cb0ef41Sopenharmony_ci/* eslint-disable no-param-reassign */ 41cb0ef41Sopenharmony_civar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 51cb0ef41Sopenharmony_ci if (k2 === undefined) k2 = k; 61cb0ef41Sopenharmony_ci var desc = Object.getOwnPropertyDescriptor(m, k); 71cb0ef41Sopenharmony_ci if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 81cb0ef41Sopenharmony_ci desc = { enumerable: true, get: function() { return m[k]; } }; 91cb0ef41Sopenharmony_ci } 101cb0ef41Sopenharmony_ci Object.defineProperty(o, k2, desc); 111cb0ef41Sopenharmony_ci}) : (function(o, m, k, k2) { 121cb0ef41Sopenharmony_ci if (k2 === undefined) k2 = k; 131cb0ef41Sopenharmony_ci o[k2] = m[k]; 141cb0ef41Sopenharmony_ci})); 151cb0ef41Sopenharmony_civar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 161cb0ef41Sopenharmony_ci Object.defineProperty(o, "default", { enumerable: true, value: v }); 171cb0ef41Sopenharmony_ci}) : function(o, v) { 181cb0ef41Sopenharmony_ci o["default"] = v; 191cb0ef41Sopenharmony_ci}); 201cb0ef41Sopenharmony_civar __importStar = (this && this.__importStar) || function (mod) { 211cb0ef41Sopenharmony_ci if (mod && mod.__esModule) return mod; 221cb0ef41Sopenharmony_ci var result = {}; 231cb0ef41Sopenharmony_ci if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 241cb0ef41Sopenharmony_ci __setModuleDefault(result, mod); 251cb0ef41Sopenharmony_ci return result; 261cb0ef41Sopenharmony_ci}; 271cb0ef41Sopenharmony_ciObject.defineProperty(exports, "__esModule", { value: true }); 281cb0ef41Sopenharmony_ciexports.Address6 = void 0; 291cb0ef41Sopenharmony_ciconst common = __importStar(require("./common")); 301cb0ef41Sopenharmony_ciconst constants4 = __importStar(require("./v4/constants")); 311cb0ef41Sopenharmony_ciconst constants6 = __importStar(require("./v6/constants")); 321cb0ef41Sopenharmony_ciconst helpers = __importStar(require("./v6/helpers")); 331cb0ef41Sopenharmony_ciconst ipv4_1 = require("./ipv4"); 341cb0ef41Sopenharmony_ciconst regular_expressions_1 = require("./v6/regular-expressions"); 351cb0ef41Sopenharmony_ciconst address_error_1 = require("./address-error"); 361cb0ef41Sopenharmony_ciconst jsbn_1 = require("jsbn"); 371cb0ef41Sopenharmony_ciconst sprintf_js_1 = require("sprintf-js"); 381cb0ef41Sopenharmony_cifunction assert(condition) { 391cb0ef41Sopenharmony_ci if (!condition) { 401cb0ef41Sopenharmony_ci throw new Error('Assertion failed.'); 411cb0ef41Sopenharmony_ci } 421cb0ef41Sopenharmony_ci} 431cb0ef41Sopenharmony_cifunction addCommas(number) { 441cb0ef41Sopenharmony_ci const r = /(\d+)(\d{3})/; 451cb0ef41Sopenharmony_ci while (r.test(number)) { 461cb0ef41Sopenharmony_ci number = number.replace(r, '$1,$2'); 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci return number; 491cb0ef41Sopenharmony_ci} 501cb0ef41Sopenharmony_cifunction spanLeadingZeroes4(n) { 511cb0ef41Sopenharmony_ci n = n.replace(/^(0{1,})([1-9]+)$/, '<span class="parse-error">$1</span>$2'); 521cb0ef41Sopenharmony_ci n = n.replace(/^(0{1,})(0)$/, '<span class="parse-error">$1</span>$2'); 531cb0ef41Sopenharmony_ci return n; 541cb0ef41Sopenharmony_ci} 551cb0ef41Sopenharmony_ci/* 561cb0ef41Sopenharmony_ci * A helper function to compact an array 571cb0ef41Sopenharmony_ci */ 581cb0ef41Sopenharmony_cifunction compact(address, slice) { 591cb0ef41Sopenharmony_ci const s1 = []; 601cb0ef41Sopenharmony_ci const s2 = []; 611cb0ef41Sopenharmony_ci let i; 621cb0ef41Sopenharmony_ci for (i = 0; i < address.length; i++) { 631cb0ef41Sopenharmony_ci if (i < slice[0]) { 641cb0ef41Sopenharmony_ci s1.push(address[i]); 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci else if (i > slice[1]) { 671cb0ef41Sopenharmony_ci s2.push(address[i]); 681cb0ef41Sopenharmony_ci } 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci return s1.concat(['compact']).concat(s2); 711cb0ef41Sopenharmony_ci} 721cb0ef41Sopenharmony_cifunction paddedHex(octet) { 731cb0ef41Sopenharmony_ci return (0, sprintf_js_1.sprintf)('%04x', parseInt(octet, 16)); 741cb0ef41Sopenharmony_ci} 751cb0ef41Sopenharmony_cifunction unsignByte(b) { 761cb0ef41Sopenharmony_ci // eslint-disable-next-line no-bitwise 771cb0ef41Sopenharmony_ci return b & 0xff; 781cb0ef41Sopenharmony_ci} 791cb0ef41Sopenharmony_ci/** 801cb0ef41Sopenharmony_ci * Represents an IPv6 address 811cb0ef41Sopenharmony_ci * @class Address6 821cb0ef41Sopenharmony_ci * @param {string} address - An IPv6 address string 831cb0ef41Sopenharmony_ci * @param {number} [groups=8] - How many octets to parse 841cb0ef41Sopenharmony_ci * @example 851cb0ef41Sopenharmony_ci * var address = new Address6('2001::/32'); 861cb0ef41Sopenharmony_ci */ 871cb0ef41Sopenharmony_ciclass Address6 { 881cb0ef41Sopenharmony_ci constructor(address, optionalGroups) { 891cb0ef41Sopenharmony_ci this.addressMinusSuffix = ''; 901cb0ef41Sopenharmony_ci this.parsedSubnet = ''; 911cb0ef41Sopenharmony_ci this.subnet = '/128'; 921cb0ef41Sopenharmony_ci this.subnetMask = 128; 931cb0ef41Sopenharmony_ci this.v4 = false; 941cb0ef41Sopenharmony_ci this.zone = ''; 951cb0ef41Sopenharmony_ci // #region Attributes 961cb0ef41Sopenharmony_ci /** 971cb0ef41Sopenharmony_ci * Returns true if the given address is in the subnet of the current address 981cb0ef41Sopenharmony_ci * @memberof Address6 991cb0ef41Sopenharmony_ci * @instance 1001cb0ef41Sopenharmony_ci * @returns {boolean} 1011cb0ef41Sopenharmony_ci */ 1021cb0ef41Sopenharmony_ci this.isInSubnet = common.isInSubnet; 1031cb0ef41Sopenharmony_ci /** 1041cb0ef41Sopenharmony_ci * Returns true if the address is correct, false otherwise 1051cb0ef41Sopenharmony_ci * @memberof Address6 1061cb0ef41Sopenharmony_ci * @instance 1071cb0ef41Sopenharmony_ci * @returns {boolean} 1081cb0ef41Sopenharmony_ci */ 1091cb0ef41Sopenharmony_ci this.isCorrect = common.isCorrect(constants6.BITS); 1101cb0ef41Sopenharmony_ci if (optionalGroups === undefined) { 1111cb0ef41Sopenharmony_ci this.groups = constants6.GROUPS; 1121cb0ef41Sopenharmony_ci } 1131cb0ef41Sopenharmony_ci else { 1141cb0ef41Sopenharmony_ci this.groups = optionalGroups; 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci this.address = address; 1171cb0ef41Sopenharmony_ci const subnet = constants6.RE_SUBNET_STRING.exec(address); 1181cb0ef41Sopenharmony_ci if (subnet) { 1191cb0ef41Sopenharmony_ci this.parsedSubnet = subnet[0].replace('/', ''); 1201cb0ef41Sopenharmony_ci this.subnetMask = parseInt(this.parsedSubnet, 10); 1211cb0ef41Sopenharmony_ci this.subnet = `/${this.subnetMask}`; 1221cb0ef41Sopenharmony_ci if (Number.isNaN(this.subnetMask) || 1231cb0ef41Sopenharmony_ci this.subnetMask < 0 || 1241cb0ef41Sopenharmony_ci this.subnetMask > constants6.BITS) { 1251cb0ef41Sopenharmony_ci throw new address_error_1.AddressError('Invalid subnet mask.'); 1261cb0ef41Sopenharmony_ci } 1271cb0ef41Sopenharmony_ci address = address.replace(constants6.RE_SUBNET_STRING, ''); 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci else if (/\//.test(address)) { 1301cb0ef41Sopenharmony_ci throw new address_error_1.AddressError('Invalid subnet mask.'); 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci const zone = constants6.RE_ZONE_STRING.exec(address); 1331cb0ef41Sopenharmony_ci if (zone) { 1341cb0ef41Sopenharmony_ci this.zone = zone[0]; 1351cb0ef41Sopenharmony_ci address = address.replace(constants6.RE_ZONE_STRING, ''); 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci this.addressMinusSuffix = address; 1381cb0ef41Sopenharmony_ci this.parsedAddress = this.parse(this.addressMinusSuffix); 1391cb0ef41Sopenharmony_ci } 1401cb0ef41Sopenharmony_ci static isValid(address) { 1411cb0ef41Sopenharmony_ci try { 1421cb0ef41Sopenharmony_ci // eslint-disable-next-line no-new 1431cb0ef41Sopenharmony_ci new Address6(address); 1441cb0ef41Sopenharmony_ci return true; 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci catch (e) { 1471cb0ef41Sopenharmony_ci return false; 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci /** 1511cb0ef41Sopenharmony_ci * Convert a BigInteger to a v6 address object 1521cb0ef41Sopenharmony_ci * @memberof Address6 1531cb0ef41Sopenharmony_ci * @static 1541cb0ef41Sopenharmony_ci * @param {BigInteger} bigInteger - a BigInteger to convert 1551cb0ef41Sopenharmony_ci * @returns {Address6} 1561cb0ef41Sopenharmony_ci * @example 1571cb0ef41Sopenharmony_ci * var bigInteger = new BigInteger('1000000000000'); 1581cb0ef41Sopenharmony_ci * var address = Address6.fromBigInteger(bigInteger); 1591cb0ef41Sopenharmony_ci * address.correctForm(); // '::e8:d4a5:1000' 1601cb0ef41Sopenharmony_ci */ 1611cb0ef41Sopenharmony_ci static fromBigInteger(bigInteger) { 1621cb0ef41Sopenharmony_ci const hex = bigInteger.toString(16).padStart(32, '0'); 1631cb0ef41Sopenharmony_ci const groups = []; 1641cb0ef41Sopenharmony_ci let i; 1651cb0ef41Sopenharmony_ci for (i = 0; i < constants6.GROUPS; i++) { 1661cb0ef41Sopenharmony_ci groups.push(hex.slice(i * 4, (i + 1) * 4)); 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci return new Address6(groups.join(':')); 1691cb0ef41Sopenharmony_ci } 1701cb0ef41Sopenharmony_ci /** 1711cb0ef41Sopenharmony_ci * Convert a URL (with optional port number) to an address object 1721cb0ef41Sopenharmony_ci * @memberof Address6 1731cb0ef41Sopenharmony_ci * @static 1741cb0ef41Sopenharmony_ci * @param {string} url - a URL with optional port number 1751cb0ef41Sopenharmony_ci * @example 1761cb0ef41Sopenharmony_ci * var addressAndPort = Address6.fromURL('http://[ffff::]:8080/foo/'); 1771cb0ef41Sopenharmony_ci * addressAndPort.address.correctForm(); // 'ffff::' 1781cb0ef41Sopenharmony_ci * addressAndPort.port; // 8080 1791cb0ef41Sopenharmony_ci */ 1801cb0ef41Sopenharmony_ci static fromURL(url) { 1811cb0ef41Sopenharmony_ci let host; 1821cb0ef41Sopenharmony_ci let port = null; 1831cb0ef41Sopenharmony_ci let result; 1841cb0ef41Sopenharmony_ci // If we have brackets parse them and find a port 1851cb0ef41Sopenharmony_ci if (url.indexOf('[') !== -1 && url.indexOf(']:') !== -1) { 1861cb0ef41Sopenharmony_ci result = constants6.RE_URL_WITH_PORT.exec(url); 1871cb0ef41Sopenharmony_ci if (result === null) { 1881cb0ef41Sopenharmony_ci return { 1891cb0ef41Sopenharmony_ci error: 'failed to parse address with port', 1901cb0ef41Sopenharmony_ci address: null, 1911cb0ef41Sopenharmony_ci port: null, 1921cb0ef41Sopenharmony_ci }; 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci host = result[1]; 1951cb0ef41Sopenharmony_ci port = result[2]; 1961cb0ef41Sopenharmony_ci // If there's a URL extract the address 1971cb0ef41Sopenharmony_ci } 1981cb0ef41Sopenharmony_ci else if (url.indexOf('/') !== -1) { 1991cb0ef41Sopenharmony_ci // Remove the protocol prefix 2001cb0ef41Sopenharmony_ci url = url.replace(/^[a-z0-9]+:\/\//, ''); 2011cb0ef41Sopenharmony_ci // Parse the address 2021cb0ef41Sopenharmony_ci result = constants6.RE_URL.exec(url); 2031cb0ef41Sopenharmony_ci if (result === null) { 2041cb0ef41Sopenharmony_ci return { 2051cb0ef41Sopenharmony_ci error: 'failed to parse address from URL', 2061cb0ef41Sopenharmony_ci address: null, 2071cb0ef41Sopenharmony_ci port: null, 2081cb0ef41Sopenharmony_ci }; 2091cb0ef41Sopenharmony_ci } 2101cb0ef41Sopenharmony_ci host = result[1]; 2111cb0ef41Sopenharmony_ci // Otherwise just assign the URL to the host and let the library parse it 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci else { 2141cb0ef41Sopenharmony_ci host = url; 2151cb0ef41Sopenharmony_ci } 2161cb0ef41Sopenharmony_ci // If there's a port convert it to an integer 2171cb0ef41Sopenharmony_ci if (port) { 2181cb0ef41Sopenharmony_ci port = parseInt(port, 10); 2191cb0ef41Sopenharmony_ci // squelch out of range ports 2201cb0ef41Sopenharmony_ci if (port < 0 || port > 65536) { 2211cb0ef41Sopenharmony_ci port = null; 2221cb0ef41Sopenharmony_ci } 2231cb0ef41Sopenharmony_ci } 2241cb0ef41Sopenharmony_ci else { 2251cb0ef41Sopenharmony_ci // Standardize `undefined` to `null` 2261cb0ef41Sopenharmony_ci port = null; 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci return { 2291cb0ef41Sopenharmony_ci address: new Address6(host), 2301cb0ef41Sopenharmony_ci port, 2311cb0ef41Sopenharmony_ci }; 2321cb0ef41Sopenharmony_ci } 2331cb0ef41Sopenharmony_ci /** 2341cb0ef41Sopenharmony_ci * Create an IPv6-mapped address given an IPv4 address 2351cb0ef41Sopenharmony_ci * @memberof Address6 2361cb0ef41Sopenharmony_ci * @static 2371cb0ef41Sopenharmony_ci * @param {string} address - An IPv4 address string 2381cb0ef41Sopenharmony_ci * @returns {Address6} 2391cb0ef41Sopenharmony_ci * @example 2401cb0ef41Sopenharmony_ci * var address = Address6.fromAddress4('192.168.0.1'); 2411cb0ef41Sopenharmony_ci * address.correctForm(); // '::ffff:c0a8:1' 2421cb0ef41Sopenharmony_ci * address.to4in6(); // '::ffff:192.168.0.1' 2431cb0ef41Sopenharmony_ci */ 2441cb0ef41Sopenharmony_ci static fromAddress4(address) { 2451cb0ef41Sopenharmony_ci const address4 = new ipv4_1.Address4(address); 2461cb0ef41Sopenharmony_ci const mask6 = constants6.BITS - (constants4.BITS - address4.subnetMask); 2471cb0ef41Sopenharmony_ci return new Address6(`::ffff:${address4.correctForm()}/${mask6}`); 2481cb0ef41Sopenharmony_ci } 2491cb0ef41Sopenharmony_ci /** 2501cb0ef41Sopenharmony_ci * Return an address from ip6.arpa form 2511cb0ef41Sopenharmony_ci * @memberof Address6 2521cb0ef41Sopenharmony_ci * @static 2531cb0ef41Sopenharmony_ci * @param {string} arpaFormAddress - an 'ip6.arpa' form address 2541cb0ef41Sopenharmony_ci * @returns {Adress6} 2551cb0ef41Sopenharmony_ci * @example 2561cb0ef41Sopenharmony_ci * var address = Address6.fromArpa(e.f.f.f.3.c.2.6.f.f.f.e.6.6.8.e.1.0.6.7.9.4.e.c.0.0.0.0.1.0.0.2.ip6.arpa.) 2571cb0ef41Sopenharmony_ci * address.correctForm(); // '2001:0:ce49:7601:e866:efff:62c3:fffe' 2581cb0ef41Sopenharmony_ci */ 2591cb0ef41Sopenharmony_ci static fromArpa(arpaFormAddress) { 2601cb0ef41Sopenharmony_ci // remove ending ".ip6.arpa." or just "." 2611cb0ef41Sopenharmony_ci let address = arpaFormAddress.replace(/(\.ip6\.arpa)?\.$/, ''); 2621cb0ef41Sopenharmony_ci const semicolonAmount = 7; 2631cb0ef41Sopenharmony_ci // correct ip6.arpa form with ending removed will be 63 characters 2641cb0ef41Sopenharmony_ci if (address.length !== 63) { 2651cb0ef41Sopenharmony_ci throw new address_error_1.AddressError("Invalid 'ip6.arpa' form."); 2661cb0ef41Sopenharmony_ci } 2671cb0ef41Sopenharmony_ci const parts = address.split('.').reverse(); 2681cb0ef41Sopenharmony_ci for (let i = semicolonAmount; i > 0; i--) { 2691cb0ef41Sopenharmony_ci const insertIndex = i * 4; 2701cb0ef41Sopenharmony_ci parts.splice(insertIndex, 0, ':'); 2711cb0ef41Sopenharmony_ci } 2721cb0ef41Sopenharmony_ci address = parts.join(''); 2731cb0ef41Sopenharmony_ci return new Address6(address); 2741cb0ef41Sopenharmony_ci } 2751cb0ef41Sopenharmony_ci /** 2761cb0ef41Sopenharmony_ci * Return the Microsoft UNC transcription of the address 2771cb0ef41Sopenharmony_ci * @memberof Address6 2781cb0ef41Sopenharmony_ci * @instance 2791cb0ef41Sopenharmony_ci * @returns {String} the Microsoft UNC transcription of the address 2801cb0ef41Sopenharmony_ci */ 2811cb0ef41Sopenharmony_ci microsoftTranscription() { 2821cb0ef41Sopenharmony_ci return (0, sprintf_js_1.sprintf)('%s.ipv6-literal.net', this.correctForm().replace(/:/g, '-')); 2831cb0ef41Sopenharmony_ci } 2841cb0ef41Sopenharmony_ci /** 2851cb0ef41Sopenharmony_ci * Return the first n bits of the address, defaulting to the subnet mask 2861cb0ef41Sopenharmony_ci * @memberof Address6 2871cb0ef41Sopenharmony_ci * @instance 2881cb0ef41Sopenharmony_ci * @param {number} [mask=subnet] - the number of bits to mask 2891cb0ef41Sopenharmony_ci * @returns {String} the first n bits of the address as a string 2901cb0ef41Sopenharmony_ci */ 2911cb0ef41Sopenharmony_ci mask(mask = this.subnetMask) { 2921cb0ef41Sopenharmony_ci return this.getBitsBase2(0, mask); 2931cb0ef41Sopenharmony_ci } 2941cb0ef41Sopenharmony_ci /** 2951cb0ef41Sopenharmony_ci * Return the number of possible subnets of a given size in the address 2961cb0ef41Sopenharmony_ci * @memberof Address6 2971cb0ef41Sopenharmony_ci * @instance 2981cb0ef41Sopenharmony_ci * @param {number} [size=128] - the subnet size 2991cb0ef41Sopenharmony_ci * @returns {String} 3001cb0ef41Sopenharmony_ci */ 3011cb0ef41Sopenharmony_ci // TODO: probably useful to have a numeric version of this too 3021cb0ef41Sopenharmony_ci possibleSubnets(subnetSize = 128) { 3031cb0ef41Sopenharmony_ci const availableBits = constants6.BITS - this.subnetMask; 3041cb0ef41Sopenharmony_ci const subnetBits = Math.abs(subnetSize - constants6.BITS); 3051cb0ef41Sopenharmony_ci const subnetPowers = availableBits - subnetBits; 3061cb0ef41Sopenharmony_ci if (subnetPowers < 0) { 3071cb0ef41Sopenharmony_ci return '0'; 3081cb0ef41Sopenharmony_ci } 3091cb0ef41Sopenharmony_ci return addCommas(new jsbn_1.BigInteger('2', 10).pow(subnetPowers).toString(10)); 3101cb0ef41Sopenharmony_ci } 3111cb0ef41Sopenharmony_ci /** 3121cb0ef41Sopenharmony_ci * Helper function getting start address. 3131cb0ef41Sopenharmony_ci * @memberof Address6 3141cb0ef41Sopenharmony_ci * @instance 3151cb0ef41Sopenharmony_ci * @returns {BigInteger} 3161cb0ef41Sopenharmony_ci */ 3171cb0ef41Sopenharmony_ci _startAddress() { 3181cb0ef41Sopenharmony_ci return new jsbn_1.BigInteger(this.mask() + '0'.repeat(constants6.BITS - this.subnetMask), 2); 3191cb0ef41Sopenharmony_ci } 3201cb0ef41Sopenharmony_ci /** 3211cb0ef41Sopenharmony_ci * The first address in the range given by this address' subnet 3221cb0ef41Sopenharmony_ci * Often referred to as the Network Address. 3231cb0ef41Sopenharmony_ci * @memberof Address6 3241cb0ef41Sopenharmony_ci * @instance 3251cb0ef41Sopenharmony_ci * @returns {Address6} 3261cb0ef41Sopenharmony_ci */ 3271cb0ef41Sopenharmony_ci startAddress() { 3281cb0ef41Sopenharmony_ci return Address6.fromBigInteger(this._startAddress()); 3291cb0ef41Sopenharmony_ci } 3301cb0ef41Sopenharmony_ci /** 3311cb0ef41Sopenharmony_ci * The first host address in the range given by this address's subnet ie 3321cb0ef41Sopenharmony_ci * the first address after the Network Address 3331cb0ef41Sopenharmony_ci * @memberof Address6 3341cb0ef41Sopenharmony_ci * @instance 3351cb0ef41Sopenharmony_ci * @returns {Address6} 3361cb0ef41Sopenharmony_ci */ 3371cb0ef41Sopenharmony_ci startAddressExclusive() { 3381cb0ef41Sopenharmony_ci const adjust = new jsbn_1.BigInteger('1'); 3391cb0ef41Sopenharmony_ci return Address6.fromBigInteger(this._startAddress().add(adjust)); 3401cb0ef41Sopenharmony_ci } 3411cb0ef41Sopenharmony_ci /** 3421cb0ef41Sopenharmony_ci * Helper function getting end address. 3431cb0ef41Sopenharmony_ci * @memberof Address6 3441cb0ef41Sopenharmony_ci * @instance 3451cb0ef41Sopenharmony_ci * @returns {BigInteger} 3461cb0ef41Sopenharmony_ci */ 3471cb0ef41Sopenharmony_ci _endAddress() { 3481cb0ef41Sopenharmony_ci return new jsbn_1.BigInteger(this.mask() + '1'.repeat(constants6.BITS - this.subnetMask), 2); 3491cb0ef41Sopenharmony_ci } 3501cb0ef41Sopenharmony_ci /** 3511cb0ef41Sopenharmony_ci * The last address in the range given by this address' subnet 3521cb0ef41Sopenharmony_ci * Often referred to as the Broadcast 3531cb0ef41Sopenharmony_ci * @memberof Address6 3541cb0ef41Sopenharmony_ci * @instance 3551cb0ef41Sopenharmony_ci * @returns {Address6} 3561cb0ef41Sopenharmony_ci */ 3571cb0ef41Sopenharmony_ci endAddress() { 3581cb0ef41Sopenharmony_ci return Address6.fromBigInteger(this._endAddress()); 3591cb0ef41Sopenharmony_ci } 3601cb0ef41Sopenharmony_ci /** 3611cb0ef41Sopenharmony_ci * The last host address in the range given by this address's subnet ie 3621cb0ef41Sopenharmony_ci * the last address prior to the Broadcast Address 3631cb0ef41Sopenharmony_ci * @memberof Address6 3641cb0ef41Sopenharmony_ci * @instance 3651cb0ef41Sopenharmony_ci * @returns {Address6} 3661cb0ef41Sopenharmony_ci */ 3671cb0ef41Sopenharmony_ci endAddressExclusive() { 3681cb0ef41Sopenharmony_ci const adjust = new jsbn_1.BigInteger('1'); 3691cb0ef41Sopenharmony_ci return Address6.fromBigInteger(this._endAddress().subtract(adjust)); 3701cb0ef41Sopenharmony_ci } 3711cb0ef41Sopenharmony_ci /** 3721cb0ef41Sopenharmony_ci * Return the scope of the address 3731cb0ef41Sopenharmony_ci * @memberof Address6 3741cb0ef41Sopenharmony_ci * @instance 3751cb0ef41Sopenharmony_ci * @returns {String} 3761cb0ef41Sopenharmony_ci */ 3771cb0ef41Sopenharmony_ci getScope() { 3781cb0ef41Sopenharmony_ci let scope = constants6.SCOPES[this.getBits(12, 16).intValue()]; 3791cb0ef41Sopenharmony_ci if (this.getType() === 'Global unicast' && scope !== 'Link local') { 3801cb0ef41Sopenharmony_ci scope = 'Global'; 3811cb0ef41Sopenharmony_ci } 3821cb0ef41Sopenharmony_ci return scope || 'Unknown'; 3831cb0ef41Sopenharmony_ci } 3841cb0ef41Sopenharmony_ci /** 3851cb0ef41Sopenharmony_ci * Return the type of the address 3861cb0ef41Sopenharmony_ci * @memberof Address6 3871cb0ef41Sopenharmony_ci * @instance 3881cb0ef41Sopenharmony_ci * @returns {String} 3891cb0ef41Sopenharmony_ci */ 3901cb0ef41Sopenharmony_ci getType() { 3911cb0ef41Sopenharmony_ci for (const subnet of Object.keys(constants6.TYPES)) { 3921cb0ef41Sopenharmony_ci if (this.isInSubnet(new Address6(subnet))) { 3931cb0ef41Sopenharmony_ci return constants6.TYPES[subnet]; 3941cb0ef41Sopenharmony_ci } 3951cb0ef41Sopenharmony_ci } 3961cb0ef41Sopenharmony_ci return 'Global unicast'; 3971cb0ef41Sopenharmony_ci } 3981cb0ef41Sopenharmony_ci /** 3991cb0ef41Sopenharmony_ci * Return the bits in the given range as a BigInteger 4001cb0ef41Sopenharmony_ci * @memberof Address6 4011cb0ef41Sopenharmony_ci * @instance 4021cb0ef41Sopenharmony_ci * @returns {BigInteger} 4031cb0ef41Sopenharmony_ci */ 4041cb0ef41Sopenharmony_ci getBits(start, end) { 4051cb0ef41Sopenharmony_ci return new jsbn_1.BigInteger(this.getBitsBase2(start, end), 2); 4061cb0ef41Sopenharmony_ci } 4071cb0ef41Sopenharmony_ci /** 4081cb0ef41Sopenharmony_ci * Return the bits in the given range as a base-2 string 4091cb0ef41Sopenharmony_ci * @memberof Address6 4101cb0ef41Sopenharmony_ci * @instance 4111cb0ef41Sopenharmony_ci * @returns {String} 4121cb0ef41Sopenharmony_ci */ 4131cb0ef41Sopenharmony_ci getBitsBase2(start, end) { 4141cb0ef41Sopenharmony_ci return this.binaryZeroPad().slice(start, end); 4151cb0ef41Sopenharmony_ci } 4161cb0ef41Sopenharmony_ci /** 4171cb0ef41Sopenharmony_ci * Return the bits in the given range as a base-16 string 4181cb0ef41Sopenharmony_ci * @memberof Address6 4191cb0ef41Sopenharmony_ci * @instance 4201cb0ef41Sopenharmony_ci * @returns {String} 4211cb0ef41Sopenharmony_ci */ 4221cb0ef41Sopenharmony_ci getBitsBase16(start, end) { 4231cb0ef41Sopenharmony_ci const length = end - start; 4241cb0ef41Sopenharmony_ci if (length % 4 !== 0) { 4251cb0ef41Sopenharmony_ci throw new Error('Length of bits to retrieve must be divisible by four'); 4261cb0ef41Sopenharmony_ci } 4271cb0ef41Sopenharmony_ci return this.getBits(start, end) 4281cb0ef41Sopenharmony_ci .toString(16) 4291cb0ef41Sopenharmony_ci .padStart(length / 4, '0'); 4301cb0ef41Sopenharmony_ci } 4311cb0ef41Sopenharmony_ci /** 4321cb0ef41Sopenharmony_ci * Return the bits that are set past the subnet mask length 4331cb0ef41Sopenharmony_ci * @memberof Address6 4341cb0ef41Sopenharmony_ci * @instance 4351cb0ef41Sopenharmony_ci * @returns {String} 4361cb0ef41Sopenharmony_ci */ 4371cb0ef41Sopenharmony_ci getBitsPastSubnet() { 4381cb0ef41Sopenharmony_ci return this.getBitsBase2(this.subnetMask, constants6.BITS); 4391cb0ef41Sopenharmony_ci } 4401cb0ef41Sopenharmony_ci /** 4411cb0ef41Sopenharmony_ci * Return the reversed ip6.arpa form of the address 4421cb0ef41Sopenharmony_ci * @memberof Address6 4431cb0ef41Sopenharmony_ci * @param {Object} options 4441cb0ef41Sopenharmony_ci * @param {boolean} options.omitSuffix - omit the "ip6.arpa" suffix 4451cb0ef41Sopenharmony_ci * @instance 4461cb0ef41Sopenharmony_ci * @returns {String} 4471cb0ef41Sopenharmony_ci */ 4481cb0ef41Sopenharmony_ci reverseForm(options) { 4491cb0ef41Sopenharmony_ci if (!options) { 4501cb0ef41Sopenharmony_ci options = {}; 4511cb0ef41Sopenharmony_ci } 4521cb0ef41Sopenharmony_ci const characters = Math.floor(this.subnetMask / 4); 4531cb0ef41Sopenharmony_ci const reversed = this.canonicalForm() 4541cb0ef41Sopenharmony_ci .replace(/:/g, '') 4551cb0ef41Sopenharmony_ci .split('') 4561cb0ef41Sopenharmony_ci .slice(0, characters) 4571cb0ef41Sopenharmony_ci .reverse() 4581cb0ef41Sopenharmony_ci .join('.'); 4591cb0ef41Sopenharmony_ci if (characters > 0) { 4601cb0ef41Sopenharmony_ci if (options.omitSuffix) { 4611cb0ef41Sopenharmony_ci return reversed; 4621cb0ef41Sopenharmony_ci } 4631cb0ef41Sopenharmony_ci return (0, sprintf_js_1.sprintf)('%s.ip6.arpa.', reversed); 4641cb0ef41Sopenharmony_ci } 4651cb0ef41Sopenharmony_ci if (options.omitSuffix) { 4661cb0ef41Sopenharmony_ci return ''; 4671cb0ef41Sopenharmony_ci } 4681cb0ef41Sopenharmony_ci return 'ip6.arpa.'; 4691cb0ef41Sopenharmony_ci } 4701cb0ef41Sopenharmony_ci /** 4711cb0ef41Sopenharmony_ci * Return the correct form of the address 4721cb0ef41Sopenharmony_ci * @memberof Address6 4731cb0ef41Sopenharmony_ci * @instance 4741cb0ef41Sopenharmony_ci * @returns {String} 4751cb0ef41Sopenharmony_ci */ 4761cb0ef41Sopenharmony_ci correctForm() { 4771cb0ef41Sopenharmony_ci let i; 4781cb0ef41Sopenharmony_ci let groups = []; 4791cb0ef41Sopenharmony_ci let zeroCounter = 0; 4801cb0ef41Sopenharmony_ci const zeroes = []; 4811cb0ef41Sopenharmony_ci for (i = 0; i < this.parsedAddress.length; i++) { 4821cb0ef41Sopenharmony_ci const value = parseInt(this.parsedAddress[i], 16); 4831cb0ef41Sopenharmony_ci if (value === 0) { 4841cb0ef41Sopenharmony_ci zeroCounter++; 4851cb0ef41Sopenharmony_ci } 4861cb0ef41Sopenharmony_ci if (value !== 0 && zeroCounter > 0) { 4871cb0ef41Sopenharmony_ci if (zeroCounter > 1) { 4881cb0ef41Sopenharmony_ci zeroes.push([i - zeroCounter, i - 1]); 4891cb0ef41Sopenharmony_ci } 4901cb0ef41Sopenharmony_ci zeroCounter = 0; 4911cb0ef41Sopenharmony_ci } 4921cb0ef41Sopenharmony_ci } 4931cb0ef41Sopenharmony_ci // Do we end with a string of zeroes? 4941cb0ef41Sopenharmony_ci if (zeroCounter > 1) { 4951cb0ef41Sopenharmony_ci zeroes.push([this.parsedAddress.length - zeroCounter, this.parsedAddress.length - 1]); 4961cb0ef41Sopenharmony_ci } 4971cb0ef41Sopenharmony_ci const zeroLengths = zeroes.map((n) => n[1] - n[0] + 1); 4981cb0ef41Sopenharmony_ci if (zeroes.length > 0) { 4991cb0ef41Sopenharmony_ci const index = zeroLengths.indexOf(Math.max(...zeroLengths)); 5001cb0ef41Sopenharmony_ci groups = compact(this.parsedAddress, zeroes[index]); 5011cb0ef41Sopenharmony_ci } 5021cb0ef41Sopenharmony_ci else { 5031cb0ef41Sopenharmony_ci groups = this.parsedAddress; 5041cb0ef41Sopenharmony_ci } 5051cb0ef41Sopenharmony_ci for (i = 0; i < groups.length; i++) { 5061cb0ef41Sopenharmony_ci if (groups[i] !== 'compact') { 5071cb0ef41Sopenharmony_ci groups[i] = parseInt(groups[i], 16).toString(16); 5081cb0ef41Sopenharmony_ci } 5091cb0ef41Sopenharmony_ci } 5101cb0ef41Sopenharmony_ci let correct = groups.join(':'); 5111cb0ef41Sopenharmony_ci correct = correct.replace(/^compact$/, '::'); 5121cb0ef41Sopenharmony_ci correct = correct.replace(/^compact|compact$/, ':'); 5131cb0ef41Sopenharmony_ci correct = correct.replace(/compact/, ''); 5141cb0ef41Sopenharmony_ci return correct; 5151cb0ef41Sopenharmony_ci } 5161cb0ef41Sopenharmony_ci /** 5171cb0ef41Sopenharmony_ci * Return a zero-padded base-2 string representation of the address 5181cb0ef41Sopenharmony_ci * @memberof Address6 5191cb0ef41Sopenharmony_ci * @instance 5201cb0ef41Sopenharmony_ci * @returns {String} 5211cb0ef41Sopenharmony_ci * @example 5221cb0ef41Sopenharmony_ci * var address = new Address6('2001:4860:4001:803::1011'); 5231cb0ef41Sopenharmony_ci * address.binaryZeroPad(); 5241cb0ef41Sopenharmony_ci * // '0010000000000001010010000110000001000000000000010000100000000011 5251cb0ef41Sopenharmony_ci * // 0000000000000000000000000000000000000000000000000001000000010001' 5261cb0ef41Sopenharmony_ci */ 5271cb0ef41Sopenharmony_ci binaryZeroPad() { 5281cb0ef41Sopenharmony_ci return this.bigInteger().toString(2).padStart(constants6.BITS, '0'); 5291cb0ef41Sopenharmony_ci } 5301cb0ef41Sopenharmony_ci // TODO: Improve the semantics of this helper function 5311cb0ef41Sopenharmony_ci parse4in6(address) { 5321cb0ef41Sopenharmony_ci const groups = address.split(':'); 5331cb0ef41Sopenharmony_ci const lastGroup = groups.slice(-1)[0]; 5341cb0ef41Sopenharmony_ci const address4 = lastGroup.match(constants4.RE_ADDRESS); 5351cb0ef41Sopenharmony_ci if (address4) { 5361cb0ef41Sopenharmony_ci this.parsedAddress4 = address4[0]; 5371cb0ef41Sopenharmony_ci this.address4 = new ipv4_1.Address4(this.parsedAddress4); 5381cb0ef41Sopenharmony_ci for (let i = 0; i < this.address4.groups; i++) { 5391cb0ef41Sopenharmony_ci if (/^0[0-9]+/.test(this.address4.parsedAddress[i])) { 5401cb0ef41Sopenharmony_ci throw new address_error_1.AddressError("IPv4 addresses can't have leading zeroes.", address.replace(constants4.RE_ADDRESS, this.address4.parsedAddress.map(spanLeadingZeroes4).join('.'))); 5411cb0ef41Sopenharmony_ci } 5421cb0ef41Sopenharmony_ci } 5431cb0ef41Sopenharmony_ci this.v4 = true; 5441cb0ef41Sopenharmony_ci groups[groups.length - 1] = this.address4.toGroup6(); 5451cb0ef41Sopenharmony_ci address = groups.join(':'); 5461cb0ef41Sopenharmony_ci } 5471cb0ef41Sopenharmony_ci return address; 5481cb0ef41Sopenharmony_ci } 5491cb0ef41Sopenharmony_ci // TODO: Make private? 5501cb0ef41Sopenharmony_ci parse(address) { 5511cb0ef41Sopenharmony_ci address = this.parse4in6(address); 5521cb0ef41Sopenharmony_ci const badCharacters = address.match(constants6.RE_BAD_CHARACTERS); 5531cb0ef41Sopenharmony_ci if (badCharacters) { 5541cb0ef41Sopenharmony_ci throw new address_error_1.AddressError((0, sprintf_js_1.sprintf)('Bad character%s detected in address: %s', badCharacters.length > 1 ? 's' : '', badCharacters.join('')), address.replace(constants6.RE_BAD_CHARACTERS, '<span class="parse-error">$1</span>')); 5551cb0ef41Sopenharmony_ci } 5561cb0ef41Sopenharmony_ci const badAddress = address.match(constants6.RE_BAD_ADDRESS); 5571cb0ef41Sopenharmony_ci if (badAddress) { 5581cb0ef41Sopenharmony_ci throw new address_error_1.AddressError((0, sprintf_js_1.sprintf)('Address failed regex: %s', badAddress.join('')), address.replace(constants6.RE_BAD_ADDRESS, '<span class="parse-error">$1</span>')); 5591cb0ef41Sopenharmony_ci } 5601cb0ef41Sopenharmony_ci let groups = []; 5611cb0ef41Sopenharmony_ci const halves = address.split('::'); 5621cb0ef41Sopenharmony_ci if (halves.length === 2) { 5631cb0ef41Sopenharmony_ci let first = halves[0].split(':'); 5641cb0ef41Sopenharmony_ci let last = halves[1].split(':'); 5651cb0ef41Sopenharmony_ci if (first.length === 1 && first[0] === '') { 5661cb0ef41Sopenharmony_ci first = []; 5671cb0ef41Sopenharmony_ci } 5681cb0ef41Sopenharmony_ci if (last.length === 1 && last[0] === '') { 5691cb0ef41Sopenharmony_ci last = []; 5701cb0ef41Sopenharmony_ci } 5711cb0ef41Sopenharmony_ci const remaining = this.groups - (first.length + last.length); 5721cb0ef41Sopenharmony_ci if (!remaining) { 5731cb0ef41Sopenharmony_ci throw new address_error_1.AddressError('Error parsing groups'); 5741cb0ef41Sopenharmony_ci } 5751cb0ef41Sopenharmony_ci this.elidedGroups = remaining; 5761cb0ef41Sopenharmony_ci this.elisionBegin = first.length; 5771cb0ef41Sopenharmony_ci this.elisionEnd = first.length + this.elidedGroups; 5781cb0ef41Sopenharmony_ci groups = groups.concat(first); 5791cb0ef41Sopenharmony_ci for (let i = 0; i < remaining; i++) { 5801cb0ef41Sopenharmony_ci groups.push('0'); 5811cb0ef41Sopenharmony_ci } 5821cb0ef41Sopenharmony_ci groups = groups.concat(last); 5831cb0ef41Sopenharmony_ci } 5841cb0ef41Sopenharmony_ci else if (halves.length === 1) { 5851cb0ef41Sopenharmony_ci groups = address.split(':'); 5861cb0ef41Sopenharmony_ci this.elidedGroups = 0; 5871cb0ef41Sopenharmony_ci } 5881cb0ef41Sopenharmony_ci else { 5891cb0ef41Sopenharmony_ci throw new address_error_1.AddressError('Too many :: groups found'); 5901cb0ef41Sopenharmony_ci } 5911cb0ef41Sopenharmony_ci groups = groups.map((group) => (0, sprintf_js_1.sprintf)('%x', parseInt(group, 16))); 5921cb0ef41Sopenharmony_ci if (groups.length !== this.groups) { 5931cb0ef41Sopenharmony_ci throw new address_error_1.AddressError('Incorrect number of groups found'); 5941cb0ef41Sopenharmony_ci } 5951cb0ef41Sopenharmony_ci return groups; 5961cb0ef41Sopenharmony_ci } 5971cb0ef41Sopenharmony_ci /** 5981cb0ef41Sopenharmony_ci * Return the canonical form of the address 5991cb0ef41Sopenharmony_ci * @memberof Address6 6001cb0ef41Sopenharmony_ci * @instance 6011cb0ef41Sopenharmony_ci * @returns {String} 6021cb0ef41Sopenharmony_ci */ 6031cb0ef41Sopenharmony_ci canonicalForm() { 6041cb0ef41Sopenharmony_ci return this.parsedAddress.map(paddedHex).join(':'); 6051cb0ef41Sopenharmony_ci } 6061cb0ef41Sopenharmony_ci /** 6071cb0ef41Sopenharmony_ci * Return the decimal form of the address 6081cb0ef41Sopenharmony_ci * @memberof Address6 6091cb0ef41Sopenharmony_ci * @instance 6101cb0ef41Sopenharmony_ci * @returns {String} 6111cb0ef41Sopenharmony_ci */ 6121cb0ef41Sopenharmony_ci decimal() { 6131cb0ef41Sopenharmony_ci return this.parsedAddress.map((n) => (0, sprintf_js_1.sprintf)('%05d', parseInt(n, 16))).join(':'); 6141cb0ef41Sopenharmony_ci } 6151cb0ef41Sopenharmony_ci /** 6161cb0ef41Sopenharmony_ci * Return the address as a BigInteger 6171cb0ef41Sopenharmony_ci * @memberof Address6 6181cb0ef41Sopenharmony_ci * @instance 6191cb0ef41Sopenharmony_ci * @returns {BigInteger} 6201cb0ef41Sopenharmony_ci */ 6211cb0ef41Sopenharmony_ci bigInteger() { 6221cb0ef41Sopenharmony_ci return new jsbn_1.BigInteger(this.parsedAddress.map(paddedHex).join(''), 16); 6231cb0ef41Sopenharmony_ci } 6241cb0ef41Sopenharmony_ci /** 6251cb0ef41Sopenharmony_ci * Return the last two groups of this address as an IPv4 address string 6261cb0ef41Sopenharmony_ci * @memberof Address6 6271cb0ef41Sopenharmony_ci * @instance 6281cb0ef41Sopenharmony_ci * @returns {Address4} 6291cb0ef41Sopenharmony_ci * @example 6301cb0ef41Sopenharmony_ci * var address = new Address6('2001:4860:4001::1825:bf11'); 6311cb0ef41Sopenharmony_ci * address.to4().correctForm(); // '24.37.191.17' 6321cb0ef41Sopenharmony_ci */ 6331cb0ef41Sopenharmony_ci to4() { 6341cb0ef41Sopenharmony_ci const binary = this.binaryZeroPad().split(''); 6351cb0ef41Sopenharmony_ci return ipv4_1.Address4.fromHex(new jsbn_1.BigInteger(binary.slice(96, 128).join(''), 2).toString(16)); 6361cb0ef41Sopenharmony_ci } 6371cb0ef41Sopenharmony_ci /** 6381cb0ef41Sopenharmony_ci * Return the v4-in-v6 form of the address 6391cb0ef41Sopenharmony_ci * @memberof Address6 6401cb0ef41Sopenharmony_ci * @instance 6411cb0ef41Sopenharmony_ci * @returns {String} 6421cb0ef41Sopenharmony_ci */ 6431cb0ef41Sopenharmony_ci to4in6() { 6441cb0ef41Sopenharmony_ci const address4 = this.to4(); 6451cb0ef41Sopenharmony_ci const address6 = new Address6(this.parsedAddress.slice(0, 6).join(':'), 6); 6461cb0ef41Sopenharmony_ci const correct = address6.correctForm(); 6471cb0ef41Sopenharmony_ci let infix = ''; 6481cb0ef41Sopenharmony_ci if (!/:$/.test(correct)) { 6491cb0ef41Sopenharmony_ci infix = ':'; 6501cb0ef41Sopenharmony_ci } 6511cb0ef41Sopenharmony_ci return correct + infix + address4.address; 6521cb0ef41Sopenharmony_ci } 6531cb0ef41Sopenharmony_ci /** 6541cb0ef41Sopenharmony_ci * Return an object containing the Teredo properties of the address 6551cb0ef41Sopenharmony_ci * @memberof Address6 6561cb0ef41Sopenharmony_ci * @instance 6571cb0ef41Sopenharmony_ci * @returns {Object} 6581cb0ef41Sopenharmony_ci */ 6591cb0ef41Sopenharmony_ci inspectTeredo() { 6601cb0ef41Sopenharmony_ci /* 6611cb0ef41Sopenharmony_ci - Bits 0 to 31 are set to the Teredo prefix (normally 2001:0000::/32). 6621cb0ef41Sopenharmony_ci - Bits 32 to 63 embed the primary IPv4 address of the Teredo server that 6631cb0ef41Sopenharmony_ci is used. 6641cb0ef41Sopenharmony_ci - Bits 64 to 79 can be used to define some flags. Currently only the 6651cb0ef41Sopenharmony_ci higher order bit is used; it is set to 1 if the Teredo client is 6661cb0ef41Sopenharmony_ci located behind a cone NAT, 0 otherwise. For Microsoft's Windows Vista 6671cb0ef41Sopenharmony_ci and Windows Server 2008 implementations, more bits are used. In those 6681cb0ef41Sopenharmony_ci implementations, the format for these 16 bits is "CRAAAAUG AAAAAAAA", 6691cb0ef41Sopenharmony_ci where "C" remains the "Cone" flag. The "R" bit is reserved for future 6701cb0ef41Sopenharmony_ci use. The "U" bit is for the Universal/Local flag (set to 0). The "G" bit 6711cb0ef41Sopenharmony_ci is Individual/Group flag (set to 0). The A bits are set to a 12-bit 6721cb0ef41Sopenharmony_ci randomly generated number chosen by the Teredo client to introduce 6731cb0ef41Sopenharmony_ci additional protection for the Teredo node against IPv6-based scanning 6741cb0ef41Sopenharmony_ci attacks. 6751cb0ef41Sopenharmony_ci - Bits 80 to 95 contains the obfuscated UDP port number. This is the 6761cb0ef41Sopenharmony_ci port number that is mapped by the NAT to the Teredo client with all 6771cb0ef41Sopenharmony_ci bits inverted. 6781cb0ef41Sopenharmony_ci - Bits 96 to 127 contains the obfuscated IPv4 address. This is the 6791cb0ef41Sopenharmony_ci public IPv4 address of the NAT with all bits inverted. 6801cb0ef41Sopenharmony_ci */ 6811cb0ef41Sopenharmony_ci const prefix = this.getBitsBase16(0, 32); 6821cb0ef41Sopenharmony_ci const udpPort = this.getBits(80, 96).xor(new jsbn_1.BigInteger('ffff', 16)).toString(); 6831cb0ef41Sopenharmony_ci const server4 = ipv4_1.Address4.fromHex(this.getBitsBase16(32, 64)); 6841cb0ef41Sopenharmony_ci const client4 = ipv4_1.Address4.fromHex(this.getBits(96, 128).xor(new jsbn_1.BigInteger('ffffffff', 16)).toString(16)); 6851cb0ef41Sopenharmony_ci const flags = this.getBits(64, 80); 6861cb0ef41Sopenharmony_ci const flagsBase2 = this.getBitsBase2(64, 80); 6871cb0ef41Sopenharmony_ci const coneNat = flags.testBit(15); 6881cb0ef41Sopenharmony_ci const reserved = flags.testBit(14); 6891cb0ef41Sopenharmony_ci const groupIndividual = flags.testBit(8); 6901cb0ef41Sopenharmony_ci const universalLocal = flags.testBit(9); 6911cb0ef41Sopenharmony_ci const nonce = new jsbn_1.BigInteger(flagsBase2.slice(2, 6) + flagsBase2.slice(8, 16), 2).toString(10); 6921cb0ef41Sopenharmony_ci return { 6931cb0ef41Sopenharmony_ci prefix: (0, sprintf_js_1.sprintf)('%s:%s', prefix.slice(0, 4), prefix.slice(4, 8)), 6941cb0ef41Sopenharmony_ci server4: server4.address, 6951cb0ef41Sopenharmony_ci client4: client4.address, 6961cb0ef41Sopenharmony_ci flags: flagsBase2, 6971cb0ef41Sopenharmony_ci coneNat, 6981cb0ef41Sopenharmony_ci microsoft: { 6991cb0ef41Sopenharmony_ci reserved, 7001cb0ef41Sopenharmony_ci universalLocal, 7011cb0ef41Sopenharmony_ci groupIndividual, 7021cb0ef41Sopenharmony_ci nonce, 7031cb0ef41Sopenharmony_ci }, 7041cb0ef41Sopenharmony_ci udpPort, 7051cb0ef41Sopenharmony_ci }; 7061cb0ef41Sopenharmony_ci } 7071cb0ef41Sopenharmony_ci /** 7081cb0ef41Sopenharmony_ci * Return an object containing the 6to4 properties of the address 7091cb0ef41Sopenharmony_ci * @memberof Address6 7101cb0ef41Sopenharmony_ci * @instance 7111cb0ef41Sopenharmony_ci * @returns {Object} 7121cb0ef41Sopenharmony_ci */ 7131cb0ef41Sopenharmony_ci inspect6to4() { 7141cb0ef41Sopenharmony_ci /* 7151cb0ef41Sopenharmony_ci - Bits 0 to 15 are set to the 6to4 prefix (2002::/16). 7161cb0ef41Sopenharmony_ci - Bits 16 to 48 embed the IPv4 address of the 6to4 gateway that is used. 7171cb0ef41Sopenharmony_ci */ 7181cb0ef41Sopenharmony_ci const prefix = this.getBitsBase16(0, 16); 7191cb0ef41Sopenharmony_ci const gateway = ipv4_1.Address4.fromHex(this.getBitsBase16(16, 48)); 7201cb0ef41Sopenharmony_ci return { 7211cb0ef41Sopenharmony_ci prefix: (0, sprintf_js_1.sprintf)('%s', prefix.slice(0, 4)), 7221cb0ef41Sopenharmony_ci gateway: gateway.address, 7231cb0ef41Sopenharmony_ci }; 7241cb0ef41Sopenharmony_ci } 7251cb0ef41Sopenharmony_ci /** 7261cb0ef41Sopenharmony_ci * Return a v6 6to4 address from a v6 v4inv6 address 7271cb0ef41Sopenharmony_ci * @memberof Address6 7281cb0ef41Sopenharmony_ci * @instance 7291cb0ef41Sopenharmony_ci * @returns {Address6} 7301cb0ef41Sopenharmony_ci */ 7311cb0ef41Sopenharmony_ci to6to4() { 7321cb0ef41Sopenharmony_ci if (!this.is4()) { 7331cb0ef41Sopenharmony_ci return null; 7341cb0ef41Sopenharmony_ci } 7351cb0ef41Sopenharmony_ci const addr6to4 = [ 7361cb0ef41Sopenharmony_ci '2002', 7371cb0ef41Sopenharmony_ci this.getBitsBase16(96, 112), 7381cb0ef41Sopenharmony_ci this.getBitsBase16(112, 128), 7391cb0ef41Sopenharmony_ci '', 7401cb0ef41Sopenharmony_ci '/16', 7411cb0ef41Sopenharmony_ci ].join(':'); 7421cb0ef41Sopenharmony_ci return new Address6(addr6to4); 7431cb0ef41Sopenharmony_ci } 7441cb0ef41Sopenharmony_ci /** 7451cb0ef41Sopenharmony_ci * Return a byte array 7461cb0ef41Sopenharmony_ci * @memberof Address6 7471cb0ef41Sopenharmony_ci * @instance 7481cb0ef41Sopenharmony_ci * @returns {Array} 7491cb0ef41Sopenharmony_ci */ 7501cb0ef41Sopenharmony_ci toByteArray() { 7511cb0ef41Sopenharmony_ci const byteArray = this.bigInteger().toByteArray(); 7521cb0ef41Sopenharmony_ci // work around issue where `toByteArray` returns a leading 0 element 7531cb0ef41Sopenharmony_ci if (byteArray.length === 17 && byteArray[0] === 0) { 7541cb0ef41Sopenharmony_ci return byteArray.slice(1); 7551cb0ef41Sopenharmony_ci } 7561cb0ef41Sopenharmony_ci return byteArray; 7571cb0ef41Sopenharmony_ci } 7581cb0ef41Sopenharmony_ci /** 7591cb0ef41Sopenharmony_ci * Return an unsigned byte array 7601cb0ef41Sopenharmony_ci * @memberof Address6 7611cb0ef41Sopenharmony_ci * @instance 7621cb0ef41Sopenharmony_ci * @returns {Array} 7631cb0ef41Sopenharmony_ci */ 7641cb0ef41Sopenharmony_ci toUnsignedByteArray() { 7651cb0ef41Sopenharmony_ci return this.toByteArray().map(unsignByte); 7661cb0ef41Sopenharmony_ci } 7671cb0ef41Sopenharmony_ci /** 7681cb0ef41Sopenharmony_ci * Convert a byte array to an Address6 object 7691cb0ef41Sopenharmony_ci * @memberof Address6 7701cb0ef41Sopenharmony_ci * @static 7711cb0ef41Sopenharmony_ci * @returns {Address6} 7721cb0ef41Sopenharmony_ci */ 7731cb0ef41Sopenharmony_ci static fromByteArray(bytes) { 7741cb0ef41Sopenharmony_ci return this.fromUnsignedByteArray(bytes.map(unsignByte)); 7751cb0ef41Sopenharmony_ci } 7761cb0ef41Sopenharmony_ci /** 7771cb0ef41Sopenharmony_ci * Convert an unsigned byte array to an Address6 object 7781cb0ef41Sopenharmony_ci * @memberof Address6 7791cb0ef41Sopenharmony_ci * @static 7801cb0ef41Sopenharmony_ci * @returns {Address6} 7811cb0ef41Sopenharmony_ci */ 7821cb0ef41Sopenharmony_ci static fromUnsignedByteArray(bytes) { 7831cb0ef41Sopenharmony_ci const BYTE_MAX = new jsbn_1.BigInteger('256', 10); 7841cb0ef41Sopenharmony_ci let result = new jsbn_1.BigInteger('0', 10); 7851cb0ef41Sopenharmony_ci let multiplier = new jsbn_1.BigInteger('1', 10); 7861cb0ef41Sopenharmony_ci for (let i = bytes.length - 1; i >= 0; i--) { 7871cb0ef41Sopenharmony_ci result = result.add(multiplier.multiply(new jsbn_1.BigInteger(bytes[i].toString(10), 10))); 7881cb0ef41Sopenharmony_ci multiplier = multiplier.multiply(BYTE_MAX); 7891cb0ef41Sopenharmony_ci } 7901cb0ef41Sopenharmony_ci return Address6.fromBigInteger(result); 7911cb0ef41Sopenharmony_ci } 7921cb0ef41Sopenharmony_ci /** 7931cb0ef41Sopenharmony_ci * Returns true if the address is in the canonical form, false otherwise 7941cb0ef41Sopenharmony_ci * @memberof Address6 7951cb0ef41Sopenharmony_ci * @instance 7961cb0ef41Sopenharmony_ci * @returns {boolean} 7971cb0ef41Sopenharmony_ci */ 7981cb0ef41Sopenharmony_ci isCanonical() { 7991cb0ef41Sopenharmony_ci return this.addressMinusSuffix === this.canonicalForm(); 8001cb0ef41Sopenharmony_ci } 8011cb0ef41Sopenharmony_ci /** 8021cb0ef41Sopenharmony_ci * Returns true if the address is a link local address, false otherwise 8031cb0ef41Sopenharmony_ci * @memberof Address6 8041cb0ef41Sopenharmony_ci * @instance 8051cb0ef41Sopenharmony_ci * @returns {boolean} 8061cb0ef41Sopenharmony_ci */ 8071cb0ef41Sopenharmony_ci isLinkLocal() { 8081cb0ef41Sopenharmony_ci // Zeroes are required, i.e. we can't check isInSubnet with 'fe80::/10' 8091cb0ef41Sopenharmony_ci if (this.getBitsBase2(0, 64) === 8101cb0ef41Sopenharmony_ci '1111111010000000000000000000000000000000000000000000000000000000') { 8111cb0ef41Sopenharmony_ci return true; 8121cb0ef41Sopenharmony_ci } 8131cb0ef41Sopenharmony_ci return false; 8141cb0ef41Sopenharmony_ci } 8151cb0ef41Sopenharmony_ci /** 8161cb0ef41Sopenharmony_ci * Returns true if the address is a multicast address, false otherwise 8171cb0ef41Sopenharmony_ci * @memberof Address6 8181cb0ef41Sopenharmony_ci * @instance 8191cb0ef41Sopenharmony_ci * @returns {boolean} 8201cb0ef41Sopenharmony_ci */ 8211cb0ef41Sopenharmony_ci isMulticast() { 8221cb0ef41Sopenharmony_ci return this.getType() === 'Multicast'; 8231cb0ef41Sopenharmony_ci } 8241cb0ef41Sopenharmony_ci /** 8251cb0ef41Sopenharmony_ci * Returns true if the address is a v4-in-v6 address, false otherwise 8261cb0ef41Sopenharmony_ci * @memberof Address6 8271cb0ef41Sopenharmony_ci * @instance 8281cb0ef41Sopenharmony_ci * @returns {boolean} 8291cb0ef41Sopenharmony_ci */ 8301cb0ef41Sopenharmony_ci is4() { 8311cb0ef41Sopenharmony_ci return this.v4; 8321cb0ef41Sopenharmony_ci } 8331cb0ef41Sopenharmony_ci /** 8341cb0ef41Sopenharmony_ci * Returns true if the address is a Teredo address, false otherwise 8351cb0ef41Sopenharmony_ci * @memberof Address6 8361cb0ef41Sopenharmony_ci * @instance 8371cb0ef41Sopenharmony_ci * @returns {boolean} 8381cb0ef41Sopenharmony_ci */ 8391cb0ef41Sopenharmony_ci isTeredo() { 8401cb0ef41Sopenharmony_ci return this.isInSubnet(new Address6('2001::/32')); 8411cb0ef41Sopenharmony_ci } 8421cb0ef41Sopenharmony_ci /** 8431cb0ef41Sopenharmony_ci * Returns true if the address is a 6to4 address, false otherwise 8441cb0ef41Sopenharmony_ci * @memberof Address6 8451cb0ef41Sopenharmony_ci * @instance 8461cb0ef41Sopenharmony_ci * @returns {boolean} 8471cb0ef41Sopenharmony_ci */ 8481cb0ef41Sopenharmony_ci is6to4() { 8491cb0ef41Sopenharmony_ci return this.isInSubnet(new Address6('2002::/16')); 8501cb0ef41Sopenharmony_ci } 8511cb0ef41Sopenharmony_ci /** 8521cb0ef41Sopenharmony_ci * Returns true if the address is a loopback address, false otherwise 8531cb0ef41Sopenharmony_ci * @memberof Address6 8541cb0ef41Sopenharmony_ci * @instance 8551cb0ef41Sopenharmony_ci * @returns {boolean} 8561cb0ef41Sopenharmony_ci */ 8571cb0ef41Sopenharmony_ci isLoopback() { 8581cb0ef41Sopenharmony_ci return this.getType() === 'Loopback'; 8591cb0ef41Sopenharmony_ci } 8601cb0ef41Sopenharmony_ci // #endregion 8611cb0ef41Sopenharmony_ci // #region HTML 8621cb0ef41Sopenharmony_ci /** 8631cb0ef41Sopenharmony_ci * @returns {String} the address in link form with a default port of 80 8641cb0ef41Sopenharmony_ci */ 8651cb0ef41Sopenharmony_ci href(optionalPort) { 8661cb0ef41Sopenharmony_ci if (optionalPort === undefined) { 8671cb0ef41Sopenharmony_ci optionalPort = ''; 8681cb0ef41Sopenharmony_ci } 8691cb0ef41Sopenharmony_ci else { 8701cb0ef41Sopenharmony_ci optionalPort = (0, sprintf_js_1.sprintf)(':%s', optionalPort); 8711cb0ef41Sopenharmony_ci } 8721cb0ef41Sopenharmony_ci return (0, sprintf_js_1.sprintf)('http://[%s]%s/', this.correctForm(), optionalPort); 8731cb0ef41Sopenharmony_ci } 8741cb0ef41Sopenharmony_ci /** 8751cb0ef41Sopenharmony_ci * @returns {String} a link suitable for conveying the address via a URL hash 8761cb0ef41Sopenharmony_ci */ 8771cb0ef41Sopenharmony_ci link(options) { 8781cb0ef41Sopenharmony_ci if (!options) { 8791cb0ef41Sopenharmony_ci options = {}; 8801cb0ef41Sopenharmony_ci } 8811cb0ef41Sopenharmony_ci if (options.className === undefined) { 8821cb0ef41Sopenharmony_ci options.className = ''; 8831cb0ef41Sopenharmony_ci } 8841cb0ef41Sopenharmony_ci if (options.prefix === undefined) { 8851cb0ef41Sopenharmony_ci options.prefix = '/#address='; 8861cb0ef41Sopenharmony_ci } 8871cb0ef41Sopenharmony_ci if (options.v4 === undefined) { 8881cb0ef41Sopenharmony_ci options.v4 = false; 8891cb0ef41Sopenharmony_ci } 8901cb0ef41Sopenharmony_ci let formFunction = this.correctForm; 8911cb0ef41Sopenharmony_ci if (options.v4) { 8921cb0ef41Sopenharmony_ci formFunction = this.to4in6; 8931cb0ef41Sopenharmony_ci } 8941cb0ef41Sopenharmony_ci if (options.className) { 8951cb0ef41Sopenharmony_ci return (0, sprintf_js_1.sprintf)('<a href="%1$s%2$s" class="%3$s">%2$s</a>', options.prefix, formFunction.call(this), options.className); 8961cb0ef41Sopenharmony_ci } 8971cb0ef41Sopenharmony_ci return (0, sprintf_js_1.sprintf)('<a href="%1$s%2$s">%2$s</a>', options.prefix, formFunction.call(this)); 8981cb0ef41Sopenharmony_ci } 8991cb0ef41Sopenharmony_ci /** 9001cb0ef41Sopenharmony_ci * Groups an address 9011cb0ef41Sopenharmony_ci * @returns {String} 9021cb0ef41Sopenharmony_ci */ 9031cb0ef41Sopenharmony_ci group() { 9041cb0ef41Sopenharmony_ci if (this.elidedGroups === 0) { 9051cb0ef41Sopenharmony_ci // The simple case 9061cb0ef41Sopenharmony_ci return helpers.simpleGroup(this.address).join(':'); 9071cb0ef41Sopenharmony_ci } 9081cb0ef41Sopenharmony_ci assert(typeof this.elidedGroups === 'number'); 9091cb0ef41Sopenharmony_ci assert(typeof this.elisionBegin === 'number'); 9101cb0ef41Sopenharmony_ci // The elided case 9111cb0ef41Sopenharmony_ci const output = []; 9121cb0ef41Sopenharmony_ci const [left, right] = this.address.split('::'); 9131cb0ef41Sopenharmony_ci if (left.length) { 9141cb0ef41Sopenharmony_ci output.push(...helpers.simpleGroup(left)); 9151cb0ef41Sopenharmony_ci } 9161cb0ef41Sopenharmony_ci else { 9171cb0ef41Sopenharmony_ci output.push(''); 9181cb0ef41Sopenharmony_ci } 9191cb0ef41Sopenharmony_ci const classes = ['hover-group']; 9201cb0ef41Sopenharmony_ci for (let i = this.elisionBegin; i < this.elisionBegin + this.elidedGroups; i++) { 9211cb0ef41Sopenharmony_ci classes.push((0, sprintf_js_1.sprintf)('group-%d', i)); 9221cb0ef41Sopenharmony_ci } 9231cb0ef41Sopenharmony_ci output.push((0, sprintf_js_1.sprintf)('<span class="%s"></span>', classes.join(' '))); 9241cb0ef41Sopenharmony_ci if (right.length) { 9251cb0ef41Sopenharmony_ci output.push(...helpers.simpleGroup(right, this.elisionEnd)); 9261cb0ef41Sopenharmony_ci } 9271cb0ef41Sopenharmony_ci else { 9281cb0ef41Sopenharmony_ci output.push(''); 9291cb0ef41Sopenharmony_ci } 9301cb0ef41Sopenharmony_ci if (this.is4()) { 9311cb0ef41Sopenharmony_ci assert(this.address4 instanceof ipv4_1.Address4); 9321cb0ef41Sopenharmony_ci output.pop(); 9331cb0ef41Sopenharmony_ci output.push(this.address4.groupForV6()); 9341cb0ef41Sopenharmony_ci } 9351cb0ef41Sopenharmony_ci return output.join(':'); 9361cb0ef41Sopenharmony_ci } 9371cb0ef41Sopenharmony_ci // #endregion 9381cb0ef41Sopenharmony_ci // #region Regular expressions 9391cb0ef41Sopenharmony_ci /** 9401cb0ef41Sopenharmony_ci * Generate a regular expression string that can be used to find or validate 9411cb0ef41Sopenharmony_ci * all variations of this address 9421cb0ef41Sopenharmony_ci * @memberof Address6 9431cb0ef41Sopenharmony_ci * @instance 9441cb0ef41Sopenharmony_ci * @param {boolean} substringSearch 9451cb0ef41Sopenharmony_ci * @returns {string} 9461cb0ef41Sopenharmony_ci */ 9471cb0ef41Sopenharmony_ci regularExpressionString(substringSearch = false) { 9481cb0ef41Sopenharmony_ci let output = []; 9491cb0ef41Sopenharmony_ci // TODO: revisit why this is necessary 9501cb0ef41Sopenharmony_ci const address6 = new Address6(this.correctForm()); 9511cb0ef41Sopenharmony_ci if (address6.elidedGroups === 0) { 9521cb0ef41Sopenharmony_ci // The simple case 9531cb0ef41Sopenharmony_ci output.push((0, regular_expressions_1.simpleRegularExpression)(address6.parsedAddress)); 9541cb0ef41Sopenharmony_ci } 9551cb0ef41Sopenharmony_ci else if (address6.elidedGroups === constants6.GROUPS) { 9561cb0ef41Sopenharmony_ci // A completely elided address 9571cb0ef41Sopenharmony_ci output.push((0, regular_expressions_1.possibleElisions)(constants6.GROUPS)); 9581cb0ef41Sopenharmony_ci } 9591cb0ef41Sopenharmony_ci else { 9601cb0ef41Sopenharmony_ci // A partially elided address 9611cb0ef41Sopenharmony_ci const halves = address6.address.split('::'); 9621cb0ef41Sopenharmony_ci if (halves[0].length) { 9631cb0ef41Sopenharmony_ci output.push((0, regular_expressions_1.simpleRegularExpression)(halves[0].split(':'))); 9641cb0ef41Sopenharmony_ci } 9651cb0ef41Sopenharmony_ci assert(typeof address6.elidedGroups === 'number'); 9661cb0ef41Sopenharmony_ci output.push((0, regular_expressions_1.possibleElisions)(address6.elidedGroups, halves[0].length !== 0, halves[1].length !== 0)); 9671cb0ef41Sopenharmony_ci if (halves[1].length) { 9681cb0ef41Sopenharmony_ci output.push((0, regular_expressions_1.simpleRegularExpression)(halves[1].split(':'))); 9691cb0ef41Sopenharmony_ci } 9701cb0ef41Sopenharmony_ci output = [output.join(':')]; 9711cb0ef41Sopenharmony_ci } 9721cb0ef41Sopenharmony_ci if (!substringSearch) { 9731cb0ef41Sopenharmony_ci output = [ 9741cb0ef41Sopenharmony_ci '(?=^|', 9751cb0ef41Sopenharmony_ci regular_expressions_1.ADDRESS_BOUNDARY, 9761cb0ef41Sopenharmony_ci '|[^\\w\\:])(', 9771cb0ef41Sopenharmony_ci ...output, 9781cb0ef41Sopenharmony_ci ')(?=[^\\w\\:]|', 9791cb0ef41Sopenharmony_ci regular_expressions_1.ADDRESS_BOUNDARY, 9801cb0ef41Sopenharmony_ci '|$)', 9811cb0ef41Sopenharmony_ci ]; 9821cb0ef41Sopenharmony_ci } 9831cb0ef41Sopenharmony_ci return output.join(''); 9841cb0ef41Sopenharmony_ci } 9851cb0ef41Sopenharmony_ci /** 9861cb0ef41Sopenharmony_ci * Generate a regular expression that can be used to find or validate all 9871cb0ef41Sopenharmony_ci * variations of this address. 9881cb0ef41Sopenharmony_ci * @memberof Address6 9891cb0ef41Sopenharmony_ci * @instance 9901cb0ef41Sopenharmony_ci * @param {boolean} substringSearch 9911cb0ef41Sopenharmony_ci * @returns {RegExp} 9921cb0ef41Sopenharmony_ci */ 9931cb0ef41Sopenharmony_ci regularExpression(substringSearch = false) { 9941cb0ef41Sopenharmony_ci return new RegExp(this.regularExpressionString(substringSearch), 'i'); 9951cb0ef41Sopenharmony_ci } 9961cb0ef41Sopenharmony_ci} 9971cb0ef41Sopenharmony_ciexports.Address6 = Address6; 9981cb0ef41Sopenharmony_ci//# sourceMappingURL=ipv6.js.map