IPAddr#== implements wrong logic
IPAddr#== should implement the logic of comparison of two IPAddr instances. This generally means that it compares two IP addresses.
Lets look at the code of this method:
return @family == other.family && @addr == other.to_i
It returns the result of comparison of the families and the addresses, but it should also compare the netmask which describes the network where this address is located.
The code below shows the test case for this comparison:
ip1 = IPAddr.new '188.8.131.52/24'
ip2 = IPAddr.new '184.108.40.206/26'
ip1 == ip2 #=> true
This code shows that two identical IP addresses from different networks are equal. But the result should be
false because these addresses are not identical.
Depending on Feature #11210 i would propose following implementation of this method:
other = coerce_other(other)
return @family == other.family && @addr == other.to_i && @mask_addr == other.netmask
Updated by bjmllr (Ben Miller) almost 3 years ago
it does not consider a difference in netmasks as significant
IPAddr.new isn't consistent with this principle:
IPAddr.new("220.127.116.11/24") == IPAddr.new("18.104.22.168/32") # => false
22.214.171.124/24 is valid notation for a host address, yet IPAddr.new will drop the low-order bits to make it a valid network address:
IPAddr.new("126.96.36.199/24") == IPAddr.new("188.8.131.52/24") # => true
I'm not sure why we would want to have a netmask at all if IPAddr is only for host addresses.
Updated by sahglie (Steven Hansen) over 2 years ago
IPAddr represents an IP address, not an IP network, so it does not consider a difference in netmasks as significant.
I disagree that IPAddr represents an IP address (I think a more accurately represents a CIDR block). To add to Ben's point:
IPAddr.new('184.108.40.206').to_range.to_a # => [#<IPAddr: IPv4:220.127.116.11/255.255.255.255>]
IPAddr.new('18.104.22.168/30').to_range.to_a # => [ #<IPAddr: IPv4:22.214.171.124/255.255.255.252>, #<IPAddr: IPv4:126.96.36.199/255.255.255.252>, #<IPAddr: IPv4:188.8.131.52/255.255.25│5.252>, #<IPAddr: IPv4:184.108.40.206/255.255.255.252> ]
The fact that IPAddr accepts a CIDR block mean it represents 1 or more IPs. So an IPAddr with 1 IP should not be equal to an IPAddr with 4 IPs