ipaddr icon indicating copy to clipboard operation
ipaddr copied to clipboard

Enhancement: add constants for IPv4 and IPv6 subnet masks

Open MatzFan opened this issue 8 months ago • 0 comments

Rationale: This SO question demonstrates there is at least some need to manipulate netmasks into CIDR integers. The accepted answer contains a bug which can be easily eliminated by hard coding the 2 sets of netmasks into the IPAddr class - see my alternative answer.

Proposed solution: Define IPAddr::IPV4_SUBNET_MASKS and IPAddr::IPV6_SUBNET_MASKS as follows:

class IPAddr
  IPV4_SUBNET_MASKS = (0..32).map { |n| IPAddr.new("0.0.0.0/#{n}").netmask }
  IPV6_SUBNET_MASKS = (0..128).map { |n| IPAddr.new("0::/#{n}").netmask }
end

# Now a user can do the following to get a subnet mask from a CIDR integer:
IPAddr::IPV4_SUBNET_MASKS[24]
# => "255.255.255.0"

IPAddr::IPV6_SUBNET_MASKS[64]
# => "ffff:ffff:ffff:ffff:0000:0000:0000:0000"

Optional: Add a predicate to check if an instance of IPAddr is a netmask:

class IPAddr
  def netmask?
    if ipv4?
      IPV4_SUBNET_MASKS.include? to_s
    else
      IPV6_SUBNET_MASKS.include? to_s
    end
  end
end

ipaddr1 = IPAddr.new '255.254.255.0'
ipaddr1.netmask? # => false

ipaddr2 = IPAddr.new '255.255.255.0/24'
ipaddr2.netmask? # => true

ipaddr3 = IPAddr.new '255.255.255.0'
ipaddr3.netmask? # => true

# And so on for IPv6 addresses

MatzFan avatar Apr 21 '25 08:04 MatzFan