Class: IP::V6

Inherits:
IP
  • Object
show all
Defined in:
lib/ip/base.rb,
lib/ip/socket.rb

Constant Summary collapse

PROTO =
'v6'
ADDR_MAX =
340_282_366_920_938_463_463_374_607_431_768_211_455
ADDR_BITS =
128
MASK =
(1 << ADDR_BITS) - 1
ARPA =
'.ip6.arpa'
AF =
Socket::AF_INET6

Constants inherited from IP

PROTO_TO_CLASS, VERSION

Instance Attribute Summary

Attributes inherited from IP

#ctx, #pfxlen

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from IP

#&, #+, #-, #<=>, #^, #af, #broadcast, #deaggregate, #divide_by_hosts, #divide_by_subnets, #eql?, #freeze, from_cpal, #hash, #initialize, #inspect, #is_in?, #mask, #mask!, #netmask, #network, new_ntoh, ntop, #offset, #offset?, orig_new, #proto, #reset_pfxlen!, #size, #split, #succ, #succ!, #to_a, #to_addrlen, #to_ah, #to_b, #to_cpal, #to_cphl, #to_hex, #to_i, #to_irange, #to_range, #to_s, #to_sockaddr, #wildmask, #|, #~

Constructor Details

This class inherits a constructor from IP

Class Method Details

.parse(str) ⇒ Object

Parse a string; return an V6 instance if it’s a valid IPv6 address, nil otherwise – FIXME: allow larger variations of mapped addrs like 0:0:0:0:ffff:1.2.3.4 ++



448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
# File 'lib/ip/base.rb', line 448

def self.parse(str)
  case str
  when %r{\A\[?::(ffff:)?(\d+\.\d+\.\d+\.\d+)\]?(?:/(\d+))?(?:@(.*))?\z}i
    mapped = Regexp.last_match[1]
    pfxlen = (Regexp.last_match[3] || 128).to_i
    ctx = Regexp.last_match[4]
    return nil if pfxlen > 128

    v4 = (V4.parse(Regexp.last_match[2]) || return).to_i
    v4 |= 0xffff00000000 if mapped
    new(v4, pfxlen, ctx)
  when %r{\A\[?([0-9a-f:]+)\]?(?:/(\d+))?(?:@(.*))?\z}i
    addr = Regexp.last_match[1]
    pfxlen = (Regexp.last_match[2] || 128).to_i
    return nil if pfxlen > 128

    ctx = Regexp.last_match[3]
    return nil if pfxlen > 128

    if addr =~ /\A(.*?)::(.*)\z/
      left = Regexp.last_match[1]
      right = Regexp.last_match[2]
      l = left.split(':', -1)
      r = right.split(':', -1)
      rest = 8 - l.length - r.length
      return nil if rest < 0
    else
      l = addr.split(':')
      r = []
      rest = 0
      return nil if l.length != 8
    end
    out = ''
    l.each do |quad|
      return nil unless (1..4).include?(quad.length)

      out << quad.rjust(4, '0')
    end
    rest.times { out << '0000' }
    r.each do |quad|
      return nil unless (1..4).include?(quad.length)

      out << quad.rjust(4, '0')
    end
    new(out, pfxlen, ctx)
  end
end

Instance Method Details

#htonObject

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



529
530
531
# File 'lib/ip/base.rb', line 529

def hton
  (0..7).map { |i| (@addr >> (112 - 16 * i)) & 0xffff }.pack('n8')
end

#ipv4_compat?Boolean

Returns:

  • (Boolean)


548
549
550
# File 'lib/ip/base.rb', line 548

def ipv4_compat?
  @addr > 1 && (@addr >> 32) == 0
end

#ipv4_mapped?Boolean

Returns:

  • (Boolean)


544
545
546
# File 'lib/ip/base.rb', line 544

def ipv4_mapped?
  (@addr >> 32) == 0xffff
end

#nativeObject

Convert an IPv6 mapped/compat address to a V4 native address



553
554
555
556
557
# File 'lib/ip/base.rb', line 553

def native
  return self unless (ipv4_mapped? || ipv4_compat?) && (@pfxlen >= 96)

  V4.new(@addr & V4::MASK, @pfxlen - 96, @ctx)
end

#to_addrObject

Return just the address part as a String in compact decimal form



497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
# File 'lib/ip/base.rb', line 497

def to_addr
  if ipv4_compat?
    "::#{native.to_addr}"
  elsif ipv4_mapped?
    "::ffff:#{native.to_addr}"
  elsif @addr.zero?
    '::'
  else
    res = to_hex.scan(/..../).join(':')
    res.gsub!(/\b0{1,3}/, '')
    res.sub!(/\b0:0:0:0(:0)*\b/, ':') ||
      res.sub!(/\b0:0:0\b/, ':') ||
      res.sub!(/\b0:0\b/, ':')
    res.sub!(/:::+/, '::')
    res
  end
end

#to_addr_fullObject

Return just the address in non-compact form, required for reverse IP.



516
517
518
519
520
521
522
523
524
525
526
# File 'lib/ip/base.rb', line 516

def to_addr_full
  if ipv4_compat?
    "::#{native.to_addr}"
  elsif ipv4_mapped?
    "::ffff:#{native.to_addr}"
  elsif @addr.zero?
    '::'
  else
    to_hex.scan(/..../).join(':')
  end
end

#to_arpaObject

return the arpa version of the address for reverse DNS: en.wikipedia.org/wiki/Reverse_DNS_lookup



540
541
542
# File 'lib/ip/base.rb', line 540

def to_arpa
  to_nibbles.reverse.join('.') + ARPA
end

#to_nibblesObject

Returns the address broken into an array of 32 nibbles. Useful for to_arpa and use in SPF - tools.ietf.org/html/rfc7208#section-7.3



535
536
537
# File 'lib/ip/base.rb', line 535

def to_nibbles
  to_hex.rjust(32, '0').split(//)
end