Netmask to Cidr in Ruby

Netmask to CIDR in ruby

Here is the quick and dirty way

require 'ipaddr'
puts IPAddr.new("255.255.255.0").to_i.to_s(2).count("1")

There should be proper function for that, I couldn't find that, so I just count "1"

If you're going to be using the function in a number of places and don't mind monkeypatching, this could help:

IPAddr.class_eval
def to_cidr
"/" + self.to_i.to_s(2).count("1")
end
end

Then you get

IPAddr.new('255.255.255.0').to_cidr
# => "/24"

IP Range to CIDR in Ruby/Rails?

Well, to get the CIDR notation of a range, you need an IP and the number of network bits (calculated from the netmask).

To enumerate the addresses of a given range, you can use the NetAddr (< 2.x) gem.

p NetAddr::CIDR.create('192.168.1.0/24').enumerate
=> ['192.168.1.0', '192.168.1.1', '192.168.1.2'... '192.168.1.255']

You can also calculate the bits from the netmask on the fly:

mask_int = NetAddr.netmask_to_i('255.255.255.0')
p NetAddr.mask_to_bits(mask_int)
=> 24

And to create a range based on two IPs:

lower = NetAddr::CIDR.create('192.168.1.1')
upper = NetAddr::CIDR.create('192.168.1.10')
p NetAddr.range(lower, upper)
=> ['192.168.1.2', '192.168.1.3'... '192.168.1.9']

So now that you can create a CIDR range, you can check to see if an IP is a part of it:

cidr = NetAddr::CIDR.create('192.168.1.0/24')
p cidr.contains?('192.168.1.10')
=> true

Ruby IPAddr: find address mask

Some parts of the Ruby core library are sometimes just sketched in, and IPAddr appears to be one of those that is, unfortunately, a little bit incomplete.

Not to worry. You can fix this with a simple monkey-patch:

class IPAddr
def cidr_mask
case (@family)
when Socket::AF_INET
32 - Math.log2((1<<32) - @mask_addr).to_i
when Socket::AF_INET6
128 - Math.log2((1<<128) - @mask_addr).to_i
else
raise AddressFamilyError, "unsupported address family"
end
end
end

That should handle IPv4 and IPv6 addresses:

IPAddr.new('151.101.65.69').cidr_mask
# => 32

IPAddr.new('151.101.65.69/26').cidr_mask
# => 26

IPAddr.new('151.101.65.69/255.255.255.0').cidr_mask
# => 24

IPAddr.new('2607:f8b0:4006:800::200e').cidr_mask
# => 128

IPAddr.new('2607:f8b0:4006:800::200e/100').cidr_mask
# => 100

It's not necessarily the best solution here, but it works.

Rails how to validate subnet mask before ip range calculation

ruby ipaddr

require 'ipaddr'
net1 = IPAddr.new("192.168.2.0/24")
net2 = IPAddr.new("192.168.2.100")
net3 = IPAddr.new("192.168.3.0")
p net1.include?(net2) #=> true
p net1.include?(net3) #=> false

NetAddr::Tree take list of CIDR and merge them?

Have you taken a look at NetAddr::merge?

From the docs:

Given a list of CIDR addresses or NetAddr::CIDR objects, merge (summarize) them in the most efficient way possible. Summarization will only occur when the newly created supernets will not result in the ‘creation’ of new IP space. For example the following blocks (192.168.0.0/24, 192.168.1.0/24, and 192.168.2.0/24) would be summarized into 192.168.0.0/23 and 192.168.2.0/24 rather than into 192.168.0.0/22

require 'netaddr'
require 'pp'

pp NetAddr.merge(
%w[
12.26.8.0/21
12.26.16.0/21
12.26.24.0/21
12.26.32.0/21
12.26.40.0/21
12.27.152.0/21
].map{ |ip| NetAddr::CIDR.create(ip) }
)

=> ["12.26.8.0/21", "12.26.16.0/20", "12.26.32.0/20", "12.27.152.0/21"]

Find out if an IP is within a range of IPs

>> require "ipaddr"
=> true
>> low = IPAddr.new("62.0.0.0").to_i
=> 1040187392
>> high = IPAddr.new("62.255.255.255").to_i
=> 1056964607
>> ip = IPAddr.new("62.156.244.13").to_i
=> 1050473485
>> (low..high)===ip
=> true

If you are given the network instead of the start and end addresses, it is even simpler

>> net = IPAddr.new("62.0.0.0/8")
=> #<IPAddr: IPv4:62.0.0.0/255.0.0.0>
>> net===IPAddr.new("62.156.244.13")
=> true

IPAddr will also work with IPv6 addresses

>> low = IPAddr.new('1::')
=> #<IPAddr: IPv6:0001:0000:0000:0000:0000:0000:0000:0000/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>
>> high = IPAddr.new('2::')
=> #<IPAddr: IPv6:0002:0000:0000:0000:0000:0000:0000:0000/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>
>> (low..high)===IPAddr.new('1::1')
=> true

convert ipv4 netmask to cidr format

The complicated way would be to convert the netmask to binary and count the number of leading 1 bits. But since there are only 33 possible values, a simpler way is just an associative array:

$netmask_to_cidr = array(
'255.255.255.255' => 32,
'255.255.255.254' => 31,
'255.255.255.252' => 30,
...
'128.0.0.0' => 1,
'0.0.0.0' => 0);


Related Topics



Leave a reply



Submit