Class: IPAddress::IPv6
Overview
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.
-
Leading zeroes: all the leading zeroes within a group can be omitted: “0008” would become “8”
-
A string of consecutive zeroes can be replaced by the string “::”. This can be only applied once.
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.
Direct Known Subclasses
Defined Under Namespace
Classes: Loopback, Mapped, Unspecified
Constant Summary collapse
- RE =
Regular expression to match an IPv6 address
%r{ #{part4} (?: : #{IPv4::INTERNAL_RE} )? \z }xo
- IN6FORMAT =
Format string to pretty print IPv6 addresses
Array.new(8, '%.4x').join(':')
- Prefix =
Prefix128- MAX_PREFIX =
Prefix::MAX
Constants inherited from IPAddress
Class Method Summary collapse
-
.compress(str) ⇒ Object
Compress an IPv6 address in its compressed form.
-
.expand(str) ⇒ Object
Expands an IPv6 address in the canocical form.
-
.groups(str) ⇒ Object
Extract 16 bits groups from a string.
-
.parse_data(str, prefix = MAX_PREFIX) ⇒ Object
Creates a new IPv6 object from binary data, like the one you get from a network stream.
-
.parse_hex(hex, prefix = MAX_PREFIX) ⇒ Object
Creates a new IPv6 object from a number expressed in hexdecimal format:.
-
.parse_i(i, prefix = MAX_PREFIX) ⇒ Object
(also: parse_u128)
Creates a new IPv6 object from an unsigned 128 bits integer.
Instance Method Summary collapse
-
#[](index) ⇒ Object
(also: #group)
Returns the 16-bits value specified by index.
-
#address ⇒ Object
Returns the IPv6 address in uncompressed form:.
-
#compressed ⇒ Object
Compressed form of the IPv6 address.
-
#data ⇒ Object
Returns the address portion of an IPv6 object in a network byte order format.
-
#groups ⇒ Object
Returns an array with the 16 bits groups in decimal format:.
-
#hexs ⇒ Object
Returns an array of the 16 bits groups in hexdecimal format:.
-
#initialize(str) ⇒ IPv6
constructor
Creates a new IPv6 address object.
-
#literal ⇒ Object
Literal version of the IPv6 address.
-
#loopback? ⇒ Boolean
Returns true if the address is a loopback address.
-
#mapped? ⇒ Boolean
Returns true if the address is a mapped address.
-
#prefix ⇒ Object
Returns an instance of the prefix object.
-
#reverse ⇒ Object
(also: #arpa)
Returns the IPv6 address in a DNS reverse lookup string, as per RFC3172 and RFC2874.
-
#to_hex ⇒ Object
Returns a Base16 number representing the IPv6 address.
-
#to_i ⇒ Object
(also: #u128, #to_u128)
Returns a decimal format (unsigned 128 bit) of the IPv6 address.
-
#to_s ⇒ Object
Returns the IPv6 address in a human readable form, using the compressed address.
-
#to_string_uncompressed ⇒ Object
Unlike its counterpart IPv6#to_string method, IPv6#to_string_uncompressed returns the whole IPv6 address and prefix in an uncompressed form.
-
#unspecified? ⇒ Boolean
Returns true if the address is an unspecified address.
- #version ⇒ Object
Methods inherited from IPAddress
#<=>, #at, #bits, #boundaries, #broadcast, #broadcast_i, #distance, #each, #each_host, #each_i, #exact_supernet, #first, #hash, #hosts, #include?, #include_all?, #include_exactly?, #inspect, #ipv4?, #ipv6?, #last, #mapped, #network, #network?, #network_i, #new_prefix, #overlap?, #overlap_i?, parse, #proper_supernet, #range, #size, #span, #span_i, #split, #subnet, subtract, #subtract, subtract!, #succ, #summarize, summarize, #supernet, #to_string, valid?, valid_ipv4?, valid_ipv4_netmask?, valid_ipv6?
Methods included from Conversions
#addr2ary, #addr2bits, #ary2addr, #ary2data, #ary2int, #bits2addr, #data2ary, #data2bits, #data2int, #int2addr, #int2ary, #int2data
Constructor Details
#initialize(str) ⇒ IPv6
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")
200 201 202 203 204 205 206 |
# File 'lib/ipaddress/ipv6.rb', line 200 def initialize(str) unless str =~ /:.+\./ @ip, @netmask = split_ip_and_netmask(str) else raise ArgumentError, "Use #{self.class}::Mapped for IPv4 mapped addresses" end end |
Class Method Details
.compress(str) ⇒ Object
Compress an IPv6 address in its compressed form
IPAddress::IPv6.compress("2001:0DB8:0000:CD30:0000:0000:0000:0000")
#=> "2001:db8:0:cd30::"
170 171 172 |
# File 'lib/ipaddress/ipv6.rb', line 170 def compress(str) new(str).compressed end |
.expand(str) ⇒ Object
Expands an IPv6 address in the canocical form
IPAddress::IPv6.("2001:0DB8:0:CD30::")
#=> "2001:0DB8:0000:CD30:0000:0000:0000:0000"
160 161 162 |
# File 'lib/ipaddress/ipv6.rb', line 160 def (str) new(str).address end |
.groups(str) ⇒ Object
Extract 16 bits groups from a string
177 178 179 180 |
# File 'lib/ipaddress/ipv6.rb', line 177 def groups(str) l, r = str.split('::', 2).map! { |i| i.split(':').map! { |j| j.hex } } l.concat(Array.new(8 - l.size - (r ||= []).size, 0)).concat(r) end |
.parse_data(str, prefix = MAX_PREFIX) ⇒ Object
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", 64)
ip6.to_s
#=> "2001:db8::8:800:200c:417a/64"
130 131 132 |
# File 'lib/ipaddress/ipv6.rb', line 130 def parse_data(str, prefix = MAX_PREFIX) instantiate { @groups, @netmask = str.unpack('n8'), prefix } end |
.parse_hex(hex, prefix = MAX_PREFIX) ⇒ Object
Creates a new IPv6 object from a number expressed in hexdecimal format:
ip6 = IPAddress::IPv6.parse_hex("20010db80000000000080800200c417a")
ip6.to_string
#=> "2001:db8::8:800:200c:417a/128"
The prefix parameter is optional:
ip6 = IPAddress::IPv6.parse_hex("20010db80000000000080800200c417a", 64)
ip6.to_string
#=> "2001:db8::8:800:200c:417a/64"
150 151 152 |
# File 'lib/ipaddress/ipv6.rb', line 150 def parse_hex(hex, prefix = MAX_PREFIX) parse_i(hex.hex, prefix) end |
.parse_i(i, prefix = MAX_PREFIX) ⇒ Object Also known as: parse_u128
Creates a new IPv6 object from an unsigned 128 bits integer.
ip6 = IPAddress::IPv6.parse_u128(42540766411282592856906245548098208122)
ip6.to_string
#=> "2001:db8::8:800:200c:417a/128"
The prefix parameter is optional:
ip6 = IPAddress::IPv6.parse_u128(42540766411282592856906245548098208122, 64)
ip6.to_string
#=> "2001:db8::8:800:200c:417a/64"
104 105 106 107 |
# File 'lib/ipaddress/ipv6.rb', line 104 def parse_i(i, prefix = MAX_PREFIX) groups = Array.new(8) { |j| i >> (112 - 16 * j) & 0xffff } instantiate { @groups, @netmask = groups, prefix } end |
Instance Method Details
#[](index) ⇒ Object Also known as: group
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
375 376 377 |
# File 'lib/ipaddress/ipv6.rb', line 375 def [](index) groups[index] end |
#address ⇒ Object
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"
220 221 222 |
# File 'lib/ipaddress/ipv6.rb', line 220 def address lazy_attr(:address) { IN6FORMAT % groups } end |
#compressed ⇒ Object
Compressed form of the IPv6 address
ip6 = IPAddress("2001:db8::8:800:200c:417a/64")
ip6.compressed
#=> "2001:db8::8:800:200c:417a"
232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/ipaddress/ipv6.rb', line 232 def compressed lazy_attr(:compressed) { r1, r2, q = /\b0(?::0)+\b/, /:{3,}/, '::' a, b = [s = groups.map { |i| i.to_s(16) }.join(':'), s.reverse].map! { |t| t.sub!(r1, q) && t.sub!(r2, q) || t } a.length > b.length ? b.reverse! : a } end |
#data ⇒ Object
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
357 358 359 |
# File 'lib/ipaddress/ipv6.rb', line 357 def data lazy_attr(:data) { groups.pack('n8') } end |
#groups ⇒ Object
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]
265 266 267 |
# File 'lib/ipaddress/ipv6.rb', line 265 def groups lazy_attr(:groups) { self.class.groups(@ip) } end |
#hexs ⇒ Object
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.
280 281 282 |
# File 'lib/ipaddress/ipv6.rb', line 280 def hexs lazy_attr(:hexs) { address.split(':') } end |
#literal ⇒ Object
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"
408 409 410 |
# File 'lib/ipaddress/ipv6.rb', line 408 def literal lazy_attr(:literal) { "#{address.tr(':', '-')}.ipv6-literal.net" } end |
#loopback? ⇒ Boolean
Returns true if the address is a loopback address
See IPAddress::IPv6::Loopback for more information
426 427 428 |
# File 'lib/ipaddress/ipv6.rb', line 426 def loopback? lazy_attr(:loopback_p) { prefix.max? && compressed == '::1' } end |
#mapped? ⇒ Boolean
Returns true if the address is a mapped address
See IPAddress::IPv6::Mapped for more information
435 436 437 |
# File 'lib/ipaddress/ipv6.rb', line 435 def mapped? lazy_attr(:mapped_p) { to_i >> 32 == 0xffff } end |
#prefix ⇒ Object
Returns an instance of the prefix object
ip6 = IPAddress("2001:db8::8:800:200c:417a/64")
ip6.prefix
#=> 64
252 253 254 |
# File 'lib/ipaddress/ipv6.rb', line 252 def prefix lazy_attr(:prefix, false) { Prefix.new(@netmask) } end |
#reverse ⇒ Object Also known as: arpa
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"
394 395 396 |
# File 'lib/ipaddress/ipv6.rb', line 394 def reverse lazy_attr(:reverse) { "#{to_hex.gsub(/(?=.)/, '.').reverse}ip6.arpa" } end |
#to_hex ⇒ Object
Returns a Base16 number representing the IPv6 address
ip6 = IPAddress("2001:db8::8:800:200c:417a/64")
ip6.to_hex
#=> "20010db80000000000080800200c417a"
293 294 295 |
# File 'lib/ipaddress/ipv6.rb', line 293 def to_hex lazy_attr(:to_hex) { hexs.join('') } end |
#to_i ⇒ Object Also known as: u128, to_u128
Returns a decimal format (unsigned 128 bit) of the IPv6 address
ip6 = IPAddress("2001:db8::8:800:200c:417a/64")
ip6.to_i
#=> 42540766411282592856906245548098208122
332 333 334 |
# File 'lib/ipaddress/ipv6.rb', line 332 def to_i lazy_attr(:int) { to_hex.hex } end |
#to_s ⇒ Object
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"
306 307 308 |
# File 'lib/ipaddress/ipv6.rb', line 306 def to_s compressed end |
#to_string_uncompressed ⇒ Object
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"
319 320 321 |
# File 'lib/ipaddress/ipv6.rb', line 319 def to_string_uncompressed "#{address}/#{prefix}" end |
#unspecified? ⇒ Boolean
Returns true if the address is an unspecified address
See IPAddress::IPv6::Unspecified for more information
417 418 419 |
# File 'lib/ipaddress/ipv6.rb', line 417 def unspecified? lazy_attr(:unspecified_p) { prefix.max? && compressed == '::' } end |
#version ⇒ Object
208 209 210 |
# File 'lib/ipaddress/ipv6.rb', line 208 def version 6 end |