JAVASCRIPT   116

ip.js

Guest on 19th July 2021 07:07:49 PM

  1. 'use strict';
  2.  
  3. var ip = exports;
  4. var Buffer = require('buffer').Buffer;
  5. var os = require('os');
  6.  
  7. ip.toBuffer = function(ip, buff, offset) {
  8.   offset = ~~offset;
  9.  
  10.   var result;
  11.  
  12.   if (this.isV4Format(ip)) {
  13.     result = buff || new Buffer(offset + 4);
  14.     ip.split(/\./g).map(function(byte) {
  15.       result[offset++] = parseInt(byte, 10) & 0xff;
  16.     });
  17.   } else if (this.isV6Format(ip)) {
  18.     var sections = ip.split(':', 8);
  19.  
  20.     var i;
  21.     for (i = 0; i < sections.length; i++) {
  22.       var isv4 = this.isV4Format(sections[i]);
  23.       var v4Buffer;
  24.  
  25.       if (isv4) {
  26.         v4Buffer = this.toBuffer(sections[i]);
  27.         sections[i] = v4Buffer.slice(0, 2).toString('hex');
  28.       }
  29.  
  30.       if (v4Buffer && ++i < 8) {
  31.         sections.splice(i, 0, v4Buffer.slice(2, 4).toString('hex'));
  32.       }
  33.     }
  34.  
  35.     if (sections[0] === '') {
  36.       while (sections.length < 8) sections.unshift('0');
  37.     } else if (sections[sections.length - 1] === '') {
  38.       while (sections.length < 8) sections.push('0');
  39.     } else if (sections.length < 8) {
  40.       for (i = 0; i < sections.length && sections[i] !== ''; i++);
  41.       var argv = [ i, 1 ];
  42.       for (i = 9 - sections.length; i > 0; i--) {
  43.         argv.push('0');
  44.       }
  45.       sections.splice.apply(sections, argv);
  46.     }
  47.  
  48.     result = buff || new Buffer(offset + 16);
  49.     for (i = 0; i < sections.length; i++) {
  50.       var word = parseInt(sections[i], 16);
  51.       result[offset++] = (word >> 8) & 0xff;
  52.       result[offset++] = word & 0xff;
  53.     }
  54.   }
  55.  
  56.   if (!result) {
  57.     throw Error('Invalid ip address: ' + ip);
  58.   }
  59.  
  60.   return result;
  61. };
  62.  
  63. ip.toString = function(buff, offset, length) {
  64.   offset = ~~offset;
  65.   length = length || (buff.length - offset);
  66.  
  67.   var result = [];
  68.   if (length === 4) {
  69.     // IPv4
  70.     for (var i = 0; i < length; i++) {
  71.       result.push(buff[offset + i]);
  72.     }
  73.     result = result.join('.');
  74.   } else if (length === 16) {
  75.     // IPv6
  76.     for (var i = 0; i < length; i += 2) {
  77.       result.push(buff.readUInt16BE(offset + i).toString(16));
  78.     }
  79.     result = result.join(':');
  80.     result = result.replace(/(^|:)0(:0)*:0(:|$)/, '$1::$3');
  81.     result = result.replace(/:{3,4}/, '::');
  82.   }
  83.  
  84.   return result;
  85. };
  86.  
  87. var ipv4Regex = /^(\d{1,3}\.){3,3}\d{1,3}$/;
  88. var ipv6Regex =
  89.     /^(::)?(((\d{1,3}\.){3}(\d{1,3}){1})?([0-9a-f]){0,4}:{0,2}){1,8}(::)?$/i;
  90.  
  91. ip.isV4Format = function(ip) {
  92.   return ipv4Regex.test(ip);
  93. };
  94.  
  95. ip.isV6Format = function(ip) {
  96.   return ipv6Regex.test(ip);
  97. };
  98. function _normalizeFamily(family) {
  99.   return family ? family.toLowerCase() : 'ipv4';
  100. }
  101.  
  102. ip.fromPrefixLen = function(prefixlen, family) {
  103.   if (prefixlen > 32) {
  104.     family = 'ipv6';
  105.   } else {
  106.     family = _normalizeFamily(family);
  107.   }
  108.  
  109.   var len = 4;
  110.   if (family === 'ipv6') {
  111.     len = 16;
  112.   }
  113.   var buff = new Buffer(len);
  114.  
  115.   for (var i = 0, n = buff.length; i < n; ++i) {
  116.     var bits = 8;
  117.     if (prefixlen < 8) {
  118.       bits = prefixlen;
  119.     }
  120.     prefixlen -= bits;
  121.  
  122.     buff[i] = ~(0xff >> bits) & 0xff;
  123.   }
  124.  
  125.   return ip.toString(buff);
  126. };
  127.  
  128. ip.mask = function(addr, mask) {
  129.   addr = ip.toBuffer(addr);
  130.   mask = ip.toBuffer(mask);
  131.  
  132.   var result = new Buffer(Math.max(addr.length, mask.length));
  133.  
  134.   var i = 0;
  135.   // Same protocol - do bitwise and
  136.   if (addr.length === mask.length) {
  137.     for (i = 0; i < addr.length; i++) {
  138.       result[i] = addr[i] & mask[i];
  139.     }
  140.   } else if (mask.length === 4) {
  141.     // IPv6 address and IPv4 mask
  142.     // (Mask low bits)
  143.     for (i = 0; i < mask.length; i++) {
  144.       result[i] = addr[addr.length - 4  + i] & mask[i];
  145.     }
  146.   } else {
  147.     // IPv6 mask and IPv4 addr
  148.     for (var i = 0; i < result.length - 6; i++) {
  149.       result[i] = 0;
  150.     }
  151.  
  152.     // ::ffff:ipv4
  153.     result[10] = 0xff;
  154.     result[11] = 0xff;
  155.     for (i = 0; i < addr.length; i++) {
  156.       result[i + 12] = addr[i] & mask[i + 12];
  157.     }
  158.     i = i + 12;
  159.   }
  160.   for (; i < result.length; i++)
  161.     result[i] = 0;
  162.  
  163.   return ip.toString(result);
  164. };
  165.  
  166. ip.cidr = function(cidrString) {
  167.   var cidrParts = cidrString.split('/');
  168.  
  169.   var addr = cidrParts[0];
  170.   if (cidrParts.length !== 2)
  171.     throw new Error('invalid CIDR subnet: ' + addr);
  172.  
  173.   var mask = ip.fromPrefixLen(parseInt(cidrParts[1], 10));
  174.  
  175.   return ip.mask(addr, mask);
  176. };
  177.  
  178. ip.subnet = function(addr, mask) {
  179.   var networkAddress = ip.toLong(ip.mask(addr, mask));
  180.  
  181.   // Calculate the mask's length.
  182.   var maskBuffer = ip.toBuffer(mask);
  183.   var maskLength = 0;
  184.  
  185.   for (var i = 0; i < maskBuffer.length; i++) {
  186.     if (maskBuffer[i] === 0xff) {
  187.       maskLength += 8;
  188.     } else {
  189.       var octet = maskBuffer[i] & 0xff;
  190.       while (octet) {
  191.         octet = (octet << 1) & 0xff;
  192.         maskLength++;
  193.       }
  194.     }
  195.   }
  196.  
  197.   var numberOfAddresses = Math.pow(2, 32 - maskLength);
  198.  
  199.   return {
  200.     networkAddress: ip.fromLong(networkAddress),
  201.     firstAddress: numberOfAddresses <= 2 ?
  202.                     ip.fromLong(networkAddress) :
  203.                     ip.fromLong(networkAddress + 1),
  204.     lastAddress: numberOfAddresses <= 2 ?
  205.                     ip.fromLong(networkAddress + numberOfAddresses - 1) :
  206.                     ip.fromLong(networkAddress + numberOfAddresses - 2),
  207.     broadcastAddress: ip.fromLong(networkAddress + numberOfAddresses - 1),
  208.     subnetMask: mask,
  209.     subnetMaskLength: maskLength,
  210.     numHosts: numberOfAddresses <= 2 ?
  211.                 numberOfAddresses : numberOfAddresses - 2,
  212.     length: numberOfAddresses,
  213.     contains: function(other) {
  214.       return networkAddress === ip.toLong(ip.mask(other, mask));
  215.     }
  216.   };
  217. };
  218.  
  219. ip.cidrSubnet = function(cidrString) {
  220.   var cidrParts = cidrString.split('/');
  221.  
  222.   var addr = cidrParts[0];
  223.   if (cidrParts.length !== 2)
  224.     throw new Error('invalid CIDR subnet: ' + addr);
  225.  
  226.   var mask = ip.fromPrefixLen(parseInt(cidrParts[1], 10));
  227.  
  228.   return ip.subnet(addr, mask);
  229. };
  230.  
  231. ip.not = function(addr) {
  232.   var buff = ip.toBuffer(addr);
  233.   for (var i = 0; i < buff.length; i++) {
  234.     buff[i] = 0xff ^ buff[i];
  235.   }
  236.   return ip.toString(buff);
  237. };
  238.  
  239. ip.or = function(a, b) {
  240.   a = ip.toBuffer(a);
  241.   b = ip.toBuffer(b);
  242.  
  243.   // same protocol
  244.   if (a.length === b.length) {
  245.     for (var i = 0; i < a.length; ++i) {
  246.       a[i] |= b[i];
  247.     }
  248.     return ip.toString(a);
  249.  
  250.   // mixed protocols
  251.   } else {
  252.     var buff = a;
  253.     var other = b;
  254.     if (b.length > a.length) {
  255.       buff = b;
  256.       other = a;
  257.     }
  258.  
  259.     var offset = buff.length - other.length;
  260.     for (var i = offset; i < buff.length; ++i) {
  261.       buff[i] |= other[i - offset];
  262.     }
  263.  
  264.     return ip.toString(buff);
  265.   }
  266. };
  267.  
  268. ip.isEqual = function(a, b) {
  269.   a = ip.toBuffer(a);
  270.   b = ip.toBuffer(b);
  271.  
  272.   // Same protocol
  273.   if (a.length === b.length) {
  274.     for (var i = 0; i < a.length; i++) {
  275.       if (a[i] !== b[i]) return false;
  276.     }
  277.     return true;
  278.   }
  279.  
  280.   // Swap
  281.   if (b.length === 4) {
  282.     var t = b;
  283.     b = a;
  284.     a = t;
  285.   }
  286.  
  287.   // a - IPv4, b - IPv6
  288.   for (var i = 0; i < 10; i++) {
  289.     if (b[i] !== 0) return false;
  290.   }
  291.  
  292.   var word = b.readUInt16BE(10);
  293.   if (word !== 0 && word !== 0xffff) return false;
  294.  
  295.   for (var i = 0; i < 4; i++) {
  296.     if (a[i] !== b[i + 12]) return false;
  297.   }
  298.  
  299.   return true;
  300. };
  301.  
  302. ip.isPrivate = function(addr) {
  303.   return /^(::f{4}:)?10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i
  304.       .test(addr) ||
  305.     /^(::f{4}:)?192\.168\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
  306.     /^(::f{4}:)?172\.(1[6-9]|2\d|30|31)\.([0-9]{1,3})\.([0-9]{1,3})$/i
  307.       .test(addr) ||
  308.     /^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
  309.     /^(::f{4}:)?169\.254\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
  310.     /^f[cd][0-9a-f]{2}:/i.test(addr) ||
  311.     /^fe80:/i.test(addr) ||
  312.     /^::1$/.test(addr) ||
  313.     /^::$/.test(addr);
  314. };
  315.  
  316. ip.isPublic = function(addr) {
  317.   return !ip.isPrivate(addr);
  318. };
  319.  
  320. ip.isLoopback = function(addr) {
  321.   return /^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/
  322.       .test(addr) ||
  323.     /^fe80::1$/.test(addr) ||
  324.     /^::1$/.test(addr) ||
  325.     /^::$/.test(addr);
  326. };
  327.  
  328. ip.loopback = function(family) {
  329.   //
  330.   // Default to `ipv4`
  331.   //
  332.   family = _normalizeFamily(family);
  333.  
  334.   if (family !== 'ipv4' && family !== 'ipv6') {
  335.     throw new Error('family must be ipv4 or ipv6');
  336.   }
  337.  
  338.   return family === 'ipv4' ? '127.0.0.1' : 'fe80::1';
  339. };
  340.  
  341. //
  342. // ### function address (name, family)
  343. // #### @name {string|'public'|'private'} **Optional** Name or security
  344. //      of the network interface.
  345. // #### @family {ipv4|ipv6} **Optional** IP family of the address (defaults
  346. //      to ipv4).
  347. //
  348. // Returns the address for the network interface on the current system with
  349. // the specified `name`:
  350. //   * String: First `family` address of the interface.
  351. //             If not found see `undefined`.
  352. //   * 'public': the first public ip address of family.
  353. //   * 'private': the first private ip address of family.
  354. //   * undefined: First address with `ipv4` or loopback address `127.0.0.1`.
  355. //
  356. ip.address = function(name, family) {
  357.   var interfaces = os.networkInterfaces();
  358.   var all;
  359.  
  360.   //
  361.   // Default to `ipv4`
  362.   //
  363.   family = _normalizeFamily(family);
  364.  
  365.   //
  366.   // If a specific network interface has been named,
  367.   // return the address.
  368.   //
  369.   if (name && name !== 'private' && name !== 'public') {
  370.     var res = interfaces[name].filter(function(details) {
  371.       var itemFamily = details.family.toLowerCase();
  372.       return itemFamily === family;
  373.     });
  374.     if (res.length === 0)
  375.       return undefined;
  376.     return res[0].address;
  377.   }
  378.  
  379.   var all = Object.keys(interfaces).map(function (nic) {
  380.     //
  381.     // Note: name will only be `public` or `private`
  382.     // when this is called.
  383.     //
  384.     var addresses = interfaces[nic].filter(function (details) {
  385.       details.family = details.family.toLowerCase();
  386.       if (details.family !== family || ip.isLoopback(details.address)) {
  387.         return false;
  388.       } else if (!name) {
  389.         return true;
  390.       }
  391.  
  392.       return name === 'public' ? ip.isPrivate(details.address) :
  393.           ip.isPublic(details.address);
  394.     });
  395.  
  396.     return addresses.length ? addresses[0].address : undefined;
  397.   }).filter(Boolean);
  398.  
  399.   return !all.length ? ip.loopback(family) : all[0];
  400. };
  401.  
  402. ip.toLong = function(ip) {
  403.   var ipl = 0;
  404.   ip.split('.').forEach(function(octet) {
  405.     ipl <<= 8;
  406.     ipl += parseInt(octet);
  407.   });
  408.   return(ipl >>> 0);
  409. };
  410.  
  411. ip.fromLong = function(ipl) {
  412.   return ((ipl >>> 24) + '.' +
  413.       (ipl >> 16 & 255) + '.' +
  414.       (ipl >> 8 & 255) + '.' +
  415.       (ipl & 255) );
  416. };

Raw Paste


Login or Register to edit or fork this paste. It's free.