In Files

  • ipaddr.rb

Class/Module Index [+]

Quicksearch

IPAddr

IPAddr provides a set of methods to manipulate an IP address. Both IPv4 and IPv6 are supported.

Example

require 'ipaddr'

ipaddr1 = IPAddr.new "3ffe:505:2::1"

p ipaddr1                   #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>

p ipaddr1.to_s              #=> "3ffe:505:2::1"

ipaddr2 = ipaddr1.mask(48)  #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0000/ffff:ffff:ffff:0000:0000:0000:0000:0000>

p ipaddr2.to_s              #=> "3ffe:505:2::"

ipaddr3 = IPAddr.new "192.168.2.0/24"

p ipaddr3                   #=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0>

Attributes

family[R]

Returns the address family of this IP address.

Public Class Methods

new(addr = '::', family = Socket::AF_UNSPEC) click to toggle source

Creates a new ipaddr object either from a human readable IP address representation in string, or from a packed in_addr value followed by an address family.

In the former case, the following are the valid formats that will be recognized: “address”, “address/prefixlen” and “address/mask”, where IPv6 address may be enclosed in square brackets (`[‘ and `]’). If a prefixlen or a mask is specified, it returns a masked IP address. Although the address family is determined automatically from a specified string, you can specify one explicitly by the optional second argument.

Otherwise an IP addess is generated from a packed in_addr value and an address family.

The IPAddr class defines many methods and operators, and some of those, such as &, |, include? and ==, accept a string, or a packed in_addr value instead of an IPAddr object.

 
               # File ipaddr.rb, line 443
def initialize(addr = '::', family = Socket::AF_UNSPEC)
  if !addr.kind_of?(String)
    case family
    when Socket::AF_INET, Socket::AF_INET6
      set(addr.to_i, family)
      @mask_addr = (family == Socket::AF_INET) ? IN4MASK : IN6MASK
      return
    when Socket::AF_UNSPEC
      raise ArgumentError, "address family must be specified"
    else
      raise ArgumentError, "unsupported address family: #{family}"
    end
  end
  prefix, prefixlen = addr.split('/')
  if prefix =~ /^\[(.*)\]$/i
    prefix = $1
    family = Socket::AF_INET6
  end
  # It seems AI_NUMERICHOST doesn't do the job.
  #Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil,
  #                  Socket::AI_NUMERICHOST)
  begin
    IPSocket.getaddress(prefix)               # test if address is vaild
  rescue
    raise ArgumentError, "invalid address"
  end
  @addr = @family = nil
  if family == Socket::AF_UNSPEC || family == Socket::AF_INET
    @addr = in_addr(prefix)
    if @addr
      @family = Socket::AF_INET
    end
  end
  if !@addr && (family == Socket::AF_UNSPEC || family == Socket::AF_INET6)
    @addr = in6_addr(prefix)
    @family = Socket::AF_INET6
  end
  if family != Socket::AF_UNSPEC && @family != family
    raise ArgumentError, "address family mismatch"
  end
  if prefixlen
    mask!(prefixlen)
  else
    @mask_addr = (@family == Socket::AF_INET) ? IN4MASK : IN6MASK
  end
end
            
new_ntoh(addr) click to toggle source

Creates a new ipaddr containing the given network byte ordered string form of an IP address.

 
               # File ipaddr.rb, line 95
def IPAddr::new_ntoh(addr)
  return IPAddr.new(IPAddr::ntop(addr))
end
            
ntop(addr) click to toggle source

Convert a network byte ordered string form of an IP address into human readable form.

 
               # File ipaddr.rb, line 101
def IPAddr::ntop(addr)
  case addr.size
  when 4
    s = addr.unpack('C4').join('.')
  when 16
    s = IN6FORMAT % addr.unpack('n8')
  else
    raise ArgumentError, "unsupported address family"
  end
  return s
end
            

Public Instance Methods

&(other) click to toggle source

Returns a new ipaddr built by bitwise AND.

 
               # File ipaddr.rb, line 114
def &(other)
  return self.clone.set(@addr & coerce_other(other).to_i)
end
            
<<(num) click to toggle source

Returns a new ipaddr built by bitwise left shift.

 
               # File ipaddr.rb, line 129
def <<(num)
  return self.clone.set(addr_mask(@addr << num))
end
            
<=>(other) click to toggle source

Compares the ipaddr with another.

 
               # File ipaddr.rb, line 325
def <=>(other)
  other = coerce_other(other)

  return nil if other.family != @family

  return @addr <=> other.to_i
end
            
==(other) click to toggle source

Returns true if two ipaddrs are equal.

 
               # File ipaddr.rb, line 139
def ==(other)
  other = coerce_other(other)
  return @family == other.family && @addr == other.to_i
end
            
===(other) click to toggle source
Alias for: include?
>>(num) click to toggle source

Returns a new ipaddr built by bitwise right-shift.

 
               # File ipaddr.rb, line 124
def >>(num)
  return self.clone.set(@addr >> num)
end
            
hton() click to toggle source

Returns a network byte ordered string form of the IP address.

 
               # File ipaddr.rb, line 225
def hton
  case @family
  when Socket::AF_INET
    return [@addr].pack('N')
  when Socket::AF_INET6
    return (0..7).map { |i|
      (@addr >> (112 - 16 * i)) & 0xffff
    }.pack('n8')
  else
    raise "unsupported address family"
  end
end
            
include?(other) click to toggle source

Returns true if the given ipaddr is in the range.

e.g.:

require 'ipaddr'
net1 = IPAddr.new("192.168.2.0/24")
net2 = IPAddr.new("192.168.2.100")
net3 = IPAddr.new("192.168.3.0")
p net1.include?(net2)     #=> true
p net1.include?(net3)     #=> false
 
               # File ipaddr.rb, line 159
def include?(other)
  other = coerce_other(other)
  if ipv4_mapped?
    if (@mask_addr >> 32) != 0xffffffffffffffffffffffff
      return false
    end
    mask_addr = (@mask_addr & IN4MASK)
    addr = (@addr & IN4MASK)
    family = Socket::AF_INET
  else
    mask_addr = @mask_addr
    addr = @addr
    family = @family
  end
  if other.ipv4_mapped?
    other_addr = (other.to_i & IN4MASK)
    other_family = Socket::AF_INET
  else
    other_addr = other.to_i
    other_family = other.family
  end

  if family != other_family
    return false
  end
  return ((addr & mask_addr) == (other_addr & mask_addr))
end
            
Also aliased as: ===
inspect() click to toggle source

Returns a string containing a human-readable representation of the ipaddr. (“#<IPAddr: family:address/mask>”)

 
               # File ipaddr.rb, line 352
def inspect
  case @family
  when Socket::AF_INET
    af = "IPv4"
  when Socket::AF_INET6
    af = "IPv6"
  else
    raise "unsupported address family"
  end
  return sprintf("#<%s: %s:%s/%s>", self.class.name,
                 af, _to_string(@addr), _to_string(@mask_addr))
end
            
ip6_arpa() click to toggle source

Returns a string for DNS reverse lookup compatible with RFC3172.

 
               # File ipaddr.rb, line 304
def ip6_arpa
  if !ipv6?
    raise ArgumentError, "not an IPv6 address"
  end
  return _reverse + ".ip6.arpa"
end
            
ip6_int() click to toggle source

Returns a string for DNS reverse lookup compatible with RFC1886.

 
               # File ipaddr.rb, line 312
def ip6_int
  if !ipv6?
    raise ArgumentError, "not an IPv6 address"
  end
  return _reverse + ".ip6.int"
end
            
ipv4?() click to toggle source

Returns true if the ipaddr is an IPv4 address.

 
               # File ipaddr.rb, line 239
def ipv4?
  return @family == Socket::AF_INET
end
            
ipv4_compat() click to toggle source

Returns a new ipaddr built by converting the native IPv4 address into an IPv4-compatible IPv6 address.

 
               # File ipaddr.rb, line 273
def ipv4_compat
  if !ipv4?
    raise ArgumentError, "not an IPv4 address"
  end
  return self.clone.set(@addr, Socket::AF_INET6)
end
            
ipv4_compat?() click to toggle source

Returns true if the ipaddr is an IPv4-compatible IPv6 address.

 
               # File ipaddr.rb, line 254
def ipv4_compat?
  if !ipv6? || (@addr >> 32) != 0
    return false
  end
  a = (@addr & IN4MASK)
  return a != 0 && a != 1
end
            
ipv4_mapped() click to toggle source

Returns a new ipaddr built by converting the native IPv4 address into an IPv4-mapped IPv6 address.

 
               # File ipaddr.rb, line 264
def ipv4_mapped
  if !ipv4?
    raise ArgumentError, "not an IPv4 address"
  end
  return self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6)
end
            
ipv4_mapped?() click to toggle source

Returns true if the ipaddr is an IPv4-mapped IPv6 address.

 
               # File ipaddr.rb, line 249
def ipv4_mapped?
  return ipv6? && (@addr >> 32) == 0xffff
end
            
ipv6?() click to toggle source

Returns true if the ipaddr is an IPv6 address.

 
               # File ipaddr.rb, line 244
def ipv6?
  return @family == Socket::AF_INET6
end
            
mask(prefixlen) click to toggle source

Returns a new ipaddr built by masking IP address with the given prefixlen/netmask. (e.g. 8, 64, “255.255.255.0”, etc.)

 
               # File ipaddr.rb, line 146
def mask(prefixlen)
  return self.clone.mask!(prefixlen)
end
            
native() click to toggle source

Returns a new ipaddr built by converting the IPv6 address into a native IPv4 address. If the IP address is not an IPv4-mapped or IPv4-compatible IPv6 address, returns self.

 
               # File ipaddr.rb, line 283
def native
  if !ipv4_mapped? && !ipv4_compat?
    return self
  end
  return self.clone.set(@addr & IN4MASK, Socket::AF_INET)
end
            
reverse() click to toggle source

Returns a string for DNS reverse lookup. It returns a string in RFC3172 form for an IPv6 address.

 
               # File ipaddr.rb, line 292
def reverse
  case @family
  when Socket::AF_INET
    return _reverse + ".in-addr.arpa"
  when Socket::AF_INET6
    return ip6_arpa
  else
    raise "unsupported address family"
  end
end
            
succ() click to toggle source

Returns the successor to the ipaddr.

 
               # File ipaddr.rb, line 320
def succ
  return self.clone.set(@addr + 1, @family)
end
            
to_i() click to toggle source

Returns the integer representation of the ipaddr.

 
               # File ipaddr.rb, line 189
def to_i
  return @addr
end
            
to_range() click to toggle source

Creates a Range object for the network address.

 
               # File ipaddr.rb, line 335
def to_range
  begin_addr = (@addr & @mask_addr)

  case @family
  when Socket::AF_INET
    end_addr = (@addr | (IN4MASK ^ @mask_addr))
  when Socket::AF_INET6
    end_addr = (@addr | (IN6MASK ^ @mask_addr))
  else
    raise "unsupported address family"
  end

  return clone.set(begin_addr, @family)..clone.set(end_addr, @family)
end
            
to_s() click to toggle source

Returns a string containing the IP address representation.

 
               # File ipaddr.rb, line 194
def to_s
  str = to_string
  return str if ipv4?

  str.gsub!(/\b0{1,3}([\da-f]+)\b/i, '\1')
  loop do
    break if str.sub!(/\A0:0:0:0:0:0:0:0\Z/, '::')
    break if str.sub!(/\b0:0:0:0:0:0:0\b/, ':')
    break if str.sub!(/\b0:0:0:0:0:0\b/, ':')
    break if str.sub!(/\b0:0:0:0:0\b/, ':')
    break if str.sub!(/\b0:0:0:0\b/, ':')
    break if str.sub!(/\b0:0:0\b/, ':')
    break if str.sub!(/\b0:0\b/, ':')
    break
  end
  str.sub!(/:{3,}/, '::')

  if /\A::(ffff:)?([\da-f]{1,4}):([\da-f]{1,4})\Z/i =~ str
    str = sprintf('::%s%d.%d.%d.%d', $1, $2.hex / 256, $2.hex % 256, $3.hex / 256, $3.hex % 256)
  end

  str
end
            
to_string() click to toggle source

Returns a string containing the IP address representation in canonical form.

 
               # File ipaddr.rb, line 220
def to_string
  return _to_string(@addr)
end
            
|(other) click to toggle source

Returns a new ipaddr built by bitwise OR.

 
               # File ipaddr.rb, line 119
def |(other)
  return self.clone.set(@addr | coerce_other(other).to_i)
end
            
~() click to toggle source

Returns a new ipaddr built by bitwise negation.

 
               # File ipaddr.rb, line 134
def ~
  return self.clone.set(addr_mask(~@addr))
end
            

Protected Instance Methods

mask!(mask) click to toggle source
 
               # File ipaddr.rb, line 387
def mask!(mask)
  if mask.kind_of?(String)
    if mask =~ /^\d+$/
      prefixlen = mask.to_i
    else
      m = IPAddr.new(mask)
      if m.family != @family
        raise ArgumentError, "address family is not same"
      end
      @mask_addr = m.to_i
      @addr &= @mask_addr
      return self
    end
  else
    prefixlen = mask
  end
  case @family
  when Socket::AF_INET
    if prefixlen < 0 || prefixlen > 32
      raise ArgumentError, "invalid length"
    end
    masklen = 32 - prefixlen
    @mask_addr = ((IN4MASK >> masklen) << masklen)
  when Socket::AF_INET6
    if prefixlen < 0 || prefixlen > 128
      raise ArgumentError, "invalid length"
    end
    masklen = 128 - prefixlen
    @mask_addr = ((IN6MASK >> masklen) << masklen)
  else
    raise "unsupported address family"
  end
  @addr = ((@addr >> masklen) << masklen)
  return self
end
            
set(addr, *family) click to toggle source
 
               # File ipaddr.rb, line 367
def set(addr, *family)
  case family[0] ? family[0] : @family
  when Socket::AF_INET
    if addr < 0 || addr > IN4MASK
      raise ArgumentError, "invalid address"
    end
  when Socket::AF_INET6
    if addr < 0 || addr > IN6MASK
      raise ArgumentError, "invalid address"
    end
  else
    raise ArgumentError, "unsupported address family"
  end
  @addr = addr
  if family[0]
    @family = family[0]
  end
  return self
end
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.

blog comments powered by Disqus