Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if IP is in subnet

Tags:

mysql

ip

subnet

I have a table A with IP addresses (ipNumeric) stored as unsigned ints and a table B with subnets (subnetNumeric):

INET_NTOA(ipNumeric) = 192.168.0.1
INET_NTOA(subnetNumeric) = 192.168.0.0

I'd like to check if this IP is a member of a subnet.

The subnets are Class A, B and C.

Is this possible to do in reasonable time in MySQL on the fly or should the subnet ranges be precomputed?

like image 612
matiasf Avatar asked Apr 03 '12 21:04

matiasf


People also ask

Can we find IP address from subnet mask?

You can determine the number and type of IP addresses any given local network requires based on its default subnet mask. An example of Class A IP address and subnet mask would be the Class A default submask of 255.0. 0.0 and an IP address of 10.20. 12.2.

How do I know if my IP is in the CIDR range?

IP Address In CIDR Range Check Please enter a valid IP Address in IPv4 format and CIDR notation range to check if it belongs to it. For example: enter IP address 192.168. 0.1 and for CIDR range 192.168. 0.0/24 to test it.

How do I find the subnet of a company's IP?

How to identify a company's public network address range. One of the most traditional ways to get the IP address of a company is to use the ping command, which allows you to get the main IP address of the webserver behind the webpage.


2 Answers

Sure, it's doable. The idea is that we calculate the subnet mask by setting the most significant bits to 1, as many as dictated by the subnet class. For a class C, that would be

SELECT -1 << 8;

Then, AND the subnet mask with the IP address you have; if the IP is inside the subnet, the result should be equal to the subnet address -- standard networking stuff. So we end up with:

SELECT (-1 << 8) & INET_ATON("192.168.0.1") = INET_ATON("192.168.0.0");

Update: Yes, it is necessary to know the network class or the subnet mask (which is equivalent information). Consider how could you handle the case where the subnet is X.Y.0.0 if you did not have this information. Is this X.Y.0.0/16 or X.Y.0.0/8 where the third octet just happens to be 0? No way to know.

If you do know the subnet mask, then the query can be written as

SELECT (-1 << (33 - INSTR(BIN(INET_ATON("255.255.255.0")), "0"))) &
       INET_ATON("192.168.0.1") = INET_ATON("192.168.0.0");
like image 190
Jon Avatar answered Oct 17 '22 08:10

Jon


This is the MySQL function we use.

DELIMITER $$
DROP FUNCTION IF EXISTS `ip_in_subnet_mask`$$
CREATE DEFINER=`root`@`%` FUNCTION `ip_in_subnet_mask`(ip VARCHAR(20), subnet VARCHAR(20), netmask VARCHAR(20)) RETURNS TINYINT(1)
    DETERMINISTIC
BEGIN
    RETURN (INET_ATON(ip) & INET_ATON(netmask)) = INET_ATON(subnet);
END$$
DELIMITER ;

e.g. Find all the rows where t.ip is in the range 192.168.0.x where 0<=x<=255

 SELECT *
 FROM t
 WHERE
    ip_in_subnet_mask(t.ip, "192.168.0.0", "255.255.255.0")
like image 31
Martin Avatar answered Oct 17 '22 09:10

Martin