Mike
Mike

Reputation:

How do I detect whether a given IP is in a given subnet in Javascript?

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?

Upvotes: 3

Views: 3717

Answers (4)

JGantts
JGantts

Reputation: 1

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

Upvotes: 0

user1951756
user1951756

Reputation: 511

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.

Upvotes: 0

Artelius
Artelius

Reputation: 49089

Pseudocode, 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.

Upvotes: 4

Dustin
Dustin

Reputation: 90980

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.

Upvotes: 1

Related Questions