I have an application where I process a lot of IP addresses (analysing Checkpoint firewall rule sets). At one point I want to check if a particular address object is a /32 or a 'network'.
Currently I am doing it like this:
next unless ip.inspect.match(/\/255\.255\.255\.255/)
it works but seems a bit inefficient but I can't see any method that extracts the mask from the address object.
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.