Class: NetAddr::IPv6Net

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

Overview

IPv6Net represents an IPv6 network.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ip, m128) ⇒ IPv6Net

arguments:

  • ip - an IPv6 object

  • m128 - a Mask128 object. will default to a /64 if nil



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/ipv6net.rb', line 9

def initialize(ip,m128)
	if (!ip.kind_of?(IPv6))
		raise ArgumentError, "Expected an IPv6 object for 'ip' but got a #{ip.class}."
	elsif (m128 != nil && !m128.kind_of?(Mask128))
		raise ArgumentError, "Expected a Mask128 object for 'm128' but got a #{m128.class}."
	end
	
	if (m128 == nil)
		if (ip.addr != 0)
			m128 = Mask128.new(64) # use /64 mask per rfc 4291
		else
			m128 = Mask128.new(128) # use /128 mask per rfc 4291
		end
	end
	@m128 = m128
	@base = IPv6.new(ip.addr & m128.mask)
end

Class Method Details

.parse(net) ⇒ Object

parse will create an IPv6Net from its string representation. A default netmask will be used if not specified. Throws ValidationError on error.



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/ipv6net.rb', line 29

def IPv6Net.parse(net)
	m128 = nil
	net.strip!
	if (net.include?("/")) # cidr format
		addr,mask = net.split("/")
		m128 = Mask128.parse(mask)
	else
		addr = net
	end
	ip = IPv6.parse(addr)
	return IPv6Net.new(ip,m128)
end

Instance Method Details

#cmp(other) ⇒ Object

cmp compares equality with another IPv6Net. Return:

  • 1 if this IPv6Net is numerically greater

  • 0 if the two are equal

  • -1 if this IPv6Net is numerically less

The comparison is initially performed on using the cmp() method of the network address, however, in cases where the network addresses are identical then the netmasks will be compared with the cmp() method of the netmask.



49
50
51
52
53
54
55
56
57
58
# File 'lib/ipv6net.rb', line 49

def cmp(other)
	if (!other.kind_of?(IPv6Net))
		raise ArgumentError, "Expected an IPv6Net object for 'other' but got a #{other.class}."
	end
	cmp = self.network.cmp(other.network)
	if (cmp != 0)
		return cmp
	end
	return self.netmask.cmp(other.netmask)
end

#contains(ip) ⇒ Object

contains returns true if the IPv6Net contains the IPv6



61
62
63
64
65
66
67
68
69
# File 'lib/ipv6net.rb', line 61

def contains(ip)
	if (!ip.kind_of?(IPv6))
		raise ArgumentError, "Expected an IPv6 object for 'ip' but got a #{ip.class}."
	end
	if (@base.addr == ip.addr & @m128.mask)
		return true
	end
	return false
end

#fill(list) ⇒ Object

fill returns a copy of the given Array, stripped of any networks which are not subnets of this IPv6Net and with any missing gaps filled in.



73
74
75
76
# File 'lib/ipv6net.rb', line 73

def fill(list)
	list = Util.filter_IPv6Net(list)
	return Util.fill(self,list)
end

#lenObject

len returns the number of IP addresses in this network. It will return 0 for /0 networks.



79
80
81
# File 'lib/ipv6net.rb', line 79

def len()
	return self.netmask.len
end

#longObject

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



84
85
86
# File 'lib/ipv6net.rb', line 84

def long()
	return @base.long() + @m128.to_s
end

#netmaskObject

netmask returns the Mask128 object representing the netmask for this network



89
90
91
# File 'lib/ipv6net.rb', line 89

def netmask()
	@m128
end

#networkObject

network returns the IPv6 object representing the network address



94
95
96
# File 'lib/ipv6net.rb', line 94

def network()
	@base
end

#nextObject

next returns the next largest consecutive IP network or nil if the end of the address space is reached.



99
100
101
102
103
104
105
# File 'lib/ipv6net.rb', line 99

def next()
	net = self.nth_next_sib(1)
	if (!net)
		return nil
	end
	return net.grow
end

#next_sibObject

next_sib returns the network immediately following this one or nil if the end of the address space is reached.



108
109
110
# File 'lib/ipv6net.rb', line 108

def next_sib()
	self.nth_next_sib(1)
end

#nth(index) ⇒ Object

nth returns the IPv6 at the given index. The size of the network may be determined with the len() method. If the range is exceeded then return nil.



115
116
117
118
119
120
121
122
# File 'lib/ipv6net.rb', line 115

def nth(index)
	if (!index.kind_of?(Integer))
		raise ArgumentError, "Expected an Integer for 'index' but got a #{index.class}."
	elsif (self.netmask.prefix_len < 64 || (self.netmask.prefix_len > 64 && index >= self.len))
		return nil
	end
	return IPv6.new(self.network.addr + index)
end

#nth_subnet(prefix_len, index) ⇒ Object

nth_subnet returns the subnet IPv6Net at the given index. The number of subnets may be determined with the subnet_count() method. If the range is exceeded or an invalid prefix_len is provided then return nil.



127
128
129
130
131
132
133
134
# File 'lib/ipv6net.rb', line 127

def nth_subnet(prefix_len,index)
	count = self.subnet_count(prefix_len)
	if (count == 0 || index >= count)
		return nil
	end
	sub0 = IPv6Net.new(self.network, Mask128.new(prefix_len))
	return sub0.nth_next_sib(index)
end

#prevObject

prev returns the previous largest consecutive IP network or nil if this is ::.



137
138
139
140
# File 'lib/ipv6net.rb', line 137

def prev()
	net = self.grow
	return net.prev_sib
end

#prev_sibObject

prev_sib returns the network immediately preceding this one or nil if this network is ::.



143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/ipv6net.rb', line 143

def prev_sib()
	if (self.network.addr == 0)
		return nil
	end
	
	shift = 128 - self.netmask.prefix_len
	addr = ((self.network.addr>>shift) - 1) << shift
	if addr < 0
		return nil
	end
	return IPv6Net.new(IPv6.new(addr), self.netmask)
end

#rel(other) ⇒ Object

rel determines the relationship to another IPv6Net. Returns:

  • 1 if this IPv6Net is the supernet of other

  • 0 if the two are equal

  • -1 if this IPv6Net is a subnet of other

  • nil if the networks are unrelated



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/ipv6net.rb', line 161

def rel(other)
	if (!other.kind_of?(IPv6Net))
		raise ArgumentError, "Expected an IPv6Net object for 'other' but got a #{other.class}."
	end
	
	# when networks are equal then we can look exlusively at the netmask
	if (self.network.addr == other.network.addr)
		return self.netmask.cmp(other.netmask)
	end
	
	# when networks are not equal we can use hostmask to test if they are
	# related and which is the supernet vs the subnet
	hostmask = self.netmask.mask ^ NetAddr::F128
	otherHostmask = other.netmask.mask ^ NetAddr::F128
	if (self.network.addr|hostmask == other.network.addr|hostmask)
		return 1
	elsif (self.network.addr|otherHostmask == other.network.addr|otherHostmask)
		return -1
	end
	return nil
end

#resize(prefix_len) ⇒ Object

resize returns a copy of the network with an adjusted netmask. Throws ValidationError on invalid prefix_len.



185
186
187
188
# File 'lib/ipv6net.rb', line 185

def resize(prefix_len)
	m128 = Mask128.new(prefix_len)
	return IPv6Net.new(self.network,m128)
end

#subnet_count(prefix_len) ⇒ Object

subnet_count returns the number a subnets of a given prefix length that this IPv6Net contains. It will return 0 for invalid requests (ie. bad prefix or prefix is shorter than that of this network). It will also return 0 if the result exceeds the capacity of a 128-bit integer (ie. if you want the # of /128 a /0 will hold)



193
194
195
196
197
198
# File 'lib/ipv6net.rb', line 193

def subnet_count(prefix_len)
	if (prefix_len <= self.netmask.prefix_len || prefix_len > 128 || prefix_len - self.netmask.prefix_len >= 128)
		return 0
	end
	return 1 << (prefix_len - self.netmask.prefix_len)
end

#summ(other) ⇒ Object

summ creates a summary address from this IPv6Net and another. It returns nil if the two networks are incapable of being summarized.



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/ipv6net.rb', line 202

def summ(other)
	if (!other.kind_of?(IPv6Net))
		raise ArgumentError, "Expected an IPv6Net object for 'other' but got a #{other.class}."
	end
	
	# netmasks must be identical
	if (self.netmask.prefix_len != other.netmask.prefix_len)
		return nil
	end
	
	# merge-able networks will be identical if you right shift them by the number of bits in the hostmask + 1
	shift = 128 - self.netmask.prefix_len + 1
	addr = self.network.addr >> shift
	otherAddr = other.network.addr >> shift
	if (addr != otherAddr)
		return nil
	end
	return self.resize(self.netmask.prefix_len - 1)
end

#to_sObject

to_s returns the IPv6Net as a String



223
224
225
# File 'lib/ipv6net.rb', line 223

def to_s()
	return @base.to_s + @m128.to_s
end