Problem with IPAddr

B

Bryan Richardson

[Note: parts of this message were removed to make it a legal post.]

Hello all,

I'm having a problem with IPAddr, and I'm hoping someone can explain it to
me. I've done the following test, and I get the results shown below.

irb(main):001:0> require 'ipaddr'
=> true
irb(main):002:0> net_1 = IPAddr.new("192.168.0.0/16")
=> #<IPAddr: IPv4:192.168.0.0/255.255.0.0>
irb(main):003:0> net_2 = IPAddr.new("192.168.0.0/24")
=> #<IPAddr: IPv4:192.168.0.0/255.255.255.0>
irb(main):004:0> net_1.include?(net_2)
=> true
irb(main):005:0> net_2.include?(net_1)
=> true
irb(main):006:0>

I understand how net_1 can include net_2, but why does net_2 include
net_1?! Thanks in advance! -- BTR
 
G

Gary Wright

Hello all,

I'm having a problem with IPAddr, and I'm hoping someone can
explain it to
me. I've done the following test, and I get the results shown below.

irb(main):001:0> require 'ipaddr'
=> true
irb(main):002:0> net_1 = IPAddr.new("192.168.0.0/16")
=> #<IPAddr: IPv4:192.168.0.0/255.255.0.0>
irb(main):003:0> net_2 = IPAddr.new("192.168.0.0/24")
=> #<IPAddr: IPv4:192.168.0.0/255.255.255.0>
irb(main):004:0> net_1.include?(net_2)
=> true
irb(main):005:0> net_2.include?(net_1)
=> true
irb(main):006:0>

It is because include? is treating its argument as an address not as
a network. The subnet mask of the argument is ignored. So
net_2.include?(net_1) is really asking whether the first address of
net_1 (192.168.0.0) is contained in net_2 and that is true.

Gary Wright
 
B

Bryan Richardson

[Note: parts of this message were removed to make it a legal post.]

Gary,

Thanks for the reply. Here's what I get when I try something else:

irb(main):001:0> require 'ipaddr'
=> true
irb(main):002:0> net_1 = IPAddr.new("192.168.0.0/16")
=> #<IPAddr: IPv4:192.168.0.0/255.255.0.0>
irb(main):003:0> net_2 = IPAddr.new("192.168.101.0/24")
=> #<IPAddr: IPv4:192.168.101.0/255.255.255.0>
irb(main):004:0> net_1.include?(net_2)
=> true
irb(main):005:0> net_2.include?(net_1)
=> false
irb(main):006:0>

Makes sense I guess. Is there any way to tell IPAddr to look at it as a
network instead of as an address? I have a situation where I may come
across an address (ending in .0, so defining a network) where the netmask
isn't given, so I assign it as a small network (say /29). Later on I may
come across it again, this time with the netmask defined (say /16), and I
want to merge the first one into the second one. Therefore, each time I add
a new network to my database, I compare it to the existing ones to see if
any should be merged. Any suggestions? Thanks!! -- BTR
 
T

Todd Benson

Gary,

Thanks for the reply. Here's what I get when I try something else:

irb(main):001:0> require 'ipaddr'
=> true
irb(main):002:0> net_1 = IPAddr.new("192.168.0.0/16")
=> #<IPAddr: IPv4:192.168.0.0/255.255.0.0>
irb(main):003:0> net_2 = IPAddr.new("192.168.101.0/24")
=> #<IPAddr: IPv4:192.168.101.0/255.255.255.0>
irb(main):004:0> net_1.include?(net_2)
=> true
irb(main):005:0> net_2.include?(net_1)
=> false
irb(main):006:0>

Makes sense I guess. Is there any way to tell IPAddr to look at it as a
network instead of as an address? I have a situation where I may come
across an address (ending in .0, so defining a network) where the netmask
isn't given, so I assign it as a small network (say /29). Later on I may
come across it again, this time with the netmask defined (say /16), and I
want to merge the first one into the second one. Therefore, each time I add
a new network to my database, I compare it to the existing ones to see if
any should be merged. Any suggestions? Thanks!! -- BTR

You could open up IPAddr to get at the mask for comparison.

class IPAddr
def net
@mask_addr
end
end

ip1 = IPAddr.new("192.168.0.0/16")
ip2 = IPAddr.new("192.168.0.0/24")

ip1.net > ip2.net # => false (which seems contradictory, but the mask
number is larger for smaller networks)
ip2.net > ip1.net #=> true

hth,
Todd
 
F

fw

Gary,

Thanks for the reply. Here's what I get when I try something else:

irb(main):001:0> require 'ipaddr'
=> true
irb(main):002:0> net_1 = IPAddr.new("192.168.0.0/16")
=> #<IPAddr: IPv4:192.168.0.0/255.255.0.0>
irb(main):003:0> net_2 = IPAddr.new("192.168.101.0/24")
=> #<IPAddr: IPv4:192.168.101.0/255.255.255.0>
irb(main):004:0> net_1.include?(net_2)
=> true
irb(main):005:0> net_2.include?(net_1)
=> false
irb(main):006:0>

Makes sense I guess. Is there any way to tell IPAddr to look at it as a
network instead of as an address? I have a situation where I may come
across an address (ending in .0, so defining a network) where the netmask
isn't given, so I assign it as a small network (say /29). Later on I may
come across it again, this time with the netmask defined (say /16), and I
want to merge the first one into the second one. Therefore, each time I add
a new network to my database, I compare it to the existing ones to see if
any should be merged. Any suggestions? Thanks!! -- BTR

First I'd like to add that the last octet being 0 does not mean that the
IP address is a network address: In the network 10.0.0.0/25, 10.0.1.0 is
a host address.

IPAddr doesn't seem to have this functionality, but you can add it like
this:

$ irb
irb(main):001:0> require 'ipaddr'
=> true
irb(main):002:0> class IPAddr
irb(main):003:1> def broadcast_addr
irb(main):004:2> _to_string(@addr | (2**32 - 1) - (@mask_addr))
irb(main):005:2> end
irb(main):006:1> def network_in_network?(network)
irb(main):007:2> return false unless self.include?(network)
irb(main):008:2> return false unless
self.include?(IPAddr.new(network.broadcast_addr))
irb(main):009:2> return true
irb(main):010:2> end
irb(main):011:1> end
=> nil
irb(main):012:0> a = IPAddr.new('192.168.0.128/25')
=> #<IPAddr: IPv4:192.168.0.128/255.255.255.128>
irb(main):013:0> b = IPAddr.new('192.168.0.0/24')
=> #<IPAddr: IPv4:192.168.0.0/255.255.255.0>
irb(main):014:0> a.network_in_network?(b)
=> false
irb(main):015:0> b.network_in_network?(a)
=> true
irb(main):016:0>


This works by determining the broadcast address of the network (by ORing
the network address with the reverse netmask) and then checking if both
network and broadcast address are included in the range you're checking
against.

HTH,

Felix
 
T

Todd Benson

First I'd like to add that the last octet being 0 does not mean that the
IP address is a network address: In the network 10.0.0.0/25, 10.0.1.0 is
a host address.

IPAddr doesn't seem to have this functionality, but you can add it like
this:

$ irb
irb(main):001:0> require 'ipaddr'
=> true
irb(main):002:0> class IPAddr
irb(main):003:1> def broadcast_addr
irb(main):004:2> _to_string(@addr | (2**32 - 1) - (@mask_addr))
irb(main):005:2> end
irb(main):006:1> def network_in_network?(network)
irb(main):007:2> return false unless self.include?(network)
irb(main):008:2> return false unless
self.include?(IPAddr.new(network.broadcast_addr))
irb(main):009:2> return true
irb(main):010:2> end
irb(main):011:1> end
=> nil
irb(main):012:0> a = IPAddr.new('192.168.0.128/25')
=> #<IPAddr: IPv4:192.168.0.128/255.255.255.128>
irb(main):013:0> b = IPAddr.new('192.168.0.0/24')
=> #<IPAddr: IPv4:192.168.0.0/255.255.255.0>
irb(main):014:0> a.network_in_network?(b)
=> false
irb(main):015:0> b.network_in_network?(a)
=> true
irb(main):016:0>


This works by determining the broadcast address of the network (by ORing
the network address with the reverse netmask) and then checking if both
network and broadcast address are included in the range you're checking
against.

This might work too...

class IPAddr
attr_accessor :mask_addr
def network_in_network? ipaddr
@mask_addr > ipaddr.mask_addr
end
end

Todd
 
B

Bryan Richardson

[Note: parts of this message were removed to make it a legal post.]

Todd,

I believe Felix's suggestion is the way to go. With yours, the addresses
could be different, but as long as the mask was bigger it would still return
true... not correct. Example:

a = IPAddr.new("192.168.15.5")
b = IPAddr.new("192.168.16.0/24")

a.network_in_network?(b) #==> true

Thanks! -- BTR
 
T

Todd Benson

Todd,

I believe Felix's suggestion is the way to go. With yours, the addresses
could be different, but as long as the mask was bigger it would still return
true... not correct.

Good point!

thanx,
Todd
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top