From: b.candler@... Date: 2007-03-21T19:11:10+09:00 Subject: Extensions to ipaddr.rb This is a MIME-formatted message. If you see this text it means that your mail software cannot handle MIME-formatted messages. --=_0_62826_1174471863 Content-Type: text/plain; format=flowed; charset=utf-8 Content-Transfer-Encoding: 7bit I'd like to contribute the following extensions to ipaddr.rb They allow the following constructs: puts IPAddr.new("192.168.0.0") + 1 # => 192.168.0.1 puts IPAddr.new("192.168.0.0") - 1 # => 192.167.255.255 puts IPAddr.new("192.168.0.0/24").netmask # => 255.255.255.0 puts IPAddr.new("192.168.0.0/24").prefixlen # => 24 puts IPAddr.new("192.168.0.0/24").size # => 256 Regards, Brian Candler. --=_0_62826_1174471863 Content-Disposition: inline; filename=ipaddr.rb.diff Content-Type: text/plain; charset="utf-8"; name=ipaddr.rb.diff Content-Transfer-Encoding: 7bit --- /usr/lib/ruby/1.8/ipaddr.rb 2006-08-04 23:00:21.000000000 +0100 +++ ipaddr.rb 2007-03-21 10:11:55.000000000 +0000 @@ -125,6 +125,16 @@ return self.clone.set(addr_mask(@addr << num)) end + # Returns a new ipaddr built by addition. + def +(other) + return self.clone.set(@addr + other.to_i) + end + + # Returns a new ipaddr built by subtraction. + def -(other) + return self.clone.set(@addr - other.to_i) + end + # Returns a new ipaddr built by bitwise negation. def ~ return self.clone.set(addr_mask(~@addr)) @@ -331,6 +341,37 @@ af, _to_string(@addr), _to_string(@mask_addr)) end + # Return just the netmask. + def netmask + _to_string(@mask_addr) + end + + # Return just the prefix length. + def prefixlen + m = case @family + when Socket::AF_INET + IN4MASK + when Socket::AF_INET6 + IN6MASK + else + raise "unsupported address family" + end + return $1.length if /\A(1*)(0*)\z/ =~ (@mask_addr & m).to_s(2) + raise "bad addr_mask format" + end + + # Return the number of IP addresses in the block. + def size + case @family + when Socket::AF_INET + ((~@mask_addr) & IN4MASK) + 1 + when Socket::AF_INET6 + ((~@mask_addr) & IN6MASK) + 1 + else + raise "unsupported address family" + end + end + protected def set(addr, *family) @@ -547,6 +588,9 @@ a = IPAddr.new("0123:4567:89ab:cdef:0ABC:DEF0:1234:5678") assert_equal("123:4567:89ab:cdef:abc:def0:1234:5678", a.to_s) assert_equal("0123:4567:89ab:cdef:0abc:def0:1234:5678", a.to_string) + assert_equal("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", a.netmask) + assert_equal(128, a.prefixlen) + assert_equal(1, a.size) assert_equal(Socket::AF_INET6, a.family) a = IPAddr.new("3ffe:505:2::/48") @@ -556,6 +600,9 @@ assert_equal(false, a.ipv4?) assert_equal(true, a.ipv6?) assert_equal("#", a.inspect) + assert_equal("ffff:ffff:ffff:0000:0000:0000:0000:0000", a.netmask) + assert_equal(48, a.prefixlen) + assert_equal(1 << 80, a.size) a = IPAddr.new("3ffe:505:2::/ffff:ffff:ffff::") assert_equal("3ffe:505:2::", a.to_s) @@ -566,6 +613,16 @@ assert_equal("0.0.0.0", a.to_s) assert_equal("0.0.0.0", a.to_string) assert_equal(Socket::AF_INET, a.family) + assert_equal("#", a.inspect) + assert_equal("255.255.255.255", a.netmask) + assert_equal(32, a.prefixlen) + assert_equal(1, a.size) + + a = IPAddr.new("0.0.0.0/0") + assert_equal("#", a.inspect) + assert_equal("0.0.0.0", a.netmask) + assert_equal(0, a.prefixlen) + assert_equal(1 << 32, a.size) a = IPAddr.new("192.168.1.2") assert_equal("192.168.1.2", a.to_s) @@ -579,11 +636,17 @@ assert_equal("192.168.1.0", a.to_string) assert_equal(Socket::AF_INET, a.family) assert_equal("#", a.inspect) + assert_equal("255.255.255.0", a.netmask) + assert_equal(24, a.prefixlen) + assert_equal(256, a.size) a = IPAddr.new("192.168.1.2/255.255.255.0") assert_equal("192.168.1.0", a.to_s) assert_equal("192.168.1.0", a.to_string) assert_equal(Socket::AF_INET, a.family) + assert_equal("255.255.255.0", a.netmask) + assert_equal(24, a.prefixlen) + assert_equal(256, a.size) assert_equal("0:0:0:1::", IPAddr.new("0:0:0:1::").to_s) assert_equal("2001:200:300::", IPAddr.new("2001:200:300::/48").to_s) @@ -728,6 +791,16 @@ assert_equal("3ffe:505:2::", @a.to_s) end + def test_add + a = IPAddr.new("3ffe:505:2:1:ffff:ffff:ffff:fffd") + assert_equal("3ffe:505:2:1:ffff:ffff:ffff:fffe", (a + 1).to_s) + assert_equal("3ffe:505:2:2::", (a + 3).to_s) + end + + def test_sub + assert_equal("3ffe:505:1:ffff:ffff:ffff:ffff:ffff", (@a - 1).to_s) + end + def test_carrot a = ~@in6_addr_any assert_equal(IN6MASK128, a.to_s) --=_0_62826_1174471863--