Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using SQL to determine cidr value of a subnet mask

I'd like to find a way to do a SQL query that will calculate the cidr (bit representation) of a subnet mask stored in the database. So for example, I've got either 255.255.255.0 or its decimal value (4294967040) stored in the database. I'd like to do a select and get back /24 representation via the query.

I've done things like the following to determine the last IP of a subnet so I'm hoping to do something similar to determine the cidr representation of a mask.

select concat(inet_ntoa(ip_addr),'-',
    inet_ntoa(ip_addr+(POWER(2,32)-ip_mask-1))) range 
from subnets 
order by ip_addr

Preferably this would be a SQL statement that would work under mysql, postgres, oracle etc.

like image 748
Matt P Avatar asked Nov 10 '08 22:11

Matt P


People also ask

How do you find the CIDR of a subnet mask?

The CIDR number comes from the number of ones in the subnet mask when converted to binary. The subnet mask 255.255. 255.0 is 11111111.11111111. 11111111.00000000 in binary.

How do I find my CIDR from my network address?

The CIDR number is typically preceded by a slash “/” and follows the IP address. For example, an IP address of 131.10. 55.70 with a subnet mask of 255.0. 0.0 (which has 8 network bits) would be represented as 131.10.

How is CIDR format calculated?

How many addresses does a CIDR block represent? You calculate 2 32-prefix , where prefix is the number after the slash. For example, /29 contains 232-29=23=8 addresses. Here's a quick table that you can reference for the most CIDR blocks.

What is CIDR subnet mask?

CIDR notation is really just shorthand for the subnet mask, and represents the number of bits available to the IP address. For instance, the /24 in 192.168.0.101/24 is equivalent to the IP address 192.168.0.101 and the subnet mask 255.255.255.0 .


2 Answers

e.g. you need to convert 255.255.255.252 netmask into bit mask.

I always use this simple query (PostgreSQL) :

SELECT 32-length(trim(((split_part('255.255.255.252','.',1)::bigint*(256^3)::bigint +
                        split_part('255.255.255.252','.',2)::bigint*(256^2)::bigint +
                        split_part('255.255.255.252','.',3)::bigint*256 +
                        split_part('255.255.255.252','.',4)::bigint)::bit(32))::text,'1'));

not as nice as could be, but it's short and working like a charm..

like image 98
Michael Kaška Avatar answered Oct 05 '22 13:10

Michael Kaška


I think I have found the solution to my issue. Here is what I have done:

select CONCAT(INET_NTOA(ip_addr),'/',32-log2((4294967296-ip_mask))) net 
from subnets 
order by ip_addr

Basically I take my decmial mask and subtract it from the maximum decimal value. I then to a log2 on that value to get the logarithm value. Then simply subtract that from 32 (the maximum bit available).

Hope that helps others.

Thanks

like image 43
Matt P Avatar answered Oct 05 '22 14:10

Matt P