Using JavaScript how would I validate an IP address "x.x.x.x" is a valid IPV4 unicast address e.g. is not 0.0.0.0 or multicast (224.0.0.0 to 224.0.0.255, 224.0.1.0 to 238.255.255.255, 239.0.0.0 to 239.255.255.255)?
Using JavaScript how would I validate an IP address "x.x.x.x" is a valid IPV4 unicast address e.g. is not 0.0.0.0 or multicast (224.0.0.0 to 224.0.0.255, 224.0.1.0 to 238.255.255.255, 239.0.0.0 to 239.255.255.255)?
Share Improve this question asked Oct 1, 2009 at 13:17 AndrewAndrew 3171 gold badge6 silver badges11 bronze badges 04 Answers
Reset to default 7First you need to get it into a number, use this function:-
function IPToNumber(s)
{
var arr = s.split(".");
var n = 0
for (var i = 0; i < 4; i++)
{
n = n * 256
n += parseInt(arr[i],10)
}
return n;
}
Looking at you spec, whilst you seem to list a series of ranges those ranges appear to be contiguous to me, that is can be simplified to (224.0.0.0 to 239.255.255.255). Hence you can test with:-
var min = IPToNumber("224.0.0.0");
var max = IPToNumber("239.255.255.255");
var ipNum = IPToNumber(sTestIP);
var isValid = (ipNum != 0 && (ipNum < min || ipNum > max))
Note of course that without knowledge of the destinations subnet you can't tell whether the address is the network address or the broadcast address for that subnet.
The dotted quad notation you're seeing is just that: a notation that makes it easier on human eyes. An IP Address is really a 32 bit integer. I suggest you convert your address to that integer and then just check that it's in a valid range (ie, > 0 for the first requirement).
To that end:
function dottedQuadToInt(ip)
{
var parts = ip.split('.', 4);
if(parts.length < 4) return -1;
var result = 0, base = 1;
for (var i = 3;i>=0;i--)
{
//validation
if (parts[i].length == 0 || parts[i].length > 3) return -1;
var segment = parseInt(parts[i],10);
if (isNaN(segment) || segment<0 || segment > 255) return -1;
//pute next segment
result += base * segment;
base = base << 8;
}
return result;
}
and then:
function isValidIP(ip)
{
ip = dottedQuadToInt(ip);
if (ip <= 0) return false;
//mulitcast range:
if (ip >= 3758096384 && ip <= 4026531839) return false;
//alternate way to check multicast (slower, but more readable):
if (ip >= dottedQuadToInt('224.0.0.0') && ip <= dottedQuadToInt('239.255.255.255')) return false;
return true;
}
Multicast IP addresses are defined as those with 1110
as their high-order four bits (see http://www.iana/assignments/multicast-addresses/multicast-addresses.xhtml and https://www.rfc-editor/rfc/rfc1112). In hex the 1110
is expressed as 0xE
(decimal value of 14, remember each hex digit is worth 4 binary bits) so if this value is in the high order 4 bits of 32 bit integer (big endian) the hex would be 0xE0000000
. If you first convert the IP address to a 32 bit number and then &
it with 0xF0000000
, if the resulting value is equal to 0xE0000000
(1110
in the high-order four bits) then it is a multicast IPv4 address (same logic used in Java Inet4Address.isMulticastAddress()).
var ipNum = IPToNumber(sTestIP);
var isMulticast = ((ipNum & 0xF0000000) == 0xE0000000);
Here is a table to prove the point (notice that valid mutlicast IP addresses in hex format all start with 0xE
, also the int values are signed 32 bit numbers):
// not a multicast, starts with 0xD
ip [223.000.000.000] hex [0xDF000000] int [-553648128] unsigned [3741319168]
ip [223.255.255.255] hex [0xDFFFFFFF] int [-536870913] unsigned [3758096383]
// is a multicast, starts with 0xE
ip [224.000.000.000] hex [0xE0000000] int [-536870912] unsigned [3758096384]
ip [224.255.255.255] hex [0xE0FFFFFF] int [-520093697] unsigned [3774873599]
ip [225.000.000.000] hex [0xE1000000] int [-520093696] unsigned [3774873600]
ip [225.255.255.255] hex [0xE1FFFFFF] int [-503316481] unsigned [3791650815]
ip [226.000.000.000] hex [0xE2000000] int [-503316480] unsigned [3791650816]
ip [226.255.255.255] hex [0xE2FFFFFF] int [-486539265] unsigned [3808428031]
ip [227.000.000.000] hex [0xE3000000] int [-486539264] unsigned [3808428032]
ip [227.255.255.255] hex [0xE3FFFFFF] int [-469762049] unsigned [3825205247]
ip [228.000.000.000] hex [0xE4000000] int [-469762048] unsigned [3825205248]
ip [228.255.255.255] hex [0xE4FFFFFF] int [-452984833] unsigned [3841982463]
ip [229.000.000.000] hex [0xE5000000] int [-452984832] unsigned [3841982464]
ip [229.255.255.255] hex [0xE5FFFFFF] int [-436207617] unsigned [3858759679]
ip [230.000.000.000] hex [0xE6000000] int [-436207616] unsigned [3858759680]
ip [230.255.255.255] hex [0xE6FFFFFF] int [-419430401] unsigned [3875536895]
ip [231.000.000.000] hex [0xE7000000] int [-419430400] unsigned [3875536896]
ip [231.255.255.255] hex [0xE7FFFFFF] int [-402653185] unsigned [3892314111]
ip [232.000.000.000] hex [0xE8000000] int [-402653184] unsigned [3892314112]
ip [232.255.255.255] hex [0xE8FFFFFF] int [-385875969] unsigned [3909091327]
ip [233.000.000.000] hex [0xE9000000] int [-385875968] unsigned [3909091328]
ip [233.255.255.255] hex [0xE9FFFFFF] int [-369098753] unsigned [3925868543]
ip [234.000.000.000] hex [0xEA000000] int [-369098752] unsigned [3925868544]
ip [234.255.255.255] hex [0xEAFFFFFF] int [-352321537] unsigned [3942645759]
ip [235.000.000.000] hex [0xEB000000] int [-352321536] unsigned [3942645760]
ip [235.255.255.255] hex [0xEBFFFFFF] int [-335544321] unsigned [3959422975]
ip [236.000.000.000] hex [0xEC000000] int [-335544320] unsigned [3959422976]
ip [236.255.255.255] hex [0xECFFFFFF] int [-318767105] unsigned [3976200191]
ip [237.000.000.000] hex [0xED000000] int [-318767104] unsigned [3976200192]
ip [237.255.255.255] hex [0xEDFFFFFF] int [-301989889] unsigned [3992977407]
ip [238.000.000.000] hex [0xEE000000] int [-301989888] unsigned [3992977408]
ip [238.255.255.255] hex [0xEEFFFFFF] int [-285212673] unsigned [4009754623]
ip [239.000.000.000] hex [0xEF000000] int [-285212672] unsigned [4009754624]
ip [239.255.255.255] hex [0xEFFFFFFF] int [-268435457] unsigned [4026531839]
// not a multicast, starts with 0xF
ip [240.000.000.000] hex [0xF0000000] int [-268435456] unsigned [4026531840]
ip [240.255.255.255] hex [0xF0FFFFFF] int [-251658241] unsigned [4043309055]
/**
* Converts an IPv4 address to a (signed) 32-bit integer.
*/
function parse_ipv4_address(str) {
var arr = str.split('.');
for (var i = 0, val = 0; i < 4; i++) {
val += parseInt(arr[i], 10) << (8 * (3 - i));
}
return val;
}
var min = parse_ipv4_address('224.0.0.0');
var max = parse_ipv4_address('239.255.255.255');
var myIp = parse_ipv4_address(myIpStr);
// because the values are signed ints, min and max will be
// negative and we need to reverse the parison operators :(
if (myIp == 0 || (myIp <= min && myIp >= max)) {
// multicast!
}