JavaScript: Is IP In One Of These Subnets?

Steve picture Steve · Feb 2, 2009 · Viewed 18.8k times · Source

So I have ~12600 subnets:

eg. 123.123.208.0/20

and an IP.

I can use a SQLite Database or an array or whatever

There was a similar question asked about a month ago, however I am not looking for checking one IP against one subnet but a bunch of subnets (obviously the most efficient way, hopefully not O(total subnets)) :)

How can I check that the IP is one of in one of these subnets, I need true or false not the subnet if that helps optimisation.

There are similar subnets in the current list eg.: (actual extract)

123.123.48.0/22 <-- not a typo
123.123.48.0/24 <-- not a typo
123.123.90.0/24
123.123.91.0/24
123.123.217.0/24

In total they range from 4.x.y.z to 222.x.y.z

Answer

bart picture bart · Feb 2, 2009

The best approach is IMO making use of bitwise operators. For example, 123.123.48.0/22 represents (123<<24)+(123<<16)+(48<<8)+0 (=2071670784; this might be a negative number) as a 32 bit numeric IP address, and -1<<(32-22) = -1024 as a mask. With this, and likewise, your test IP address converted to a number, you can do:

(inputIP & testMask) == testIP

For example, 123.123.49.123 is in that range, as 2071671163 & -1024 is 2071670784

So, here are some tool functions:

function IPnumber(IPaddress) {
    var ip = IPaddress.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
    if(ip) {
        return (+ip[1]<<24) + (+ip[2]<<16) + (+ip[3]<<8) + (+ip[4]);
    }
    // else ... ?
    return null;
}

function IPmask(maskSize) {
    return -1<<(32-maskSize)
}

test:

(IPnumber('123.123.49.123') & IPmask('22')) == IPnumber('123.123.48.0')

yields true.

In case your mask is in the format '255.255.252.0', then you can use the IPnumber function for the mask, too.