Class: RRs::IPv6

Inherits:
Object
  • Object
show all
Defined in:
lib/rrs/ipv6.rb

Constant Summary collapse

Regex_8Hex =

IPv6 address format a:b:c:d:e:f:g:h

/\A
(?:[0-9A-Fa-f]{1,4}:){7}
    [0-9A-Fa-f]{1,4}
\z/x
Regex_CompressedHex =

Compressed IPv6 address format a::b

/\A
((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
\z/x
Regex_6Hex4Dec =

IPv4 mapped IPv6 address format a:b:c:d:e:f:w.x.y.z

/\A
((?:[0-9A-Fa-f]{1,4}:){6,6})
(\d+)\.(\d+)\.(\d+)\.(\d+)
\z/x
Regex_CompressedHex4Dec =

Compressed IPv4 mapped IPv6 address format a::b:w.x.y.z

/\A
((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
((?:[0-9A-Fa-f]{1,4}:)*)
(\d+)\.(\d+)\.(\d+)\.(\d+)
\z/x
Regex_8HexLinkLocal =

IPv6 link local address format fe80:b:c:d:e:f:g:h%em1

/\A
[Ff][Ee]80
(?::[0-9A-Fa-f]{1,4}){7}
%[-0-9A-Za-z._~]+
\z/x
Regex_CompressedHexLinkLocal =

Compressed IPv6 link local address format fe80::b%em1

/\A
[Ff][Ee]80:
(?:
  ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
  ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
  |
  :((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
)?
:[0-9A-Fa-f]{1,4}%[-0-9A-Za-z._~]+
\z/x
Regex =

A composite IPv6 address Regexp.

/
(?:#{Regex_8Hex}) |
(?:#{Regex_CompressedHex}) |
(?:#{Regex_6Hex4Dec}) |
(?:#{Regex_CompressedHex4Dec}) |
(?:#{Regex_8HexLinkLocal}) |
(?:#{Regex_CompressedHexLinkLocal})
/x

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(address) ⇒ IPv6

:nodoc:



122
123
124
125
126
127
# File 'lib/rrs/ipv6.rb', line 122

def initialize(address) # :nodoc:
  unless address.kind_of?(String) && address.length == 16
    raise ArgumentError.new('IPv6 address must be 16 bytes')
  end
  @address = address
end

Instance Attribute Details

#addressObject (readonly)

The raw IPv6 address as a String.



132
133
134
# File 'lib/rrs/ipv6.rb', line 132

def address
  @address
end

Class Method Details

.create(arg) ⇒ Object

Creates a new IPv6 address from arg which may be:

IPv6

returns arg.

String

arg must match one of the IPv6::Regex* constants



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/rrs/ipv6.rb', line 76

def self.create(arg)
  case arg
  when IPv6
    return arg
  when String
    address = ''.b
    if Regex_8Hex =~ arg
      arg.scan(/[0-9A-Fa-f]+/) {|hex| address << [hex.hex].pack('n')}
    elsif Regex_CompressedHex =~ arg
      prefix = $1
      suffix = $2
      a1 = ''.b
      a2 = ''.b
      prefix.scan(/[0-9A-Fa-f]+/) {|hex| a1 << [hex.hex].pack('n')}
      suffix.scan(/[0-9A-Fa-f]+/) {|hex| a2 << [hex.hex].pack('n')}
      omitlen = 16 - a1.length - a2.length
      address << a1 << "\0" * omitlen << a2
    elsif Regex_6Hex4Dec =~ arg
      prefix, a, b, c, d = $1, $2.to_i, $3.to_i, $4.to_i, $5.to_i
      if (0..255) === a && (0..255) === b && (0..255) === c && (0..255) === d
        prefix.scan(/[0-9A-Fa-f]+/) {|hex| address << [hex.hex].pack('n')}
        address << [a, b, c, d].pack('CCCC')
      else
        raise ArgumentError.new("not numeric IPv6 address: " + arg)
      end
    elsif Regex_CompressedHex4Dec =~ arg
      prefix, suffix, a, b, c, d = $1, $2, $3.to_i, $4.to_i, $5.to_i, $6.to_i
      if (0..255) === a && (0..255) === b && (0..255) === c && (0..255) === d
        a1 = ''.b
        a2 = ''.b
        prefix.scan(/[0-9A-Fa-f]+/) {|hex| a1 << [hex.hex].pack('n')}
        suffix.scan(/[0-9A-Fa-f]+/) {|hex| a2 << [hex.hex].pack('n')}
        omitlen = 12 - a1.length - a2.length
        address << a1 << "\0" * omitlen << a2 << [a, b, c, d].pack('CCCC')
      else
        raise ArgumentError.new("not numeric IPv6 address: " + arg)
      end
    else
      raise ArgumentError.new("not numeric IPv6 address: " + arg)
    end
    return IPv6.new(address)
  else
    raise ArgumentError.new("cannot interpret as IPv6 address: #{arg.inspect}")
  end
end

Instance Method Details

#==(other) ⇒ Object

:nodoc:



142
143
144
# File 'lib/rrs/ipv6.rb', line 142

def ==(other) # :nodoc:
  return @address == other.address
end

#eql?(other) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


146
147
148
# File 'lib/rrs/ipv6.rb', line 146

def eql?(other) # :nodoc:
  return self == other
end

#hashObject

:nodoc:



150
151
152
# File 'lib/rrs/ipv6.rb', line 150

def hash # :nodoc:
  return @address.hash
end

#inspectObject

:nodoc:



138
139
140
# File 'lib/rrs/ipv6.rb', line 138

def inspect # :nodoc:
  return "#<#{self.class} #{self}>"
end

#to_sObject

:nodoc:



134
135
136
# File 'lib/rrs/ipv6.rb', line 134

def to_s # :nodoc:
  sprintf("%x:%x:%x:%x:%x:%x:%x:%x", *@address.unpack("nnnnnnnn")).sub(/(^|:)0(:0)+(:|$)/, '::')
end