Parent

Included Modules

IPAddress::IPv6

Name

IPAddress::IPv6 - IP version 6 address manipulation library

Synopsis

require 'ipaddress'

Description

Class IPAddress::IPv6 is used to handle IPv6 type addresses.

IPv6 addresses

IPv6 addresses are 128 bits long, in contrast with IPv4 addresses which are only 32 bits long. An IPv6 address is generally written as eight groups of four hexadecimal digits, each group representing 16 bits or two octect. For example, the following is a valid IPv6 address:

2001:0db8:0000:0000:0008:0800:200c:417a

Letters in an IPv6 address are usually written downcase, as per RFC. You can create a new IPv6 object using uppercase letters, but they will be converted.

Compression

Since IPv6 addresses are very long to write, there are some semplifications and compressions that you can use to shorten them.

Using compression, the IPv6 address written above can be shorten into the following, equivalent, address

2001:db8::8:800:200c:417a

This short version is often used in human representation.

Network Mask

As we used to do with IPv4 addresses, an IPv6 address can be written using the prefix notation to specify the subnet mask:

2001:db8::8:800:200c:417a/64

The /64 part means that the first 64 bits of the address are representing the network portion, and the last 64 bits are the host portion.

Constants

IN6FORMAT

Format string to pretty print IPv6 addresses

Public Class Methods

compress(str) click to toggle source

Compress an IPv6 address in its compressed form

IPAddress::IPv6.compress "2001:0DB8:0000:CD30:0000:0000:0000:0000"
  #=> "2001:db8:0:cd30::"
# File lib/ipaddress/ipv6.rb, line 514
def self.compress(str)
  self.new(str).compressed
end
expand(str) click to toggle source

Expands an IPv6 address in the canocical form

IPAddress::IPv6.expand "2001:0DB8:0:CD30::"
  #=> "2001:0DB8:0000:CD30:0000:0000:0000:0000"
# File lib/ipaddress/ipv6.rb, line 504
def self.expand(str)
  self.new(str).address
end
groups(str) click to toggle source

Extract 16 bits groups from a string

# File lib/ipaddress/ipv6.rb, line 546
def self.groups(str)
  l, r = if str =~ /^(.*)::(.*)$/
           [$1,$2].map {|i| i.split ":"}
         else
           [str.split(":"),[]]
         end
  (l + Array.new(8-l.size-r.size, '0') + r).map {|i| i.hex}
end
new(str) click to toggle source

Creates a new IPv6 address object.

An IPv6 address can be expressed in any of the following forms:

  • "2001:0db8:0000:0000:0008:0800:200C:417A": IPv6 address with no compression

  • "2001:db8:0:0:8:800:200C:417A": IPv6 address with leading zeros compression

  • "2001:db8::8:800:200C:417A": IPv6 address with full compression

In all these 3 cases, a new IPv6 address object will be created, using the default subnet mask /128

You can also specify the subnet mask as with IPv4 addresses:

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"
# File lib/ipaddress/ipv6.rb, line 89
def initialize(str)
  ip, netmask = str.split("/")

  if str =~ /:.+\./
    raise ArgumentError, "Please use #{self.class}::Mapped for IPv4 mapped addresses"
  end
  
  if IPAddress.valid_ipv6?(ip)
    @groups = self.class.groups(ip)
    @address = IN6FORMAT % @groups
    @compressed = compress_address
  else
    raise ArgumentError, "Invalid IP #{ip.inspect}"
  end

  @prefix = Prefix128.new(netmask ? netmask : 128)

end
parse_data(str) click to toggle source

Creates a new IPv6 object from binary data, like the one you get from a network stream.

For example, on a network stream the IP

"2001:db8::8:800:200c:417a"

is represented with the binary data

" \001\r\270\000\000\000\000\000\b\b\000 \fAz"

With that data you can create a new IPv6 object:

ip6 = IPAddress::IPv6::parse_data " \001\r\270\000\000\000\000\000\b\b\000 \fAz"
ip6.prefix = 64

ip6.to_s
  #=> "2001:db8::8:800:200c:417a/64"
# File lib/ipaddress/ipv6.rb, line 575
def self.parse_data(str)
  self.new(IN6FORMAT % str.unpack("n8"))
end
parse_hex(hex, prefix=128) click to toggle source

Creates a new IPv6 object from a number expressed in hexdecimal format:

ip6 = IPAddress::IPv6::parse_hex("20010db80000000000080800200c417a")
ip6.prefix = 64

ip6.to_string
  #=> "2001:db8::8:800:200c:417a/64"

The prefix parameter is optional:

ip6 = IPAddress::IPv6::parse_hex("20010db80000000000080800200c417a", 64)

ip6.to_string
  #=> "2001:db8::8:800:200c:417a/64"
# File lib/ipaddress/ipv6.rb, line 618
def self.parse_hex(hex, prefix=128)
  self.parse_u128(hex.hex, prefix)
end
parse_u128(u128, prefix=128) click to toggle source

Creates a new IPv6 object from an unsigned 128 bits integer.

ip6 = IPAddress::IPv6::parse_u128(42540766411282592856906245548098208122)
ip6.prefix = 64

ip6.to_string
  #=> "2001:db8::8:800:200c:417a/64"

The prefix parameter is optional:

ip6 = IPAddress::IPv6::parse_u128(42540766411282592856906245548098208122, 64)

ip6.to_string
  #=> "2001:db8::8:800:200c:417a/64"
# File lib/ipaddress/ipv6.rb, line 596
def self.parse_u128(u128, prefix=128)
  str = IN6FORMAT % (0..7).map{|i| (u128>>(112-16*i))&0xffff}
  self.new(str + "/#{prefix}")
end

Public Instance Methods

<=>(oth) click to toggle source

Spaceship operator to compare IPv6 objects

Comparing IPv6 addresses is useful to ordinate them into lists that match our intuitive perception of ordered IP addresses.

The first comparison criteria is the u128 value. For example, 2001:db8:1::1 will be considered to be less than 2001:db8:2::1, because, in a ordered list, we expect 2001:db8:1::1 to come before 2001:db8:2::1.

The second criteria, in case two IPv6 objects have identical addresses, is the prefix. An higher prefix will be considered greater than a lower prefix. This is because we expect to see 2001:db8:1::1/64 come before 2001:db8:1::1/65

Example:

ip1 = IPAddress "2001:db8:1::1/64"
ip2 = IPAddress "2001:db8:2::1/64"
ip3 = IPAddress "2001:db8:1::1/65"

ip1 < ip2
  #=> true
ip1 < ip3
  #=> false

[ip1,ip2,ip3].sort.map{|i| i.to_string}
  #=> ["2001:db8:1::1/64","2001:db8:1::1/65","2001:db8:2::1/64"]
# File lib/ipaddress/ipv6.rb, line 480
def <=>(oth)
  return prefix <=> oth.prefix if to_u128 == oth.to_u128  
  to_u128 <=> oth.to_u128
end
[](index) click to toggle source

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
# File lib/ipaddress/ipv6.rb, line 250
def [](index)
  @groups[index]
end
Also aliased as: group
address() click to toggle source

Returns the IPv6 address in uncompressed form:

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.address
  #=> "2001:0db8:0000:0000:0008:0800:200c:417a"
# File lib/ipaddress/ipv6.rb, line 116
def address
  @address
end
arpa() click to toggle source
Alias for: reverse
bits() click to toggle source

Returns the address portion of an IP in binary format, as a string containing a sequence of 0 and 1

ip6 = IPAddress("2001:db8::8:800:200c:417a")

ip6.bits 
  #=> "0010000000000001000011011011100000 [...] "
# File lib/ipaddress/ipv6.rb, line 494
def bits
  data.unpack("B*").first
end
broadcast_u128() click to toggle source

Returns the broadcast address in Unsigned 128bits format

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.broadcast_u128
  #=> 42540766411282592875350729025363378175

Please note that there is no Broadcast concept in IPv6 addresses as in IPv4 addresses, and this method is just an helper to other functions.

# File lib/ipaddress/ipv6.rb, line 343
def broadcast_u128
  network_u128 + size - 1
end
compressed() click to toggle source

Compressed form of the IPv6 address

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.compressed
  #=> "2001:db8::8:800:200c:417a"
# File lib/ipaddress/ipv6.rb, line 387
def compressed
  @compressed
end
data() click to toggle source

Returns the address portion of an IPv6 object in a network byte order format.

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.data
  #=> " \001\r\270\000\000\000\000\000\b\b\000 \fAz"

It is usually used to include an IP address in a data packet to be sent over a socket

a = Socket.open(params) # socket details here
ip6 = IPAddress "2001:db8::8:800:200c:417a/64"
binary_data = ["Address: "].pack("a*") + ip.data

# Send binary data
a.puts binary_data
# File lib/ipaddress/ipv6.rb, line 286
def data
  @groups.pack("n8")
end
each() click to toggle source

Iterates over all the IP addresses for the given network (or IP address).

The object yielded is a new IPv6 object created from the iteration.

ip6 = IPAddress("2001:db8::4/125")

ip6.each do |i|
  p i.compressed
end
  #=> "2001:db8::"
  #=> "2001:db8::1"
  #=> "2001:db8::2"
  #=> "2001:db8::3"
  #=> "2001:db8::4"
  #=> "2001:db8::5"
  #=> "2001:db8::6"
  #=> "2001:db8::7"

WARNING: if the host portion is very large, this method can be very slow and possibly hang your system!

# File lib/ipaddress/ipv6.rb, line 442
def each
  (network_u128..broadcast_u128).each do |i|
    yield self.class.parse_u128(i, @prefix)
  end
end
group(index) click to toggle source
Alias for: []
groups() click to toggle source

Returns an array with the 16 bits groups in decimal format:

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.groups
  #=> [8193, 3512, 0, 0, 8, 2048, 8204, 16762]
# File lib/ipaddress/ipv6.rb, line 129
def groups
  @groups
end
hexs() click to toggle source

Returns an array of the 16 bits groups in hexdecimal format:

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.hexs
  #=> ["2001", "0db8", "0000", "0000", "0008", "0800", "200c", "417a"]

Not to be confused with the similar IPv6#to_hex method.

# File lib/ipaddress/ipv6.rb, line 301
def hexs
  @address.split(":")
end
include?(oth) click to toggle source

Checks whether a subnet includes the given IP address.

Example:

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"
addr = IPAddress "2001:db8::8:800:200c:1/128"

ip6.include? addr
  #=> true

ip6.include? IPAddress("2001:db8:1::8:800:200c:417a/76")
  #=> false
# File lib/ipaddress/ipv6.rb, line 375
def include?(oth)
  @prefix <= oth.prefix and network_u128 == self.class.new(oth.address+"/#@prefix").network_u128
end
literal() click to toggle source

Literal version of the IPv6 address

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.literal
  #=> "2001-0db8-0000-0000-0008-0800-200c-417a.ipv6-literal.net"
# File lib/ipaddress/ipv6.rb, line 526
def literal
  @address.gsub(":","-") + ".ipv6-literal.net"
end
loopback?() click to toggle source

Returns true if the address is a loopback address

See IPAddress::IPv6::Loopback for more information

# File lib/ipaddress/ipv6.rb, line 405
def loopback?
  @prefix == 128 and @compressed == "::1"
end
mapped?() click to toggle source

Returns true if the address is a mapped address

See IPAddress::IPv6::Mapped for more information

# File lib/ipaddress/ipv6.rb, line 414
def mapped?
  to_u128 >> 32 == 0xffff
end
network() click to toggle source

Returns a new IPv6 object with the network number for the given IP.

ip = IPAddress "2001:db8:1:1:1:1:1:1/32" 

ip.network.to_string
  #=> "2001:db8::/32"
# File lib/ipaddress/ipv6.rb, line 539
def network
  self.class.parse_u128(network_u128, @prefix)
end
network?() click to toggle source

True if the IPv6 address is a network

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.network?
  #=> false

ip6 = IPAddress "2001:db8:8:800::/64"

ip6.network?
  #=> true
# File lib/ipaddress/ipv6.rb, line 232
def network?
  to_u128 | @prefix.to_u128 == @prefix.to_u128
end
network_u128() click to toggle source

Returns the network number in Unsigned 128bits format

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.network_u128
  #=> 42540766411282592856903984951653826560
# File lib/ipaddress/ipv6.rb, line 327
def network_u128
  to_u128 & @prefix.to_u128
end
prefix() click to toggle source

Returns an instance of the prefix object

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.prefix
  #=> 64
# File lib/ipaddress/ipv6.rb, line 141
def prefix
  @prefix
end
prefix=(num) click to toggle source

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.

ip6 = IPAddress("2001:db8::8:800:200c:417a")

puts ip6.to_string
  #=> "2001:db8::8:800:200c:417a/128"

ip6.prefix = 64
puts ip6.to_string
  #=> "2001:db8::8:800:200c:417a/64"
# File lib/ipaddress/ipv6.rb, line 162
def prefix=(num)
  @prefix = Prefix128.new(num)
end
reverse() click to toggle source

Returns the IPv6 address in a DNS reverse lookup string, as per RFC3172 and RFC2874.

ip6 = IPAddress "3ffe:505:2::f"

ip6.reverse
  #=> "f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.arpa"
# File lib/ipaddress/ipv6.rb, line 314
def reverse
  to_hex.reverse.gsub(/./){|c| c+"."} + "ip6.arpa"
end
Also aliased as: arpa
size() click to toggle source

Returns the number of IP addresses included in the network. It also counts the network address and the broadcast address.

ip6 = IPAddress("2001:db8::8:800:200c:417a/64")

ip6.size
  #=> 18446744073709551616
# File lib/ipaddress/ipv6.rb, line 357
def size
  2 ** @prefix.host_prefix
end
to_hex() click to toggle source

Returns a Base16 number representing the IPv6 address

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.to_hex
  #=> "20010db80000000000080800200c417a"
# File lib/ipaddress/ipv6.rb, line 264
def to_hex
  hexs.join("")
end
to_i() click to toggle source

Returns a decimal format (unsigned 128 bit) of the IPv6 address

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.to_i
  #=> 42540766411282592856906245548098208122
# File lib/ipaddress/ipv6.rb, line 214
def to_i
  to_hex.hex
end
Also aliased as: to_u128
to_s() click to toggle source

Returns the IPv6 address in a human readable form, using the compressed address.

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.to_s
  #=> "2001:db8::8:800:200c:417a"
# File lib/ipaddress/ipv6.rb, line 201
def to_s
  @compressed
end
to_string() click to toggle source

Returns the IPv6 address in a human readable form, using the compressed address.

ip6 = IPAddress "2001:0db8:0000:0000:0008:0800:200c:417a/64"

ip6.to_string
  #=> "2001:db8::8:800:200c:417a/64"
# File lib/ipaddress/ipv6.rb, line 188
def to_string
  "#@compressed/#@prefix"
end
to_string_uncompressed() click to toggle source

Unlike its counterpart IPv6#to_string method, IPv6#to_string_uncompressed returns the whole IPv6 address and prefix in an uncompressed form

ip6 = IPAddress "2001:db8::8:800:200c:417a/64"

ip6.to_string_uncompressed
  #=> "2001:0db8:0000:0000:0008:0800:200c:417a/64"
# File lib/ipaddress/ipv6.rb, line 175
def to_string_uncompressed
  "#@address/#@prefix"
end
to_u128() click to toggle source
Alias for: to_i
unspecified?() click to toggle source

Returns true if the address is an unspecified address

See IPAddress::IPv6::Unspecified for more information

# File lib/ipaddress/ipv6.rb, line 396
def unspecified?
  @prefix == 128 and @compressed == "::"
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.