2016-11-28 10:42:58 +00:00
/* globals BigInteger */
/ * *
* Internet Protocol address operations .
*
* @ author n1474335 [ n1474335 @ gmail . com ]
* @ copyright Crown Copyright 2016
* @ license Apache - 2.0
*
* @ namespace
* /
var IP = {
/ * *
* @ constant
* @ default
* /
INCLUDE _NETWORK _INFO : true ,
/ * *
* @ constant
* @ default
* /
ENUMERATE _ADDRESSES : true ,
/ * *
* @ constant
* @ default
* /
ALLOW _LARGE _LIST : false ,
/ * *
* Parse IP range operation .
*
* @ param { string } input
* @ param { Object [ ] } args
* @ returns { string }
* /
run _parse _ip _range : function ( input , args ) {
var include _network _info = args [ 0 ] ,
enumerate _addresses = args [ 1 ] ,
allow _large _list = args [ 2 ] ;
// Check what type of input we are looking at
var ipv4 _cidr _regex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/ ,
ipv4 _range _regex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/ ,
ipv6 _cidr _regex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i ,
ipv6 _range _regex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i ,
match ;
2016-12-14 16:39:17 +00:00
if ( ( match = ipv4 _cidr _regex . exec ( input ) ) ) {
2016-11-28 10:42:58 +00:00
return IP . _ipv4 _cidr _range ( match , include _network _info , enumerate _addresses , allow _large _list ) ;
2016-12-14 16:39:17 +00:00
} else if ( ( match = ipv4 _range _regex . exec ( input ) ) ) {
2016-11-28 10:42:58 +00:00
return IP . _ipv4 _hyphenated _range ( match , include _network _info , enumerate _addresses , allow _large _list ) ;
2016-12-14 16:39:17 +00:00
} else if ( ( match = ipv6 _cidr _regex . exec ( input ) ) ) {
2016-11-28 10:42:58 +00:00
return IP . _ipv6 _cidr _range ( match , include _network _info ) ;
2016-12-14 16:39:17 +00:00
} else if ( ( match = ipv6 _range _regex . exec ( input ) ) ) {
2016-11-28 10:42:58 +00:00
return IP . _ipv6 _hyphenated _range ( match , include _network _info ) ;
} else {
return "Invalid input.\n\nEnter either a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0). IPv6 also supported." ;
}
} ,
/ * *
* @ constant
* @ default
* /
IPv4 _REGEX : /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/ ,
/ * *
* @ constant
* @ default
* /
IPv6 _REGEX : /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i ,
/ * *
* Parse IPv6 address operation .
*
* @ param { string } input
* @ param { Object [ ] } args
* @ returns { string }
* /
run _parse _ipv6 : function ( input , args ) {
var match ,
output = "" ;
2016-12-14 16:39:17 +00:00
if ( ( match = IP . IPv6 _REGEX . exec ( input ) ) ) {
2016-11-28 10:42:58 +00:00
var ipv6 = IP . _str _to _ipv6 ( match [ 1 ] ) ,
longhand = IP . _ipv6 _to _str ( ipv6 ) ,
shorthand = IP . _ipv6 _to _str ( ipv6 , true ) ;
output += "Longhand: " + longhand + "\nShorthand: " + shorthand + "\n" ;
// Detect reserved addresses
2016-12-14 16:39:17 +00:00
if ( shorthand === "::" ) {
2016-11-28 10:42:58 +00:00
// Unspecified address
output += "\nUnspecified address corresponding to 0.0.0.0/32 in IPv4." ;
output += "\nUnspecified address range: ::/128" ;
2016-12-14 16:39:17 +00:00
} else if ( shorthand === "::1" ) {
2016-11-28 10:42:58 +00:00
// Loopback address
output += "\nLoopback address to the local host corresponding to 127.0.0.1/8 in IPv4." ;
output += "\nLoopback addresses range: ::1/128" ;
} else if ( ipv6 [ 0 ] === 0 && ipv6 [ 1 ] === 0 && ipv6 [ 2 ] === 0 &&
ipv6 [ 3 ] === 0 && ipv6 [ 4 ] === 0 && ipv6 [ 5 ] === 0xffff ) {
// IPv4-mapped IPv6 address
output += "\nIPv4-mapped IPv6 address detected. IPv6 clients will be handled natively by default, and IPv4 clients appear as IPv6 clients at their IPv4-mapped IPv6 address." ;
output += "\nMapped IPv4 address: " + IP . _ipv4 _to _str ( ( ipv6 [ 6 ] << 16 ) + ipv6 [ 7 ] ) ;
output += "\nIPv4-mapped IPv6 addresses range: ::ffff:0:0/96" ;
} else if ( ipv6 [ 0 ] === 0 && ipv6 [ 1 ] === 0 && ipv6 [ 2 ] === 0 &&
ipv6 [ 3 ] === 0 && ipv6 [ 4 ] === 0xffff && ipv6 [ 5 ] === 0 ) {
// IPv4-translated address
output += "\nIPv4-translated address detected. Used by Stateless IP/ICMP Translation (SIIT). See RFCs 6145 and 6052 for more details." ;
output += "\nTranslated IPv4 address: " + IP . _ipv4 _to _str ( ( ipv6 [ 6 ] << 16 ) + ipv6 [ 7 ] ) ;
output += "\nIPv4-translated addresses range: ::ffff:0:0:0/96" ;
} else if ( ipv6 [ 0 ] === 0x100 ) {
// Discard prefix per RFC 6666
output += "\nDiscard prefix detected. This is used when forwarding traffic to a sinkhole router to mitigate the effects of a denial-of-service attack. See RFC 6666 for more details." ;
output += "\nDiscard range: 100::/64" ;
} else if ( ipv6 [ 0 ] === 0x64 && ipv6 [ 1 ] === 0xff9b && ipv6 [ 2 ] === 0 &&
ipv6 [ 3 ] === 0 && ipv6 [ 4 ] === 0 && ipv6 [ 5 ] === 0 ) {
// IPv4/IPv6 translation per RFC 6052
output += "\n'Well-Known' prefix for IPv4/IPv6 translation detected. See RFC 6052 for more details." ;
output += "\nTranslated IPv4 address: " + IP . _ipv4 _to _str ( ( ipv6 [ 6 ] << 16 ) + ipv6 [ 7 ] ) ;
output += "\n'Well-Known prefix range: 64:ff9b::/96" ;
} else if ( ipv6 [ 0 ] === 0x2001 && ipv6 [ 1 ] === 0 ) {
// Teredo tunneling
output += "\nTeredo tunneling IPv6 address detected\n" ;
var server _ipv4 = ( ipv6 [ 2 ] << 16 ) + ipv6 [ 3 ] ,
udp _port = ( ~ ipv6 [ 5 ] ) & 0xffff ,
client _ipv4 = ~ ( ( ipv6 [ 6 ] << 16 ) + ipv6 [ 7 ] ) ,
flag _cone = ( ipv6 [ 4 ] >>> 15 ) & 1 ,
flag _r = ( ipv6 [ 4 ] >>> 14 ) & 1 ,
flag _random1 = ( ipv6 [ 4 ] >>> 10 ) & 15 ,
flag _ug = ( ipv6 [ 4 ] >>> 8 ) & 3 ,
flag _random2 = ipv6 [ 4 ] & 255 ;
output += "\nServer IPv4 address: " + IP . _ipv4 _to _str ( server _ipv4 ) +
"\nClient IPv4 address: " + IP . _ipv4 _to _str ( client _ipv4 ) +
"\nClient UDP port: " + udp _port +
"\nFlags:" +
"\n\tCone: " + flag _cone ;
if ( flag _cone ) {
output += " (Client is behind a cone NAT)" ;
} else {
output += " (Client is not behind a cone NAT)" ;
}
output += "\n\tR: " + flag _r ;
if ( flag _r ) {
output += " Error: This flag should be set to 0. See RFC 5991 and RFC 4380." ;
}
output += "\n\tRandom1: " + Utils . bin ( flag _random1 , 4 ) +
"\n\tUG: " + Utils . bin ( flag _ug , 2 ) ;
if ( flag _ug ) {
output += " Error: This flag should be set to 00. See RFC 4380." ;
}
output += "\n\tRandom2: " + Utils . bin ( flag _random2 , 8 ) ;
if ( ! flag _r && ! flag _ug && flag _random1 && flag _random2 ) {
output += "\n\nThis is a valid Teredo address which complies with RFC 4380 and RFC 5991." ;
} else if ( ! flag _r && ! flag _ug ) {
output += "\n\nThis is a valid Teredo address which complies with RFC 4380, however it does not comply with RFC 5991 (Teredo Security Updates) as there are no randomised bits in the flag field." ;
} else {
output += "\n\nThis is an invalid Teredo address." ;
}
output += "\n\nTeredo prefix range: 2001::/32" ;
} else if ( ipv6 [ 0 ] === 0x2001 && ipv6 [ 1 ] === 0x2 && ipv6 [ 2 ] === 0 ) {
// Benchmarking
output += "\nAssigned to the Benchmarking Methodology Working Group (BMWG) for benchmarking IPv6. Corresponds to 198.18.0.0/15 for benchmarking IPv4. See RFC 5180 for more details." ;
output += "\nBMWG range: 2001:2::/48" ;
2016-12-14 16:39:17 +00:00
} else if ( ipv6 [ 0 ] === 0x2001 && ipv6 [ 1 ] >= 0x10 && ipv6 [ 1 ] <= 0x1f ) {
2016-11-28 10:42:58 +00:00
// ORCHIDv1
output += "\nDeprecated, previously ORCHIDv1 (Overlay Routable Cryptographic Hash Identifiers).\nORCHIDv1 range: 2001:10::/28\nORCHIDv2 now uses 2001:20::/28." ;
2016-12-14 16:39:17 +00:00
} else if ( ipv6 [ 0 ] === 0x2001 && ipv6 [ 1 ] >= 0x20 && ipv6 [ 1 ] <= 0x2f ) {
2016-11-28 10:42:58 +00:00
// ORCHIDv2
output += "\nORCHIDv2 (Overlay Routable Cryptographic Hash Identifiers).\nThese are non-routed IPv6 addresses used for Cryptographic Hash Identifiers." ;
output += "\nORCHIDv2 range: 2001:20::/28" ;
2016-12-14 16:39:17 +00:00
} else if ( ipv6 [ 0 ] === 0x2001 && ipv6 [ 1 ] === 0xdb8 ) {
2016-11-28 10:42:58 +00:00
// Documentation
output += "\nThis is a documentation IPv6 address. This range should be used whenever an example IPv6 address is given or to model networking scenarios. Corresponds to 192.0.2.0/24, 198.51.100.0/24, and 203.0.113.0/24 in IPv4." ;
output += "\nDocumentation range: 2001:db8::/32" ;
2016-12-14 16:39:17 +00:00
} else if ( ipv6 [ 0 ] === 0x2002 ) {
2016-11-28 10:42:58 +00:00
// 6to4
output += "\n6to4 transition IPv6 address detected. See RFC 3056 for more details." +
"\n6to4 prefix range: 2002::/16" ;
var v4 _addr = IP . _ipv4 _to _str ( ( ipv6 [ 1 ] << 16 ) + ipv6 [ 2 ] ) ,
sla _id = ipv6 [ 3 ] ,
interface _id _str = ipv6 [ 4 ] . toString ( 16 ) + ipv6 [ 5 ] . toString ( 16 ) + ipv6 [ 6 ] . toString ( 16 ) + ipv6 [ 7 ] . toString ( 16 ) ,
interface _id = new BigInteger ( interface _id _str , 16 ) ;
output += "\n\nEncapsulated IPv4 address: " + v4 _addr +
"\nSLA ID: " + sla _id +
"\nInterface ID (base 16): " + interface _id _str +
"\nInterface ID (base 10): " + interface _id . toString ( ) ;
} else if ( ipv6 [ 0 ] >= 0xfc00 && ipv6 [ 0 ] <= 0xfdff ) {
// Unique local address
output += "\nThis is a unique local address comparable to the IPv4 private addresses 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16. See RFC 4193 for more details." ;
output += "\nUnique local addresses range: fc00::/7" ;
} else if ( ipv6 [ 0 ] >= 0xfe80 && ipv6 [ 0 ] <= 0xfebf ) {
// Link-local address
output += "\nThis is a link-local address comparable to the auto-configuration addresses 169.254.0.0/16 in IPv4." ;
output += "\nLink-local addresses range: fe80::/10" ;
} else if ( ipv6 [ 0 ] >= 0xff00 ) {
// Multicast
output += "\nThis is a reserved multicast address." ;
output += "\nMulticast addresses range: ff00::/8" ;
}
} else {
return "Invalid IPv6 address" ;
}
return output ;
} ,
/ * *
* @ constant
* @ default
* /
IP _FORMAT _LIST : [ "Dotted Decimal" , "Decimal" , "Hex" ] ,
/ * *
* Change IP format operation .
*
* @ param { string } input
* @ param { Object [ ] } args
* @ returns { string }
* /
run _change _ip _format : function ( input , args ) {
var in _format = args [ 0 ] ,
out _format = args [ 1 ] ,
lines = input . split ( "\n" ) ,
output = "" ,
j = 0 ;
for ( var i = 0 ; i < lines . length ; i ++ ) {
if ( lines [ i ] === "" ) continue ;
var ba _ip = [ ] ;
2016-12-14 16:39:17 +00:00
if ( in _format === out _format ) {
2016-11-28 10:42:58 +00:00
output += lines [ i ] + "\n" ;
continue ;
}
// Convert to byte array IP from input format
switch ( in _format ) {
case "Dotted Decimal" :
var octets = lines [ i ] . split ( "." ) ;
for ( j = 0 ; j < octets . length ; j ++ ) {
ba _ip . push ( parseInt ( octets [ j ] , 10 ) ) ;
}
break ;
case "Decimal" :
var decimal = lines [ i ] . toString ( ) ;
ba _ip . push ( decimal >> 24 & 255 ) ;
ba _ip . push ( decimal >> 16 & 255 ) ;
ba _ip . push ( decimal >> 8 & 255 ) ;
ba _ip . push ( decimal & 255 ) ;
break ;
case "Hex" :
ba _ip = Utils . hex _to _byte _array ( lines [ i ] ) ;
break ;
default :
throw "Unsupported input IP format" ;
}
// Convert byte array IP to output format
switch ( out _format ) {
case "Dotted Decimal" :
var dd _ip = "" ;
for ( j = 0 ; j < ba _ip . length ; j ++ ) {
dd _ip += ba _ip [ j ] + "." ;
}
output += dd _ip . slice ( 0 , dd _ip . length - 1 ) + "\n" ;
break ;
case "Decimal" :
var dec _ip = ( ( ba _ip [ 0 ] << 24 ) | ( ba _ip [ 1 ] << 16 ) | ( ba _ip [ 2 ] << 8 ) | ba _ip [ 3 ] ) >>> 0 ;
output += dec _ip . toString ( ) + "\n" ;
break ;
case "Hex" :
var hex _ip = "" ;
for ( j = 0 ; j < ba _ip . length ; j ++ ) {
hex _ip += Utils . hex ( ba _ip [ j ] ) ;
}
output += hex _ip + "\n" ;
break ;
default :
throw "Unsupported output IP format" ;
}
}
return output . slice ( 0 , output . length - 1 ) ;
} ,
/ * *
* @ constant
* @ default
* /
DELIM _OPTIONS : [ "Line feed" , "CRLF" , "Space" , "Comma" , "Semi-colon" ] ,
/ * *
* @ constant
* @ default
* /
GROUP _CIDR : 24 ,
/ * *
* @ constant
* @ default
* /
GROUP _ONLY _SUBNET : false ,
/ * *
* Group IP addresses operation .
*
* @ param { string } input
* @ param { Object [ ] } args
* @ returns { string }
* /
run _group _ips : function ( input , args ) {
var delim = Utils . char _rep [ args [ 0 ] ] ,
cidr = args [ 1 ] ,
only _subnets = args [ 2 ] ,
ipv4 _mask = cidr < 32 ? ~ ( 0xFFFFFFFF >>> cidr ) : 0xFFFFFFFF ,
ipv6 _mask = IP . _gen _ipv6 _mask ( cidr ) ,
ips = input . split ( delim ) ,
ipv4 _networks = { } ,
ipv6 _networks = { } ,
match = null ,
output = "" ,
ip = null ,
network = null ,
network _str = "" ;
if ( cidr < 0 || cidr > 127 ) {
return "CIDR must be less than 32 for IPv4 or 128 for IPv6" ;
}
// Parse all IPs and add to network dictionary
for ( var i = 0 ; i < ips . length ; i ++ ) {
2016-12-14 16:39:17 +00:00
if ( ( match = IP . IPv4 _REGEX . exec ( ips [ i ] ) ) ) {
2016-11-28 10:42:58 +00:00
ip = IP . _str _to _ipv4 ( match [ 1 ] ) >>> 0 ;
network = ip & ipv4 _mask ;
if ( ipv4 _networks . hasOwnProperty ( network ) ) {
ipv4 _networks [ network ] . push ( ip ) ;
} else {
ipv4 _networks [ network ] = [ ip ] ;
}
2016-12-14 16:39:17 +00:00
} else if ( ( match = IP . IPv6 _REGEX . exec ( ips [ i ] ) ) ) {
2016-11-28 10:42:58 +00:00
ip = IP . _str _to _ipv6 ( match [ 1 ] ) ;
network = [ ] ;
network _str = "" ;
for ( var j = 0 ; j < 8 ; j ++ ) {
network . push ( ip [ j ] & ipv6 _mask [ j ] ) ;
}
network _str = IP . _ipv6 _to _str ( network , true ) ;
if ( ipv6 _networks . hasOwnProperty ( network _str ) ) {
ipv6 _networks [ network _str ] . push ( ip ) ;
} else {
ipv6 _networks [ network _str ] = [ ip ] ;
}
}
}
// Sort IPv4 network dictionaries and print
for ( network in ipv4 _networks ) {
ipv4 _networks [ network ] = ipv4 _networks [ network ] . sort ( ) ;
output += IP . _ipv4 _to _str ( network ) + "/" + cidr + "\n" ;
if ( ! only _subnets ) {
for ( i = 0 ; i < ipv4 _networks [ network ] . length ; i ++ ) {
output += " " + IP . _ipv4 _to _str ( ipv4 _networks [ network ] [ i ] ) + "\n" ;
}
output += "\n" ;
}
}
// Sort IPv6 network dictionaries and print
for ( network _str in ipv6 _networks ) {
//ipv6_networks[network_str] = ipv6_networks[network_str].sort(); TODO
output += network _str + "/" + cidr + "\n" ;
if ( ! only _subnets ) {
for ( i = 0 ; i < ipv6 _networks [ network _str ] . length ; i ++ ) {
output += " " + IP . _ipv6 _to _str ( ipv6 _networks [ network _str ] [ i ] , true ) + "\n" ;
}
output += "\n" ;
}
}
return output ;
} ,
/ * *
* @ constant
* @ default
* @ private
* /
_LARGE _RANGE _ERROR : "The specified range contains more than 65,536 addresses. Running this query could crash your browser. If you want to run it, select the \"Allow large queries\" option. You are advised to turn off \"Auto Bake\" whilst editing large ranges." ,
/ * *
* Parses an IPv4 CIDR range ( e . g . 192.168 . 0.0 / 24 ) and displays information about it .
*
* @ private
* @ param { RegExp } cidr
* @ param { boolean } include _network _info
* @ param { boolean } enumerate _addresses
* @ param { boolean } allow _large _list
* @ returns { string }
* /
_ipv4 _cidr _range : function ( cidr , include _network _info , enumerate _addresses , allow _large _list ) {
var output = "" ,
network = IP . _str _to _ipv4 ( cidr [ 1 ] ) ,
cidr _range = parseInt ( cidr [ 2 ] , 10 ) ;
if ( cidr _range < 0 || cidr _range > 31 ) {
return "IPv4 CIDR must be less than 32" ;
}
var mask = ~ ( 0xFFFFFFFF >>> cidr _range ) ,
ip1 = network & mask ,
ip2 = ip1 | ~ mask ;
if ( include _network _info ) {
output += "Network: " + IP . _ipv4 _to _str ( network ) + "\n" ;
output += "CIDR: " + cidr _range + "\n" ;
output += "Mask: " + IP . _ipv4 _to _str ( mask ) + "\n" ;
output += "Range: " + IP . _ipv4 _to _str ( ip1 ) + " - " + IP . _ipv4 _to _str ( ip2 ) + "\n" ;
output += "Total addresses in range: " + ( ( ( ip2 - ip1 ) >>> 0 ) + 1 ) + "\n\n" ;
}
if ( enumerate _addresses ) {
if ( cidr _range >= 16 || allow _large _list ) {
output += IP . _generate _ipv4 _range ( ip1 , ip2 ) . join ( "\n" ) ;
} else {
output += IP . _LARGE _RANGE _ERROR ;
}
}
return output ;
} ,
/ * *
* Parses an IPv6 CIDR range ( e . g . ff00 : : / 4 8 ) a n d d i s p l a y s i n f o r m a t i o n a b o u t i t .
*
* @ private
* @ param { RegExp } cidr
* @ param { boolean } include _network _info
* @ returns { string }
* /
_ipv6 _cidr _range : function ( cidr , include _network _info ) {
var output = "" ,
network = IP . _str _to _ipv6 ( cidr [ 1 ] ) ,
cidr _range = parseInt ( cidr [ cidr . length - 1 ] , 10 ) ;
if ( cidr _range < 0 || cidr _range > 127 ) {
return "IPv6 CIDR must be less than 128" ;
}
var mask = IP . _gen _ipv6 _mask ( cidr _range ) ,
ip1 = new Array ( 8 ) ,
ip2 = new Array ( 8 ) ,
total _diff = "" ,
total = new Array ( 128 ) ;
for ( var i = 0 ; i < 8 ; i ++ ) {
ip1 [ i ] = network [ i ] & mask [ i ] ;
ip2 [ i ] = ip1 [ i ] | ( ~ mask [ i ] & 0x0000FFFF ) ;
total _diff = ( ip2 [ i ] - ip1 [ i ] ) . toString ( 2 ) ;
2016-12-14 16:39:17 +00:00
if ( total _diff !== "0" ) {
2016-11-28 10:42:58 +00:00
for ( var n = 0 ; n < total _diff . length ; n ++ ) {
total [ i * 16 + 16 - ( total _diff . length - n ) ] = total _diff [ n ] ;
}
}
}
if ( include _network _info ) {
output += "Network: " + IP . _ipv6 _to _str ( network ) + "\n" ;
output += "Shorthand: " + IP . _ipv6 _to _str ( network , true ) + "\n" ;
output += "CIDR: " + cidr _range + "\n" ;
output += "Mask: " + IP . _ipv6 _to _str ( mask ) + "\n" ;
output += "Range: " + IP . _ipv6 _to _str ( ip1 ) + " - " + IP . _ipv6 _to _str ( ip2 ) + "\n" ;
output += "Total addresses in range: " + ( parseInt ( total . join ( "" ) , 2 ) + 1 ) + "\n\n" ;
}
return output ;
} ,
/ * *
* Generates an IPv6 subnet mask given a CIDR value .
*
* @ private
* @ param { number } cidr
* @ returns { number [ ] }
* /
_gen _ipv6 _mask : function ( cidr ) {
var mask = new Array ( 8 ) ,
shift ;
for ( var i = 0 ; i < 8 ; i ++ ) {
if ( cidr > ( ( i + 1 ) * 16 ) ) {
mask [ i ] = 0x0000FFFF ;
} else {
shift = cidr - ( i * 16 ) ;
if ( shift < 0 ) shift = 0 ;
mask [ i ] = ~ ( ( 0x0000FFFF >>> shift ) | 0xFFFF0000 ) ;
}
}
return mask ;
} ,
/ * *
* Parses an IPv4 hyphenated range ( e . g . 192.168 . 0.0 - 192.168 . 0.255 ) and displays information
* about it .
*
* @ private
* @ param { RegExp } range
* @ param { boolean } include _network _info
* @ param { boolean } enumerate _addresses
* @ param { boolean } allow _large _list
* @ returns { string }
* /
_ipv4 _hyphenated _range : function ( range , include _network _info , enumerate _addresses , allow _large _list ) {
var output = "" ,
ip1 = IP . _str _to _ipv4 ( range [ 1 ] ) ,
ip2 = IP . _str _to _ipv4 ( range [ 2 ] ) ;
// Calculate mask
var diff = ip1 ^ ip2 ,
cidr = 32 ,
mask = 0 ;
while ( diff !== 0 ) {
diff >>= 1 ;
cidr -- ;
mask = ( mask << 1 ) | 1 ;
}
mask = ~ mask >>> 0 ;
var network = ip1 & mask ,
sub _ip1 = network & mask ,
sub _ip2 = sub _ip1 | ~ mask ;
if ( include _network _info ) {
output += "Minimum subnet required to hold this range:\n" ;
output += "\tNetwork: " + IP . _ipv4 _to _str ( network ) + "\n" ;
output += "\tCIDR: " + cidr + "\n" ;
output += "\tMask: " + IP . _ipv4 _to _str ( mask ) + "\n" ;
output += "\tSubnet range: " + IP . _ipv4 _to _str ( sub _ip1 ) + " - " + IP . _ipv4 _to _str ( sub _ip2 ) + "\n" ;
output += "\tTotal addresses in subnet: " + ( ( ( sub _ip2 - sub _ip1 ) >>> 0 ) + 1 ) + "\n\n" ;
output += "Range: " + IP . _ipv4 _to _str ( ip1 ) + " - " + IP . _ipv4 _to _str ( ip2 ) + "\n" ;
output += "Total addresses in range: " + ( ( ( ip2 - ip1 ) >>> 0 ) + 1 ) + "\n\n" ;
}
if ( enumerate _addresses ) {
if ( ( ( ip2 - ip1 ) >>> 0 ) <= 65536 || allow _large _list ) {
output += IP . _generate _ipv4 _range ( ip1 , ip2 ) . join ( "\n" ) ;
} else {
output += IP . _LARGE _RANGE _ERROR ;
}
}
return output ;
} ,
/ * *
* Parses an IPv6 hyphenated range ( e . g . ff00 : : - ffff : : ) and displays information about it .
*
* @ private
* @ param { RegExp } range
* @ param { boolean } include _network _info
* @ returns { string }
* /
_ipv6 _hyphenated _range : function ( range , include _network _info ) {
var output = "" ,
ip1 = IP . _str _to _ipv6 ( range [ 1 ] ) ,
ip2 = IP . _str _to _ipv6 ( range [ 14 ] ) ;
var t = "" ,
total = new Array ( 128 ) ;
// Initialise total array to "0"
for ( var i = 0 ; i < 128 ; i ++ )
total [ i ] = "0" ;
for ( i = 0 ; i < 8 ; i ++ ) {
t = ( ip2 [ i ] - ip1 [ i ] ) . toString ( 2 ) ;
2016-12-14 16:39:17 +00:00
if ( t !== "0" ) {
2016-11-28 10:42:58 +00:00
for ( var n = 0 ; n < t . length ; n ++ ) {
total [ i * 16 + 16 - ( t . length - n ) ] = t [ n ] ;
}
}
}
if ( include _network _info ) {
output += "Range: " + IP . _ipv6 _to _str ( ip1 ) + " - " + IP . _ipv6 _to _str ( ip2 ) + "\n" ;
output += "Shorthand range: " + IP . _ipv6 _to _str ( ip1 , true ) + " - " + IP . _ipv6 _to _str ( ip2 , true ) + "\n" ;
output += "Total addresses in range: " + ( parseInt ( total . join ( "" ) , 2 ) + 1 ) + "\n\n" ;
}
return output ;
} ,
/ * *
* Converts an IPv4 address from string format to numerical format .
*
* @ private
* @ param { string } ip _str
* @ returns { number }
*
* @ example
* // returns 168427520
* IP . _str _to _ipv4 ( "10.10.0.0" ) ;
* /
_str _to _ipv4 : function ( ip _str ) {
var blocks = ip _str . split ( "." ) ,
num _blocks = parse _blocks ( blocks ) ,
result = 0 ;
result += num _blocks [ 0 ] << 24 ;
result += num _blocks [ 1 ] << 16 ;
result += num _blocks [ 2 ] << 8 ;
result += num _blocks [ 3 ] ;
return result ;
function parse _blocks ( blocks ) {
2016-12-14 16:39:17 +00:00
if ( blocks . length !== 4 )
2016-11-28 10:42:58 +00:00
throw "More than 4 blocks." ;
var num _blocks = [ ] ;
for ( var i = 0 ; i < 4 ; i ++ ) {
num _blocks [ i ] = parseInt ( blocks [ i ] , 10 ) ;
if ( num _blocks [ i ] < 0 || num _blocks [ i ] > 255 )
throw "Block out of range." ;
}
return num _blocks ;
}
} ,
/ * *
* Converts an IPv4 address from numerical format to string format .
*
* @ private
* @ param { number } ip _int
* @ returns { string }
*
* @ example
* // returns "10.10.0.0"
* IP . _ipv4 _to _str ( 168427520 ) ;
* /
_ipv4 _to _str : function ( ip _int ) {
var blockA = ( ip _int >> 24 ) & 255 ,
blockB = ( ip _int >> 16 ) & 255 ,
blockC = ( ip _int >> 8 ) & 255 ,
blockD = ip _int & 255 ;
return blockA + "." + blockB + "." + blockC + "." + blockD ;
} ,
/ * *
* Converts an IPv6 address from string format to numerical array format .
*
* @ private
* @ param { string } ip _str
* @ returns { number [ ] }
*
* @ example
* // returns [65280, 0, 0, 0, 0, 0, 4369, 8738]
* IP . _str _to _ipv6 ( "ff00::1111:2222" ) ;
* /
_str _to _ipv6 : function ( ip _str ) {
var blocks = ip _str . split ( ":" ) ,
num _blocks = parse _blocks ( blocks ) ,
j = 0 ,
ipv6 = new Array ( 8 ) ;
for ( var i = 0 ; i < 8 ; i ++ ) {
if ( isNaN ( num _blocks [ j ] ) ) {
ipv6 [ i ] = 0 ;
2016-12-14 16:39:17 +00:00
if ( i === ( 8 - num _blocks . slice ( j ) . length ) ) j ++ ;
2016-11-28 10:42:58 +00:00
} else {
ipv6 [ i ] = num _blocks [ j ] ;
j ++ ;
}
}
return ipv6 ;
function parse _blocks ( blocks ) {
if ( blocks . length < 3 || blocks . length > 8 )
throw "Badly formatted IPv6 address." ;
var num _blocks = [ ] ;
for ( var i = 0 ; i < blocks . length ; i ++ ) {
num _blocks [ i ] = parseInt ( blocks [ i ] , 16 ) ;
if ( num _blocks [ i ] < 0 || num _blocks [ i ] > 65535 )
throw "Block out of range." ;
}
return num _blocks ;
}
} ,
/ * *
* Converts an IPv6 address from numerical array format to string format .
*
* @ private
* @ param { number [ ] } ipv6
* @ param { boolean } compact - Whether or not to return the address in shorthand or not
* @ returns { string }
*
* @ example
* // returns "ff00::1111:2222"
* IP . _ipv6 _to _str ( [ 65280 , 0 , 0 , 0 , 0 , 0 , 4369 , 8738 ] , true ) ;
*
* // returns "ff00:0000:0000:0000:0000:0000:1111:2222"
* IP . _ipv6 _to _str ( [ 65280 , 0 , 0 , 0 , 0 , 0 , 4369 , 8738 ] , false ) ;
* /
_ipv6 _to _str : function ( ipv6 , compact ) {
var output = "" ,
i = 0 ;
if ( compact ) {
var start = - 1 ,
end = - 1 ,
s = 0 ,
e = - 1 ;
for ( i = 0 ; i < 8 ; i ++ ) {
if ( ipv6 [ i ] === 0 && e === ( i - 1 ) ) {
e = i ;
} else if ( ipv6 [ i ] === 0 ) {
s = i ; e = i ;
}
if ( e >= 0 && ( e - s ) > ( end - start ) ) {
start = s ;
end = e ;
}
}
for ( i = 0 ; i < 8 ; i ++ ) {
2016-12-14 16:39:17 +00:00
if ( i !== start ) {
output += Utils . hex ( ipv6 [ i ] , 1 ) + ":" ;
2016-11-28 10:42:58 +00:00
} else {
output += ":" ;
i = end ;
if ( end === 7 ) output += ":" ;
}
}
if ( output [ 0 ] === ":" )
output = ":" + output ;
} else {
for ( i = 0 ; i < 8 ; i ++ ) {
2016-12-14 16:39:17 +00:00
output += Utils . hex ( ipv6 [ i ] , 4 ) + ":" ;
2016-11-28 10:42:58 +00:00
}
}
2016-12-14 16:39:17 +00:00
return output . slice ( 0 , output . length - 1 ) ;
2016-11-28 10:42:58 +00:00
} ,
/ * *
* Generates a list of IPv4 addresses in string format between two given numerical values .
*
* @ private
* @ param { number } ip
* @ param { number } end _ip
* @ returns { string [ ] }
*
* @ example
* // returns ["0.0.0.1", "0.0.0.2", "0.0.0.3"]
* IP . _generate _ipv4 _range ( 1 , 3 ) ;
* /
_generate _ipv4 _range : function ( ip , end _ip ) {
var range = [ ] ;
if ( end _ip >= ip ) {
for ( ; ip <= end _ip ; ip ++ ) {
range . push ( IP . _ipv4 _to _str ( ip ) ) ;
}
} else {
range [ 0 ] = "Second IP address smaller than first." ;
}
return range ;
} ,
} ;