ipv4.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. "use strict";
  2. /* eslint-disable no-param-reassign */
  3. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  4. if (k2 === undefined) k2 = k;
  5. var desc = Object.getOwnPropertyDescriptor(m, k);
  6. if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
  7. desc = { enumerable: true, get: function() { return m[k]; } };
  8. }
  9. Object.defineProperty(o, k2, desc);
  10. }) : (function(o, m, k, k2) {
  11. if (k2 === undefined) k2 = k;
  12. o[k2] = m[k];
  13. }));
  14. var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
  15. Object.defineProperty(o, "default", { enumerable: true, value: v });
  16. }) : function(o, v) {
  17. o["default"] = v;
  18. });
  19. var __importStar = (this && this.__importStar) || function (mod) {
  20. if (mod && mod.__esModule) return mod;
  21. var result = {};
  22. if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
  23. __setModuleDefault(result, mod);
  24. return result;
  25. };
  26. Object.defineProperty(exports, "__esModule", { value: true });
  27. exports.Address4 = void 0;
  28. const common = __importStar(require("./common"));
  29. const constants = __importStar(require("./v4/constants"));
  30. const address_error_1 = require("./address-error");
  31. const jsbn_1 = require("jsbn");
  32. const sprintf_js_1 = require("sprintf-js");
  33. /**
  34. * Represents an IPv4 address
  35. * @class Address4
  36. * @param {string} address - An IPv4 address string
  37. */
  38. class Address4 {
  39. constructor(address) {
  40. this.groups = constants.GROUPS;
  41. this.parsedAddress = [];
  42. this.parsedSubnet = '';
  43. this.subnet = '/32';
  44. this.subnetMask = 32;
  45. this.v4 = true;
  46. /**
  47. * Returns true if the address is correct, false otherwise
  48. * @memberof Address4
  49. * @instance
  50. * @returns {Boolean}
  51. */
  52. this.isCorrect = common.isCorrect(constants.BITS);
  53. /**
  54. * Returns true if the given address is in the subnet of the current address
  55. * @memberof Address4
  56. * @instance
  57. * @returns {boolean}
  58. */
  59. this.isInSubnet = common.isInSubnet;
  60. this.address = address;
  61. const subnet = constants.RE_SUBNET_STRING.exec(address);
  62. if (subnet) {
  63. this.parsedSubnet = subnet[0].replace('/', '');
  64. this.subnetMask = parseInt(this.parsedSubnet, 10);
  65. this.subnet = `/${this.subnetMask}`;
  66. if (this.subnetMask < 0 || this.subnetMask > constants.BITS) {
  67. throw new address_error_1.AddressError('Invalid subnet mask.');
  68. }
  69. address = address.replace(constants.RE_SUBNET_STRING, '');
  70. }
  71. this.addressMinusSuffix = address;
  72. this.parsedAddress = this.parse(address);
  73. }
  74. static isValid(address) {
  75. try {
  76. // eslint-disable-next-line no-new
  77. new Address4(address);
  78. return true;
  79. }
  80. catch (e) {
  81. return false;
  82. }
  83. }
  84. /*
  85. * Parses a v4 address
  86. */
  87. parse(address) {
  88. const groups = address.split('.');
  89. if (!address.match(constants.RE_ADDRESS)) {
  90. throw new address_error_1.AddressError('Invalid IPv4 address.');
  91. }
  92. return groups;
  93. }
  94. /**
  95. * Returns the correct form of an address
  96. * @memberof Address4
  97. * @instance
  98. * @returns {String}
  99. */
  100. correctForm() {
  101. return this.parsedAddress.map((part) => parseInt(part, 10)).join('.');
  102. }
  103. /**
  104. * Converts a hex string to an IPv4 address object
  105. * @memberof Address4
  106. * @static
  107. * @param {string} hex - a hex string to convert
  108. * @returns {Address4}
  109. */
  110. static fromHex(hex) {
  111. const padded = hex.replace(/:/g, '').padStart(8, '0');
  112. const groups = [];
  113. let i;
  114. for (i = 0; i < 8; i += 2) {
  115. const h = padded.slice(i, i + 2);
  116. groups.push(parseInt(h, 16));
  117. }
  118. return new Address4(groups.join('.'));
  119. }
  120. /**
  121. * Converts an integer into a IPv4 address object
  122. * @memberof Address4
  123. * @static
  124. * @param {integer} integer - a number to convert
  125. * @returns {Address4}
  126. */
  127. static fromInteger(integer) {
  128. return Address4.fromHex(integer.toString(16));
  129. }
  130. /**
  131. * Return an address from in-addr.arpa form
  132. * @memberof Address4
  133. * @static
  134. * @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address
  135. * @returns {Adress4}
  136. * @example
  137. * var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.)
  138. * address.correctForm(); // '192.0.2.42'
  139. */
  140. static fromArpa(arpaFormAddress) {
  141. // remove ending ".in-addr.arpa." or just "."
  142. const leader = arpaFormAddress.replace(/(\.in-addr\.arpa)?\.$/, '');
  143. const address = leader.split('.').reverse().join('.');
  144. return new Address4(address);
  145. }
  146. /**
  147. * Converts an IPv4 address object to a hex string
  148. * @memberof Address4
  149. * @instance
  150. * @returns {String}
  151. */
  152. toHex() {
  153. return this.parsedAddress.map((part) => (0, sprintf_js_1.sprintf)('%02x', parseInt(part, 10))).join(':');
  154. }
  155. /**
  156. * Converts an IPv4 address object to an array of bytes
  157. * @memberof Address4
  158. * @instance
  159. * @returns {Array}
  160. */
  161. toArray() {
  162. return this.parsedAddress.map((part) => parseInt(part, 10));
  163. }
  164. /**
  165. * Converts an IPv4 address object to an IPv6 address group
  166. * @memberof Address4
  167. * @instance
  168. * @returns {String}
  169. */
  170. toGroup6() {
  171. const output = [];
  172. let i;
  173. for (i = 0; i < constants.GROUPS; i += 2) {
  174. const hex = (0, sprintf_js_1.sprintf)('%02x%02x', parseInt(this.parsedAddress[i], 10), parseInt(this.parsedAddress[i + 1], 10));
  175. output.push((0, sprintf_js_1.sprintf)('%x', parseInt(hex, 16)));
  176. }
  177. return output.join(':');
  178. }
  179. /**
  180. * Returns the address as a BigInteger
  181. * @memberof Address4
  182. * @instance
  183. * @returns {BigInteger}
  184. */
  185. bigInteger() {
  186. return new jsbn_1.BigInteger(this.parsedAddress.map((n) => (0, sprintf_js_1.sprintf)('%02x', parseInt(n, 10))).join(''), 16);
  187. }
  188. /**
  189. * Helper function getting start address.
  190. * @memberof Address4
  191. * @instance
  192. * @returns {BigInteger}
  193. */
  194. _startAddress() {
  195. return new jsbn_1.BigInteger(this.mask() + '0'.repeat(constants.BITS - this.subnetMask), 2);
  196. }
  197. /**
  198. * The first address in the range given by this address' subnet.
  199. * Often referred to as the Network Address.
  200. * @memberof Address4
  201. * @instance
  202. * @returns {Address4}
  203. */
  204. startAddress() {
  205. return Address4.fromBigInteger(this._startAddress());
  206. }
  207. /**
  208. * The first host address in the range given by this address's subnet ie
  209. * the first address after the Network Address
  210. * @memberof Address4
  211. * @instance
  212. * @returns {Address4}
  213. */
  214. startAddressExclusive() {
  215. const adjust = new jsbn_1.BigInteger('1');
  216. return Address4.fromBigInteger(this._startAddress().add(adjust));
  217. }
  218. /**
  219. * Helper function getting end address.
  220. * @memberof Address4
  221. * @instance
  222. * @returns {BigInteger}
  223. */
  224. _endAddress() {
  225. return new jsbn_1.BigInteger(this.mask() + '1'.repeat(constants.BITS - this.subnetMask), 2);
  226. }
  227. /**
  228. * The last address in the range given by this address' subnet
  229. * Often referred to as the Broadcast
  230. * @memberof Address4
  231. * @instance
  232. * @returns {Address4}
  233. */
  234. endAddress() {
  235. return Address4.fromBigInteger(this._endAddress());
  236. }
  237. /**
  238. * The last host address in the range given by this address's subnet ie
  239. * the last address prior to the Broadcast Address
  240. * @memberof Address4
  241. * @instance
  242. * @returns {Address4}
  243. */
  244. endAddressExclusive() {
  245. const adjust = new jsbn_1.BigInteger('1');
  246. return Address4.fromBigInteger(this._endAddress().subtract(adjust));
  247. }
  248. /**
  249. * Converts a BigInteger to a v4 address object
  250. * @memberof Address4
  251. * @static
  252. * @param {BigInteger} bigInteger - a BigInteger to convert
  253. * @returns {Address4}
  254. */
  255. static fromBigInteger(bigInteger) {
  256. return Address4.fromInteger(parseInt(bigInteger.toString(), 10));
  257. }
  258. /**
  259. * Returns the first n bits of the address, defaulting to the
  260. * subnet mask
  261. * @memberof Address4
  262. * @instance
  263. * @returns {String}
  264. */
  265. mask(mask) {
  266. if (mask === undefined) {
  267. mask = this.subnetMask;
  268. }
  269. return this.getBitsBase2(0, mask);
  270. }
  271. /**
  272. * Returns the bits in the given range as a base-2 string
  273. * @memberof Address4
  274. * @instance
  275. * @returns {string}
  276. */
  277. getBitsBase2(start, end) {
  278. return this.binaryZeroPad().slice(start, end);
  279. }
  280. /**
  281. * Return the reversed ip6.arpa form of the address
  282. * @memberof Address4
  283. * @param {Object} options
  284. * @param {boolean} options.omitSuffix - omit the "in-addr.arpa" suffix
  285. * @instance
  286. * @returns {String}
  287. */
  288. reverseForm(options) {
  289. if (!options) {
  290. options = {};
  291. }
  292. const reversed = this.correctForm().split('.').reverse().join('.');
  293. if (options.omitSuffix) {
  294. return reversed;
  295. }
  296. return (0, sprintf_js_1.sprintf)('%s.in-addr.arpa.', reversed);
  297. }
  298. /**
  299. * Returns true if the given address is a multicast address
  300. * @memberof Address4
  301. * @instance
  302. * @returns {boolean}
  303. */
  304. isMulticast() {
  305. return this.isInSubnet(new Address4('224.0.0.0/4'));
  306. }
  307. /**
  308. * Returns a zero-padded base-2 string representation of the address
  309. * @memberof Address4
  310. * @instance
  311. * @returns {string}
  312. */
  313. binaryZeroPad() {
  314. return this.bigInteger().toString(2).padStart(constants.BITS, '0');
  315. }
  316. /**
  317. * Groups an IPv4 address for inclusion at the end of an IPv6 address
  318. * @returns {String}
  319. */
  320. groupForV6() {
  321. const segments = this.parsedAddress;
  322. return this.address.replace(constants.RE_ADDRESS, (0, sprintf_js_1.sprintf)('<span class="hover-group group-v4 group-6">%s</span>.<span class="hover-group group-v4 group-7">%s</span>', segments.slice(0, 2).join('.'), segments.slice(2, 4).join('.')));
  323. }
  324. }
  325. exports.Address4 = Address4;
  326. //# sourceMappingURL=ipv4.js.map