Class: NetAddr::IPv4Net

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

Overview

IPv4Net represents an IPv4 network.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ip, m32) ⇒ IPv4Net

arguments:

  • ip - an IPv4 object

  • m32 - a Mask32 object. will default to a /32 if nil



9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/ipv4net.rb', line 9

def initialize(ip,m32)
	if (!ip.kind_of?(IPv4))
		raise ArgumentError, "Expected an IPv4 object for 'ip' but got a #{ip.class}."
	elsif (m32 != nil && !m32.kind_of?(Mask32))
		raise ArgumentError, "Expected a Mask32 object for 'm32' but got a #{m32.class}."
	end
	
	if (m32 == nil)
		m32 = Mask32.new(32)
	end
	@m32 = m32
	@base = IPv4.new(ip.addr & m32.mask)
end

Class Method Details

.parse(net) ⇒ Object

parse will create an IPv4Net from its string representation. Will default to a /32 netmask if not specified. Throws ValidationError on error.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/ipv4net.rb', line 25

def IPv4Net.parse(net)
	net = net.strip
	m32 = nil
	if (net.include?("/")) # cidr format
		addr,mask = net.split("/")
		m32 = Mask32.parse(mask)
	elsif (net.include?(" ") ) # extended format
		addr,mask = net.split(' ')
		m32 = Mask32.parse(mask)
	else
		addr = net
	end
	ip = IPv4.parse(addr)
	return IPv4Net.new(ip,m32)
end

Instance Method Details

#cmp(other) ⇒ Object

cmp compares equality with another IPv4Net. Return:

  • 1 if this IPv4Net is numerically greater

  • 0 if the two are equal

  • -1 if this IPv4Net 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.



53
54
55
56
57
58
59
60
61
62
# File 'lib/ipv4net.rb', line 53

def cmp(other)
	if (!other.kind_of?(IPv4Net))
		raise ArgumentError, "Expected an IPv4Net 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 IPv4Net contains the IPv4



65
66
67
68
69
70
71
72
73
# File 'lib/ipv4net.rb', line 65

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

#extendedObject

extended returns the IPv4Net in extended format (eg. x.x.x.x y.y.y.y)



42
43
44
# File 'lib/ipv4net.rb', line 42

def extended()
	return @base.to_s + " " + Util.int_to_IPv4(@m32.mask)
end

#fill(list) ⇒ Object

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



77
78
79
80
# File 'lib/ipv4net.rb', line 77

def fill(list)
	list = Util.filter_IPv4Net(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.



93
94
95
# File 'lib/ipv4net.rb', line 93

def len()
	return self.netmask.len
end

#netmaskObject

netmask returns the Mask32 object representing the netmask for this network



83
84
85
# File 'lib/ipv4net.rb', line 83

def netmask()
	@m32
end

#networkObject

network returns the IPv4 object representing the network address



88
89
90
# File 'lib/ipv4net.rb', line 88

def network()
	@base
end

#nextObject

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



98
99
100
101
102
103
104
# File 'lib/ipv4net.rb', line 98

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.



107
108
109
# File 'lib/ipv4net.rb', line 107

def next_sib()
	self.nth_next_sib(1)
end

#nth(index) ⇒ Object

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



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

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

#nth_subnet(prefix_len, index) ⇒ Object

nth_subnet returns the subnet IPv4Net 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.



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

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

#prevObject

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



136
137
138
139
# File 'lib/ipv4net.rb', line 136

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 0.0.0.0.



142
143
144
145
146
147
148
149
150
# File 'lib/ipv4net.rb', line 142

def prev_sib()
	if (self.network.addr == 0)
		return nil
	end
	
	shift = 32 - self.netmask.prefix_len
	addr = ((self.network.addr>>shift) - 1) << shift
	return IPv4Net.new(IPv4.new(addr), self.netmask)
end

#rel(other) ⇒ Object

rel determines the relationship to another IPv4Net. Returns:

  • 1 if this IPv4Net is the supernet of other

  • 0 if the two are equal

  • -1 if this IPv4Net is a subnet of other

  • nil if the networks are unrelated



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/ipv4net.rb', line 157

def rel(other)
	if (!other.kind_of?(IPv4Net))
		raise ArgumentError, "Expected an IPv4Net 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::F32
	otherHostmask = other.netmask.mask ^ NetAddr::F32
	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.



181
182
183
184
# File 'lib/ipv4net.rb', line 181

def resize(prefix_len)
	m32 = Mask32.new(prefix_len)
	return IPv4Net.new(self.network,m32)
end

#subnet_count(prefix_len) ⇒ Object

subnet_count returns the number a subnets of a given prefix length that this IPv4Net 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 32-bit integer (ie. if you want the # of /32 a /0 will hold)



189
190
191
192
193
194
# File 'lib/ipv4net.rb', line 189

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

#summ(other) ⇒ Object

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



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/ipv4net.rb', line 198

def summ(other)
	if (!other.kind_of?(IPv4Net))
		raise ArgumentError, "Expected an IPv4Net 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 = 32 - 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 IPv4Net as a String



219
220
221
# File 'lib/ipv4net.rb', line 219

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

#versionObject

version returns “4” for IPv4



224
225
226
# File 'lib/ipv4net.rb', line 224

def version()
	return 4
end