Class: NetAddr::IPv6

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

Overview

IPv6 represents a single IPv6 address.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(i) ⇒ IPv6

Create an IPv6 from an Integer. Must be between 0 and 2**128-1. Throws ValidationError on error.



10
11
12
13
14
15
16
17
# File 'lib/ipv6.rb', line 10

def initialize(i)
	if (!i.kind_of?(Integer))
		raise ValidationError, "Expected an Integer for 'i' but got a #{i.class}."
	elsif ( (i < 0) || (i > NetAddr::F128) )
		raise ValidationError, "#{i} is out of bounds for IPv6."
	end
	@addr = i
end

Instance Attribute Details

#addrObject (readonly)

addr is the Integer representation of this IP address



6
7
8
# File 'lib/ipv6.rb', line 6

def addr
  @addr
end

Class Method Details

.parse(ip) ⇒ Object

parse will create an IPv6 from its string representation (ie. “1::”). Throws ValidationError on error.



21
22
23
24
25
# File 'lib/ipv6.rb', line 21

def IPv6.parse(ip)
	ip = ip.strip
	i = Util.parse_IPv6(ip)
	return IPv6.new(i)
end

Instance Method Details

#cmp(other) ⇒ Object

cmp compares equality with another IPv6. Return:

  • 1 if this IPv6 is numerically greater

  • 0 if the two are equal

  • -1 if this IPv6 is numerically less



31
32
33
34
35
36
37
38
39
40
41
# File 'lib/ipv6.rb', line 31

def cmp(other)
	if (!other.kind_of?(IPv6))
		raise ArgumentError, "Expected an IPv6 object for 'other' but got a #{other.class}."
	end
	if (self.addr > other.addr)
		return 1
	elsif (self.addr < other.addr)
		return -1
	end
	return 0
end

#ipv4(pl = 96) ⇒ Object

ipv4 generates an IPv4 from an IPv6 address. The IPv4 address is generated based on the mechanism described by RFC 6052. The argument pl (prefix length) should be one of: 32, 40, 48, 56, 64, or 96. Default is 96 unless one of the supported values is provided.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/ipv6.rb', line 45

def ipv4(pl=96)
	if (pl == 32)
		i = (@addr >> 64) # get bits 32-63 into position
		return IPv4.new(i & NetAddr::F32)
	elsif (pl == 40)
		i = (@addr >> 48) & 0xff # get the last 8 bits into position
		i2 = (@addr & 0xffffff0000000000000000) >> 56 # get first 24 bits into position
		return IPv4.new(i | i2)
	elsif (pl == 48)
		i = (@addr >> 40) & 0xffff # get the last 16 bits into position
		i2 = (@addr & 0xffff0000000000000000) >> 48 # get first 16 bits into position
		return IPv4.new(i | i2)
	elsif (pl == 56)
		i = (@addr >> 32) & 0xffffff # get the last 24 bits into position
		i2 = (@addr & 0xff0000000000000000) >> 40 # get first 8 bits into position
		return IPv4.new(i | i2)
	elsif (pl == 64)
		i = (@addr >> 24) # get the 32 bits into position
		return IPv4.new(i & NetAddr::F32)
	end
	return IPv4.new(@addr & NetAddr::F32)
end

#longObject

long returns the IPv6 as a string in long (uncompressed) format



69
70
71
72
73
74
75
76
# File 'lib/ipv6.rb', line 69

def long()
	words = []
	7.downto(0) do |x|
		word = (@addr >> 16*x) & 0xffff 
		words.push( word.to_s(16).rjust(4, "0") )
	end
	return words.join(':')
end

#nextObject

next returns the next consecutive IPv6 or nil if the address space is exceeded



79
80
81
82
83
84
# File 'lib/ipv6.rb', line 79

def next()
	if (self.addr == NetAddr::F128)
		return nil
	end
	return IPv6.new(self.addr + 1)
end

#prevObject

prev returns the preceding IPv6 or nil if this is 0.0.0.0



87
88
89
90
91
92
# File 'lib/ipv6.rb', line 87

def prev()
	if (self.addr == 0)
		return nil
	end
	return IPv6.new(self.addr - 1)
end

#to_netObject

to_net returns the IPv6 as a IPv6Net



95
96
97
# File 'lib/ipv6.rb', line 95

def to_net()
	NetAddr::IPv6Net.new(self,nil)
end

#to_sObject

to_s returns the IPv6 as a String in zero-compressed format (per rfc5952).



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/ipv6.rb', line 100

def to_s()
	hexStr = ["","","","","","","",""]
	zeroStart, consec0, finalStart, finalLen = -1,0,-1,0
	8.times do |i|
		# capture 2-byte word
		shift = 112 - 16*i
		wd = (self.addr >> shift) & 0xffff
		hexStr[i] = wd.to_s(16)
		
		# capture count of consecutive zeros
		if (wd == 0)
			if (zeroStart == -1)
				zeroStart = i
			end
			consec0 += 1
		end
		
		# test for longest consecutive zeros when non-zero encountered or we're at the end
		if (wd != 0 || i == 7)
			if (consec0 > finalStart+finalLen-1)
				finalStart = zeroStart
				finalLen = consec0
			end
			zeroStart = -1
			consec0 = 0
		end
	end
	
	# compress if we've found a series of zero fields in a row.
    # per https://tools.ietf.org/html/rfc5952#section-4.2.2 we must not compress just a single 16-bit zero field.
	if (finalLen > 1)
		head = hexStr[0,finalStart].join(":")
		tailStart = finalStart + finalLen 
		tail = hexStr[tailStart..7].join(":")
		return head + "::" + tail
	end
	return hexStr.join(":")
end

#versionObject

version returns “6” for IPv6



140
141
142
# File 'lib/ipv6.rb', line 140

def version()
	return 6
end