lib/ipaddress/ipv4.rb in ipaddress-0.8.0 vs lib/ipaddress/ipv4.rb in ipaddress-0.8.2

- old
+ new

@@ -229,10 +229,25 @@ end alias_method :to_i, :u32 alias_method :to_u32, :u32 # + # Returns the address portion in + # hex + # + # ip = IPAddress("10.0.0.0") + # + # ip.to_h + # #=> 0a000000 + # + def hex(space=true) + "%.4x%.4x" % [to_u32].pack("N").unpack("nn") + end + alias_method :to_h, :hex + alias_method :to_hex, :hex + + # # Returns the address portion of an IPv4 object # in a network byte order format. # # ip = IPAddress("172.16.10.1/24") # @@ -269,10 +284,25 @@ # def [](index) @octets[index] end alias_method :octet, :[] + + # + # Updated the octet specified at index + # + # ip = IPAddress("172.16.100.50/24") + # ip[2] = 200 + # + # #=> #<IPAddress::IPv4:0x00000000000000 @address="172.16.200.1", + # #=> @prefix=32, @octets=[172, 16, 200, 1], @u32=2886780929> + # + def []=(index, value) + @octets[index] = value.to_i + initialize("#{@octets.join('.')}/#{prefix}") + end + alias_method :octet=, :[]= # # Returns the address portion of an IP in binary format, # as a string containing a sequence of 0 and 1 # @@ -292,11 +322,18 @@ # # ip.broadcast.to_s # #=> "172.16.10.255" # def broadcast - self.class.parse_u32(broadcast_u32, @prefix) + case + when prefix <= 30 + self.class.parse_u32(broadcast_u32, @prefix) + when prefix == 31 + self.class.parse_u32(-1, @prefix) + when prefix == 32 + return self + end end # # Checks if the IP address is actually a network # @@ -309,11 +346,11 @@ # # ip.network? # #=> true # def network? - @u32 | @prefix.to_u32 == @prefix.to_u32 + (@prefix < 32) && (@u32 | @prefix.to_u32 == @prefix.to_u32) end # # Returns a new IPv4 object with the network number # for the given IP. @@ -346,11 +383,18 @@ # # ip.first.to_s # #=> "192.168.100.1" # def first - self.class.parse_u32(network_u32+1, @prefix) + case + when prefix <= 30 + self.class.parse_u32(network_u32+1, @prefix) + when prefix == 31 + self.class.parse_u32(network_u32, @prefix) + when prefix == 32 + return self + end end # # Like its sibling method IPv4#first, this method # returns a new IPv4 object with the @@ -371,11 +415,18 @@ # # ip.last.to_s # #=> "192.168.100.254" # def last - self.class.parse_u32(broadcast_u32-1, @prefix) + case + when prefix <= 30 + self.class.parse_u32(broadcast_u32-1, @prefix) + when prefix == 31 + self.class.parse_u32(broadcast_u32, @prefix) + when prefix == 32 + return self + end end # # Iterates over all the hosts IP addresses for the given # network (or IP address). @@ -568,10 +619,52 @@ self.class.new("172.16.0.0/12"), self.class.new("192.168.0.0/16")].any? {|i| i.include? self} end # + # Checks if an IPv4 address objects belongs + # to a multicast network RFC3171 + # + # Example: + # + # ip = IPAddress "224.0.0.0/4" + # ip.multicast? + # #=> true + # + def multicast? + [self.class.new("224.0.0.0/4")].any? {|i| i.include? self} + end + + # + # Checks if an IPv4 address objects belongs + # to a multicast network RFC3171 + # + # Example: + # + # ip = IPAddress "224.0.0.0/4" + # ip.multicast? + # #=> true + # + def multicast? + [self.class.new("224.0.0.0/4")].any? {|i| i.include? self} + end + + # + # Checks if an IPv4 address objects belongs + # to a loopback network RFC1122 + # + # Example: + # + # ip = IPAddress "127.0.0.1" + # ip.loopback? + # #=> true + # + def loopback? + [self.class.new("127.0.0.0/8")].any? {|i| i.include? self} + end + + # # Returns the IP address in in-addr.arpa format # for DNS lookups # # ip = IPAddress("172.16.100.50/24") # @@ -582,10 +675,30 @@ @octets.reverse.join(".") + ".in-addr.arpa" end alias_method :arpa, :reverse # + # Return a list of IP's between @address + # and the supplied IP + # + # ip = IPAddress("172.16.100.51/32") + # + # ip.to("172.16.100.100") + # #=> ["172.16.100.51", + # #=> "172.16.100.52", + # #=> ... + # #=> "172.16.100.99", + # #=> "172.16.100.100"] + # + def to(e) + unless e.is_a? IPAddress::IPv4 + e = IPv4.new(e) + end + + Range.new(@u32, e.to_u32).map{|i| IPAddress.ntoa(i) } + end + # # Splits a network into different subnets # # If the IP Address is a network, it can be divided into # multiple networks. If +self+ is not a network, this # method will calculate the network from the IP and then @@ -596,24 +709,24 @@ # # network = IPAddress("172.16.10.0/24") # # network / 4 # implies map{|i| i.to_string} # #=> ["172.16.10.0/26", - # "172.16.10.64/26", - # "172.16.10.128/26", - # "172.16.10.192/26"] + # #=> "172.16.10.64/26", + # #=> "172.16.10.128/26", + # #=> "172.16.10.192/26"] # # If +num+ is any other number, the supernet will be # divided into some networks with a even number of hosts and # other networks with the remaining addresses. # # network = IPAddress("172.16.10.0/24") # # network / 3 # implies map{|i| i.to_string} # #=> ["172.16.10.0/26", - # "172.16.10.64/26", - # "172.16.10.128/25"] + # #=> "172.16.10.64/26", + # #=> "172.16.10.128/25"] # # Returns an array of IPv4 objects # def split(subnets=2) unless (1..(2**@prefix.host_prefix)).include? subnets @@ -967,15 +1080,12 @@ # # private methods # private + # Tweaked to remove the #upto(32) def newprefix(num) - num.upto(32) do |i| - if (a = Math::log2(i).to_i) == Math::log2(i) - return @prefix + a - end - end + return @prefix + (Math::log2(num).ceil ) end def sum_first_found(arr) dup = arr.dup.reverse dup.each_with_index do |obj,i|