Bug #14119
closedIPAddr#include? does not seem to support the subnet mask
Description
IPAdrr#include? において、引数のIPAddrオブジェクトのネットマスクが考慮された判定になっていないようです。
再現方法と得られた結果¶
irb(main):001:0> require 'ipaddr'
=> true
irb(main):002:0> IPAddr.new('10.5.0.0/24').include?('10.5.0.0/16')
=> true
irb(main):003:0> IPAddr.new('10.5.0.0/16').include?('10.5.0.0/24')
=> true
irb(main):004:0> IPAddr.new('10.5.0.0/24').include?(IPAddr.new('10.5.0.0/16'))
=> true
irb(main):005:0> IPAddr.new('10.5.0.0/16').include?(IPAddr.new('10.5.0.0/24'))
=> true
期待した結果と、それを期待した理由¶
irb(main):001:0> require 'ipaddr'
=> true
irb(main):002:0> IPAddr.new('10.5.0.0/24').include?('10.5.0.0/16')
=> true
irb(main):003:0> IPAddr.new('10.5.0.0/16').include?('10.5.0.0/24')
=> false
irb(main):004:0> IPAddr.new('10.5.0.0/24').include?(IPAddr.new('10.5.0.0/16'))
=> true
irb(main):005:0> IPAddr.new('10.5.0.0/16').include?(IPAddr.new('10.5.0.0/24'))
=> false
期待した理由¶
- IPAddrオブジェクトは
#include?
において、レシーバはIPアドレス範囲(集合)として動いている - るりま によると、引数について「与えられた IPAddr オブジェクトが自身の範囲に入っているかを判定します」とある
上記の情報から、レシーバと引数とは集合同士の包含関係をチェックするのが直感的ではないか?と考えたからです。
(片方のIPAddrオブジェクトだけ集合で、片方のIPAddrオブジェクトだけ単一IPアドレスという点が直感的ではない)
期待される結果であった場合のユースケース¶
- iptablesなどで設定されているCIDR表記のIPアドレス範囲に対して、確認したいIPアドレス範囲が含まれているかどうかの確認
過去の議論のサーベイ¶
1905¶
#1905 のチケットの中において、#==
の挙動についての議論の中にIPAddrについての説明ありました(ML側が抜け落ちているので リンク ruby-dev:39381)
整形して引用:
> > IPAddr.new("192.168.2.0/24") == IPAddr.new("192.168.2.0/32")
> >
> > が true から false に変わるという仕様変更なのですが、どうでしょうか?
>
> というのがまずいでしょうか。
これは受け入れられません。IPAddrはネットマスクも保持するため
ネットワークもできますが、第一義はIPアドレスなので、ネット
マスクの違いで等しくなくなるのはまずいです。
上記から、IPAddrは、まず単一のIPアドレスとして動くことが求められていることは理解しました。
その後、ネットマスクを考慮した拡張についての議論が ruby-dev:39391 であるようなのですが、
こちらは文字化けがあり、まだしっかりと確認・理解できていません。すみません。
1275¶
#1275 のチケットにおいてネットマスクでIPアドレスの情報が消される問題についての議論がありました。
過去の議論をふまえて¶
- 「
IPAdrr#include?
においてはIPアドレス範囲同士の包含関係を見るようにする」のみの修正であれば、IPAddrの第一義に反していないと言えるのでは?と考えています(IPAdrr#include?
のタイミングではレシーバはネットマスクを考慮するため)。 - #1275 のパッチが入った場合は、本チケットについての修正内容も変更されると思います。
- 上記より踏み込んだ修正は、ruby-dev:39391 にある(であろう)流れの拡張になろうだろうと考えています。
Files
Updated by k1LoW (Ken'ichiro Oyama) almost 7 years ago
- Subject changed from IPAdrr#include? does not seem to support the subnet mask to IPAddr#include? does not seem to support the subnet mask
s/IPAdrr/IPAddr/ です。申し訳ありません。。。
Updated by hsbt (Hiroshi SHIBATA) almost 7 years ago
- Status changed from Open to Assigned
- Assignee set to knu (Akinori MUSHA)
Updated by jeremyevans0 (Jeremy Evans) almost 5 years ago
I'm not sure this is a bug, but it certainly seems like a bug to me. IPAddr#include?
must consider the netmask of the receiver in order to work, for it not to consider the netmask of the argument seems wrong.
Attached is a patch that uses Range#cover?
to implement the include check, which I think is the best way of solving the issue. It does not break any existing tests. It also is a much simpler implementation.
Updated by jeremyevans0 (Jeremy Evans) over 4 years ago
As ipaddr has been moved to a gem, I have submitted a pull request for this: https://github.com/ruby/ipaddr/pull/22
Updated by jeremyevans0 (Jeremy Evans) over 4 years ago
- Status changed from Assigned to Closed