I'd like to write a function in Javascript along the lines of:
in_subnet(ip, network, slash) {
...
}
in_subnet('1.2.3.4', '1.2.0.0', 16) # True, since it's in 1.2.0.0/16
in_subnet('1.2.3.4', '1.2.0.0', 24) # False, since it's not in 1.2.0.0/24
Should I write it from scratch, or are there some good libraries I could use? Or is the entire function already written and in the public domain?
I'd like to write a function in Javascript along the lines of:
in_subnet(ip, network, slash) {
...
}
in_subnet('1.2.3.4', '1.2.0.0', 16) # True, since it's in 1.2.0.0/16
in_subnet('1.2.3.4', '1.2.0.0', 24) # False, since it's not in 1.2.0.0/24
Should I write it from scratch, or are there some good libraries I could use? Or is the entire function already written and in the public domain?
Share Improve this question edited Jul 9, 2014 at 6:14 latonz 1,75010 silver badges21 bronze badges asked Dec 31, 2008 at 5:06 MikeMike4 Answers
Reset to default 4Pseudocode, building on dustin's answer:
addr_one = ip_addr_to_integer(ip);
addr_two = ip_addr_to_integer(network);
mask = ((1 << (32-slash)) - 1) ^ 0xFFFFFFFF;
return (((addr_one ^ addr_two) & mask) == 0);
If you know that the IP address strings are valid, you can probably use string.split('.') to get the four octets and easily convert them to an integer.
Go ahead and learn it. :)
The trick is to parse '1.2.3.4' into a single integer ( (1 << 24 | 2 << 16 | 3 << 8 | 4) == 16909060), and then '1.2.0.0' as an integer (16908288) and then the mask as the number of 1 bits from the msb as an integer (16 bits == 4294901760) and then apply the mask with bitwise and to the original address ((16909060 & 4294901760) == 16908288) if the masked address == the network address, then it's in the network.
addr_one = ip_addr_to_integer(ip >> (32 - slash));
addr_two = ip_addr_to_integer(network >> (32 - slash));
return (addr_one == addr_two);
Bitwise operators stop working with 32 bits.
function in_subnet(ip, subnet) {
let chunks = subnet.split('/')
let network = chunks[0]
let slash = Number(chunks[1])
addr_one = ip_addr_to_integer(ip) >> (32 - slash);
addr_two = ip_addr_to_integer(network) >> (32 - slash);
return (addr_one === addr_two);
}
function ip_addr_to_integer(ip) {
let chunks = ip.split('.')
let sum =
chunks[0] << 24
chunks[1] << 16
chunks[2] << 8
chunks[3]
return sum
}
This code does no input sanitation.
Use it like:
if (in_subnet('127.0.0.1', '127.0.0.0/8')) {
console.log('127.0.0.1 is in 127.0.0.0/8.')
} else {
console.log('Address is not in subnet.')
}
if (in_subnet('10.0.11.0', '10.0.10.0/24')) {
console.log('Address is in subnet.')
} else {
console.log('10.0.11.0 is not in 10.0.10.0/24.')
}
output:
127.0.0.1 is in 127.0.0.0/8.
10.0.11.0 is not in 10.0.10.0/24.
Based on answers by user1951756 and Dustin