diff options
author | Marco Ceresa <ceresa@gmail.com> | 2010-02-03 17:51:49 +0000 |
---|---|---|
committer | Marco Ceresa <ceresa@gmail.com> | 2010-02-03 17:51:49 +0000 |
commit | 48045a5857123dc3e5067bb457e4fd2c337c98df (patch) | |
tree | dc964be23548320efeaeb6b18811926e5befe486 | |
parent | 9030d410a3757558ef23ac2317f2fb82d5a1e324 (diff) | |
download | ipaddress-48045a5857123dc3e5067bb457e4fd2c337c98df.tar.gz |
added IPv4#+ and many new IPv6 methods and tests
-rw-r--r-- | lib/ipaddress/ipv4.rb | 27 | ||||
-rw-r--r-- | lib/ipaddress/ipv6.rb | 75 | ||||
-rw-r--r-- | lib/ipaddress/prefix.rb | 6 | ||||
-rw-r--r-- | test/ipaddress/ipv4_test.rb | 11 | ||||
-rw-r--r-- | test/ipaddress/ipv6_test.rb | 79 |
5 files changed, 168 insertions, 30 deletions
diff --git a/lib/ipaddress/ipv4.rb b/lib/ipaddress/ipv4.rb index 5621a97..23dec91 100644 --- a/lib/ipaddress/ipv4.rb +++ b/lib/ipaddress/ipv4.rb @@ -225,7 +225,7 @@ module IPAddress; # a.puts binary_data # def data - @octets.pack("CCCC") + @octets.pack("C4") end # @@ -588,6 +588,25 @@ module IPAddress; end # + # Returns a new IPv4 object which is the result + # of the summarization, if possible, of the two + # objects + # + # Example: + # + # ip1 = IPAddress("172.16.10.1/24") + # ip2 = IPAddress("172.16.11.2/24") + # puts ip1 + ip2 + # #=>"172.16.10.0/23" + # + # If the networks are not contiguous, returns + # the two network numbers from the objects + # + def +(oth) + self.class.summarize(self,oth) + end + + # # Creates a new IPv4 object from an # unsigned 32bits integer. # @@ -603,7 +622,7 @@ module IPAddress; # #=> "10.0.0.0/8" # def self.parse_u32(u32, prefix=nil) - ip = [u32].pack("N").unpack("CCCC").join(".") + ip = [u32].pack("N").unpack("C4").join(".") if prefix IPAddress::IPv4.new(ip+"/#{prefix}") else @@ -616,7 +635,7 @@ module IPAddress; # TODO # def self.parse_data(str) - self.new str.unpack("CCCC").join(".") + self.new str.unpack("C4").join(".") end # @@ -712,7 +731,7 @@ module IPAddress; private def bits_from_address(ip) - ip.split(".").map{|i| i.to_i}.pack("CCCC").unpack("B*").first + ip.split(".").map{|i| i.to_i}.pack("C4").unpack("B*").first end def prefix_from_ip(ip) diff --git a/lib/ipaddress/ipv6.rb b/lib/ipaddress/ipv6.rb index ebb2d03..01e2f04 100644 --- a/lib/ipaddress/ipv6.rb +++ b/lib/ipaddress/ipv6.rb @@ -36,12 +36,14 @@ module IPAddress; raise ArgumentError, "Invalid IP #{ip.inspect}" end - # Check the prefix - if netmask =~ /^\d{1,3}$/ - @prefix = Prefix128.new(netmask.to_i) - else - @prefix = Prefix128.new(128) - end +# # Check the prefix +# if netmask =~ /^\d{1,3}$/ +# @prefix = Prefix128.new(netmask.to_i) +# else +# @prefix = Prefix128.new(128) +# end + + @prefix = Prefix128.new(netmask ? netmask : 128) end # def initialize @@ -58,6 +60,27 @@ module IPAddress; @prefix end + # + # Set a new prefix number for the object + # + # This is useful if you want to change the prefix + # to an object created with IPv6::parse_u128 or + # if the object was created using the default prefix + # of 128 bits. + # + # ip = IPAddress("2001:db8::8:800:200c:417a") + # puts ip + # #=> 2001:db8::8:800:200c:417a/128 + # + # ip.prefix = 64 + # puts ip + # #=> 2001:db8::8:800:200c:417a/64 + # + def prefix=(num) + @prefix = Prefix128.new(num) + end + + def to_string "#@address/#@prefix" end @@ -69,6 +92,25 @@ module IPAddress; def to_i to_hex.hex end + alias_method :to_u128, :to_i + + # + # Returns the 16-bits value specified by index + # + # ip = IPAddress("2001:db8::8:800:200c:417a/64") + # ip[0] + # #=> 8193 + # ip[1] + # #=> 3512 + # ip[2] + # #=> 0 + # ip[3] + # #=> 0 + # + def [](index) + @groups[index] + end + alias_method :group, :[] def to_hex hexs.to_s @@ -93,6 +135,18 @@ module IPAddress; def loopback? @prefix == 128 and @compressed == "::1" end + + # + # Returns the address portion of an IP in binary format, + # as a string containing a sequence of 0 and 1 + # + # ip = IPAddress("2001:db8::8:800:200c:417a") + # ip.bits + # #=> "01111111000000000000000000000001" + # + def bits + data.unpack("B*").first + end # # Expands an IPv6 address in the canocical form @@ -120,6 +174,15 @@ module IPAddress; def self.parse_data(str) self.new(IN6FORMAT % str.unpack("n8")) end + + def self.parse_u128(u128, prefix=128) + str = IN6FORMAT % (0..7).map{|i| (u128>>(112-16*i))&0xffff} + self.new(str + "/#{prefix}") + end + + def self.parse_hex(hex, prefix=128) + self.parse_u128(hex.hex, prefix) + end private diff --git a/lib/ipaddress/prefix.rb b/lib/ipaddress/prefix.rb index 5726272..b2fa07b 100644 --- a/lib/ipaddress/prefix.rb +++ b/lib/ipaddress/prefix.rb @@ -69,11 +69,11 @@ module IPAddress class Prefix128 < Prefix - def initialize(num) - unless (1..128).include? num + def initialize(num=128) + unless (1..128).include? num.to_i raise ArgumentError, "Prefix must be in range 1..128, got: #{num}" end - super(num) + super(num.to_i) end def bits diff --git a/test/ipaddress/ipv4_test.rb b/test/ipaddress/ipv4_test.rb index e8b299f..70c9c9c 100644 --- a/test/ipaddress/ipv4_test.rb +++ b/test/ipaddress/ipv4_test.rb @@ -134,7 +134,7 @@ class IPv4Test < Test::Unit::TestCase def test_method_bits ip = @klass.new("127.0.0.1") - assert_equal ip.bits, "01111111000000000000000000000001" + assert_equal "01111111000000000000000000000001", ip.bits end def test_method_first @@ -255,6 +255,15 @@ class IPv4Test < Test::Unit::TestCase assert_equal 9, ip1 - ip2 end + def test_method_plus + ip1 = @klass.new("172.16.10.1/24") + ip2 = @klass.new("172.16.11.2/24") + assert_equal "172.16.10.0/23", (ip1 + ip2).to_s + ip2 = @klass.new("172.16.12.2/24") + assert_equal [ip1.network.to_s,ip2.network.to_s], (ip1 + ip2).map{|i| i.to_s} + end + + def test_method_netmask_equal ip = @klass.new("10.1.1.1/16") assert_equal 16, ip.prefix.to_i diff --git a/test/ipaddress/ipv6_test.rb b/test/ipaddress/ipv6_test.rb index afc3b45..6549442 100644 --- a/test/ipaddress/ipv6_test.rb +++ b/test/ipaddress/ipv6_test.rb @@ -11,8 +11,28 @@ class IPv6Test < Test::Unit::TestCase "ff01:0:0:0:0:0:0:101" => "ff01::101", "0:0:0:0:0:0:0:1" => "::1", "0:0:0:0:0:0:0:0" => "::"} + + @valid_ipv6 = { # Kindly taken from the python IPy library + "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210" => 338770000845734292534325025077361652240, + "1080:0000:0000:0000:0008:0800:200C:417A" => 21932261930451111902915077091070067066, + "1080:0:0:0:8:800:200C:417A" => 21932261930451111902915077091070067066, + "1080:0::8:800:200C:417A" => 21932261930451111902915077091070067066, + "1080::8:800:200C:417A" => 21932261930451111902915077091070067066, + "FF01:0:0:0:0:0:0:43" => 338958331222012082418099330867817087043, + "FF01:0:0::0:0:43" => 338958331222012082418099330867817087043, + "FF01::43" => 338958331222012082418099330867817087043, + "0:0:0:0:0:0:0:1" => 1, + "0:0:0::0:0:1" => 1, + "::1" => 1, + "0:0:0:0:0:0:0:0" => 0, + "0:0:0::0:0:0" => 0, + "::" => 0, + "1080:0:0:0:8:800:200C:417A" => 21932261930451111902915077091070067066, + "1080::8:800:200C:417A" => 21932261930451111902915077091070067066} + @ip = @klass.new "2001:db8::8:800:200c:417a/64" + @arr = [8193,3512,0,0,8,2048,8204,16762] end @@ -27,8 +47,7 @@ class IPv6Test < Test::Unit::TestCase end def test_attribute_groups - arr = [8193,3512,0,0,8,2048,8204,16762] - assert_equal arr, @ip.groups + assert_equal @arr, @ip.groups end def test_method_hexs @@ -37,8 +56,30 @@ class IPv6Test < Test::Unit::TestCase end def test_method_to_i - bigint = 42540766411282592856906245548098208122 - assert_equal bigint, @ip.to_i + @valid_ipv6.each do |ip,num| + assert_equal num, @klass.new(ip).to_i + end + end + + def test_method_bits + bits = "0010000000000001000011011011100000000000000000000" + + "000000000000000000000000000100000001000000000000010000" + + "0000011000100000101111010" + assert_equal bits, @ip.bits + end + + def test_method_prefix=() + ip = @klass.new "2001:db8::8:800:200c:417a" + assert_equal 128, ip.prefix + ip.prefix = 64 + assert_equal 64, ip.prefix + assert_equal "2001:db8::8:800:200c:417a/64", ip.to_s + end + + def test_method_group + @arr.each_with_index do |val,index| + assert_equal val, @ip[index] + end end def test_method_to_hex @@ -68,16 +109,16 @@ class IPv6Test < Test::Unit::TestCase assert_equal "1::1", @klass.new("1:0:0:0:0:0:0:1").compressed end - def test_method_unspecified? - assert_equal true, @klass.new("::").unspecified? - assert_equal false, @ip.unspecified? - end - - def test_method_loopback? - assert_equal true, @klass.new("::1").loopback? - assert_equal false, @ip.loopback? - end - + def test_method_unspecified? + assert_equal true, @klass.new("::").unspecified? + assert_equal false, @ip.unspecified? + end + + def test_method_loopback? + assert_equal true, @klass.new("::1").loopback? + assert_equal false, @ip.loopback? + end + def test_classmethod_expand compressed = "2001:db8:0:cd30::" expanded = "2001:0db8:0000:cd30:0000:0000:0000:0000" @@ -86,7 +127,7 @@ class IPv6Test < Test::Unit::TestCase assert_not_equal expanded, @klass.expand("2001:0db8::cd30") assert_not_equal expanded, @klass.expand("2001:0db8::cd3") end - + def test_classmethod_compress compressed = "2001:db8:0:cd30::" expanded = "2001:0db8:0000:cd30:0000:0000:0000:0000" @@ -119,7 +160,13 @@ class IPv6Test < Test::Unit::TestCase assert_equal "2001:0db8:0000:0000:0008:0800:200c:417a", ip.address assert_equal "2001:db8::8:800:200c:417a/128", ip.to_s end - + + def test_classhmethod_parse_u128 + @valid_ipv6.each do |ip,num| + assert_equal @klass.new(ip).to_s, @klass.parse_u128(num).to_s + end + end + end # class IPv4Test |