netaddr 2.0.3 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/LICENSE +0 -0
- data/README.md +0 -0
- data/lib/eui48.rb +0 -0
- data/lib/eui64.rb +0 -0
- data/lib/ipv4.rb +6 -1
- data/lib/ipv4net.rb +6 -1
- data/lib/ipv6.rb +34 -3
- data/lib/ipv6net.rb +6 -1
- data/lib/mask128.rb +4 -2
- data/lib/mask32.rb +11 -5
- data/lib/netaddr.rb +18 -0
- data/lib/util.rb +106 -43
- data/test/eui48_test.rb +0 -0
- data/test/eui64_test.rb +0 -0
- data/test/examples.rb +0 -0
- data/test/ipv4_test.rb +0 -0
- data/test/ipv4net_test.rb +29 -0
- data/test/ipv6_test.rb +39 -0
- data/test/ipv6net_test.rb +44 -2
- data/test/mask128_test.rb +0 -0
- data/test/mask32_test.rb +5 -0
- data/test/netaddr_test.rb +22 -0
- data/test/run_all.rb +0 -0
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 13e871a188dbf2b94f5c57fe638c5dac249792134a8eece5386fbc36d1ea88d6
|
4
|
+
data.tar.gz: 14e02af771158f3003e49181ed49fe7e2fa8d201991215bda51fc2a48b15a96a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c1baeafeba2d571e007da5ed16276c3fadccb9be542ea47922878ba2e9889e8912145482db9b3c10f2aad3a7a19005ad0499005f71f893bb2db1e7806db1ed2
|
7
|
+
data.tar.gz: 3a287b3d7cb1f87cc46e50fefc54952c80e2ff43581492328a27091605db7937cde768d5003d9eeda201ee5e1b353de86e4602bf093bea497bac3403612f6e0f
|
data/LICENSE
CHANGED
File without changes
|
data/README.md
CHANGED
File without changes
|
data/lib/eui48.rb
CHANGED
File without changes
|
data/lib/eui64.rb
CHANGED
File without changes
|
data/lib/ipv4.rb
CHANGED
@@ -19,7 +19,7 @@ module NetAddr
|
|
19
19
|
# parse will create an IPv4 from its string representation (ie. "192.168.1.1").
|
20
20
|
# Throws ValidationError on error.
|
21
21
|
def IPv4.parse(ip)
|
22
|
-
ip.strip
|
22
|
+
ip = ip.strip
|
23
23
|
i = Util.parse_IPv4(ip)
|
24
24
|
return IPv4.new(i)
|
25
25
|
end
|
@@ -77,6 +77,11 @@ module NetAddr
|
|
77
77
|
Util.int_to_IPv4(@addr)
|
78
78
|
end
|
79
79
|
|
80
|
+
# version returns "4" for IPv4
|
81
|
+
def version()
|
82
|
+
return 4
|
83
|
+
end
|
84
|
+
|
80
85
|
end # end class IPv4
|
81
86
|
|
82
87
|
end # end module
|
data/lib/ipv4net.rb
CHANGED
@@ -23,7 +23,7 @@ module NetAddr
|
|
23
23
|
# parse will create an IPv4Net from its string representation. Will default to a /32 netmask if not specified.
|
24
24
|
# Throws ValidationError on error.
|
25
25
|
def IPv4Net.parse(net)
|
26
|
-
net.strip
|
26
|
+
net = net.strip
|
27
27
|
m32 = nil
|
28
28
|
if (net.include?("/")) # cidr format
|
29
29
|
addr,mask = net.split("/")
|
@@ -220,6 +220,11 @@ module NetAddr
|
|
220
220
|
return @base.to_s + @m32.to_s
|
221
221
|
end
|
222
222
|
|
223
|
+
# version returns "4" for IPv4
|
224
|
+
def version()
|
225
|
+
return 4
|
226
|
+
end
|
227
|
+
|
223
228
|
|
224
229
|
protected
|
225
230
|
|
data/lib/ipv6.rb
CHANGED
@@ -19,7 +19,7 @@ module NetAddr
|
|
19
19
|
# parse will create an IPv6 from its string representation (ie. "1::").
|
20
20
|
# Throws ValidationError on error.
|
21
21
|
def IPv6.parse(ip)
|
22
|
-
ip.strip
|
22
|
+
ip = ip.strip
|
23
23
|
i = Util.parse_IPv6(ip)
|
24
24
|
return IPv6.new(i)
|
25
25
|
end
|
@@ -40,6 +40,31 @@ module NetAddr
|
|
40
40
|
return 0
|
41
41
|
end
|
42
42
|
|
43
|
+
# ipv4 generates an IPv4 from an IPv6 address. The IPv4 address is generated based on the mechanism described by RFC 6052.
|
44
|
+
# 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
|
+
def ipv4(pl=96)
|
46
|
+
if (pl == 32)
|
47
|
+
i = (@addr >> 64) # get bits 32-63 into position
|
48
|
+
return IPv4.new(i & NetAddr::F32)
|
49
|
+
elsif (pl == 40)
|
50
|
+
i = (@addr >> 48) & 0xff # get the last 8 bits into position
|
51
|
+
i2 = (@addr & 0xffffff0000000000000000) >> 56 # get first 24 bits into position
|
52
|
+
return IPv4.new(i | i2)
|
53
|
+
elsif (pl == 48)
|
54
|
+
i = (@addr >> 40) & 0xffff # get the last 16 bits into position
|
55
|
+
i2 = (@addr & 0xffff0000000000000000) >> 48 # get first 16 bits into position
|
56
|
+
return IPv4.new(i | i2)
|
57
|
+
elsif (pl == 56)
|
58
|
+
i = (@addr >> 32) & 0xffffff # get the last 24 bits into position
|
59
|
+
i2 = (@addr & 0xff0000000000000000) >> 40 # get first 8 bits into position
|
60
|
+
return IPv4.new(i | i2)
|
61
|
+
elsif (pl == 64)
|
62
|
+
i = (@addr >> 24) # get the 32 bits into position
|
63
|
+
return IPv4.new(i & NetAddr::F32)
|
64
|
+
end
|
65
|
+
return IPv4.new(@addr & NetAddr::F32)
|
66
|
+
end
|
67
|
+
|
43
68
|
# long returns the IPv6 as a string in long (uncompressed) format
|
44
69
|
def long()
|
45
70
|
words = []
|
@@ -100,8 +125,9 @@ module NetAddr
|
|
100
125
|
end
|
101
126
|
end
|
102
127
|
|
103
|
-
# compress if we've found a series of
|
104
|
-
|
128
|
+
# compress if we've found a series of zero fields in a row.
|
129
|
+
# per https://tools.ietf.org/html/rfc5952#section-4.2.2 we must not compress just a single 16-bit zero field.
|
130
|
+
if (finalLen > 1)
|
105
131
|
head = hexStr[0,finalStart].join(":")
|
106
132
|
tailStart = finalStart + finalLen
|
107
133
|
tail = hexStr[tailStart..7].join(":")
|
@@ -110,6 +136,11 @@ module NetAddr
|
|
110
136
|
return hexStr.join(":")
|
111
137
|
end
|
112
138
|
|
139
|
+
# version returns "6" for IPv6
|
140
|
+
def version()
|
141
|
+
return 6
|
142
|
+
end
|
143
|
+
|
113
144
|
end # end class IPv6
|
114
145
|
|
115
146
|
end # end module
|
data/lib/ipv6net.rb
CHANGED
@@ -28,7 +28,7 @@ module NetAddr
|
|
28
28
|
# Throws ValidationError on error.
|
29
29
|
def IPv6Net.parse(net)
|
30
30
|
m128 = nil
|
31
|
-
net.strip
|
31
|
+
net = net.strip
|
32
32
|
if (net.include?("/")) # cidr format
|
33
33
|
addr,mask = net.split("/")
|
34
34
|
m128 = Mask128.parse(mask)
|
@@ -224,6 +224,11 @@ module NetAddr
|
|
224
224
|
return @base.to_s + @m128.to_s
|
225
225
|
end
|
226
226
|
|
227
|
+
# version returns "6" for IPv6
|
228
|
+
def version()
|
229
|
+
return 6
|
230
|
+
end
|
231
|
+
|
227
232
|
|
228
233
|
protected
|
229
234
|
|
data/lib/mask128.rb
CHANGED
@@ -26,11 +26,13 @@ module NetAddr
|
|
26
26
|
#
|
27
27
|
# Throws ValidationError on error.
|
28
28
|
def Mask128.parse(mask)
|
29
|
-
mask.strip
|
29
|
+
mask = mask.strip
|
30
30
|
if (mask.start_with?("/")) # cidr format
|
31
31
|
mask = mask[1..-1] # remove "/"
|
32
32
|
end
|
33
|
-
return Mask128.new(mask
|
33
|
+
return Mask128.new(Integer(mask))
|
34
|
+
rescue ArgumentError
|
35
|
+
raise ValidationError, "#{mask} is not valid integer."
|
34
36
|
end
|
35
37
|
|
36
38
|
#cmp compares equality with another Mask128. Return:
|
data/lib/mask32.rb
CHANGED
@@ -26,11 +26,17 @@ module NetAddr
|
|
26
26
|
#
|
27
27
|
# Throws ValidationError on error.
|
28
28
|
def Mask32.parse(mask)
|
29
|
-
mask.strip
|
29
|
+
mask = mask.strip
|
30
30
|
if (mask.start_with?("/")) # cidr format
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
mask = mask[1..-1] # remove "/"
|
32
|
+
end
|
33
|
+
|
34
|
+
if (!mask.include?("."))
|
35
|
+
begin
|
36
|
+
return Mask32.new(Integer(mask))
|
37
|
+
rescue ArgumentError
|
38
|
+
raise ValidationError, "#{mask} is not valid integer."
|
39
|
+
end
|
34
40
|
end
|
35
41
|
|
36
42
|
# for extended netmask
|
@@ -62,7 +68,7 @@ module NetAddr
|
|
62
68
|
|
63
69
|
# extended returns the Mask32 in extended format (eg. x.x.x.x)
|
64
70
|
def extended()
|
65
|
-
Util.
|
71
|
+
Util.int_to_IPv4(@mask)
|
66
72
|
end
|
67
73
|
|
68
74
|
#cmp compares equality with another Mask32. Return:
|
data/lib/netaddr.rb
CHANGED
@@ -37,6 +37,24 @@ module NetAddr
|
|
37
37
|
end
|
38
38
|
module_function :ipv4_prefix_len
|
39
39
|
|
40
|
+
## parse_ip parses a string into an IPv4 or IPv6
|
41
|
+
def parse_ip(ip)
|
42
|
+
if (ip.include?(":"))
|
43
|
+
return IPv6.parse(ip)
|
44
|
+
end
|
45
|
+
return IPv4.parse(ip)
|
46
|
+
end
|
47
|
+
module_function :parse_ip
|
48
|
+
|
49
|
+
## parse_net parses a string into an IPv4Net or IPv6Net
|
50
|
+
def parse_net(net)
|
51
|
+
if (net.include?(":"))
|
52
|
+
return IPv6Net.parse(net)
|
53
|
+
end
|
54
|
+
return IPv4Net.parse(net)
|
55
|
+
end
|
56
|
+
module_function :parse_net
|
57
|
+
|
40
58
|
# sort_IPv4 sorts a list of IPv4 objects in ascending order.
|
41
59
|
# It will return a new list with any non IPv4 objects removed.
|
42
60
|
def sort_IPv4(list)
|
data/lib/util.rb
CHANGED
@@ -23,35 +23,33 @@ module NetAddr
|
|
23
23
|
|
24
24
|
# discard_subnets returns a copy of the IPv4NetList with any entries which are subnets of other entries removed.
|
25
25
|
def Util.discard_subnets(list)
|
26
|
-
|
27
|
-
supernets = []
|
26
|
+
keepers = []
|
28
27
|
last = list[list.length-1]
|
28
|
+
keep_last = true
|
29
29
|
list.each do |net|
|
30
30
|
rel = last.rel(net)
|
31
|
-
if (!rel)
|
32
|
-
|
33
|
-
elsif (rel == -1) #
|
34
|
-
|
31
|
+
if (!rel) # keep unrelated nets
|
32
|
+
keepers.push(net)
|
33
|
+
elsif (rel == -1) # keep supernets, but do not keep last
|
34
|
+
keepers.push(net)
|
35
|
+
keep_last = false
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
|
-
|
39
|
-
if (
|
40
|
-
|
41
|
-
else
|
42
|
-
cleaned.push(last)
|
39
|
+
# recursively clean up keepers
|
40
|
+
if (keepers.length > 0)
|
41
|
+
keepers = discard_subnets(keepers)
|
43
42
|
end
|
44
|
-
|
45
|
-
|
46
|
-
cleaned.concat( discard_subnets(unrelated) )
|
43
|
+
if keep_last
|
44
|
+
keepers.unshift(last)
|
47
45
|
end
|
48
|
-
return
|
46
|
+
return keepers
|
49
47
|
end
|
50
48
|
|
51
49
|
# fill returns a copy of the given Array, stripped of any networks which are not subnets of ipnet
|
52
50
|
# and with any missing gaps filled in.
|
53
51
|
def Util.fill(ipnet,list)
|
54
|
-
# sort &
|
52
|
+
# sort & get rid of non subnets
|
55
53
|
subs = []
|
56
54
|
discard_subnets(list).each do |sub|
|
57
55
|
r = ipnet.rel(sub)
|
@@ -69,21 +67,14 @@ module NetAddr
|
|
69
67
|
filled = backfill(subs[0],base)
|
70
68
|
end
|
71
69
|
|
72
|
-
# fill gaps
|
73
|
-
sib = ipnet.next_sib()
|
74
|
-
ceil = NetAddr::F32
|
75
|
-
if (sib != nil)
|
76
|
-
ceil = sib.network.addr
|
77
|
-
end
|
78
|
-
|
70
|
+
# fill gaps between subnets
|
79
71
|
0.upto(subs.length-1) do |i|
|
80
72
|
sub = subs[i]
|
81
|
-
filled.push(sub)
|
82
|
-
limit = ceil
|
83
73
|
if (i+1 < subs.length)
|
84
|
-
|
74
|
+
filled.concat( fwdfill(sub,ipnet,subs[i+1]) )
|
75
|
+
else
|
76
|
+
filled.concat( fwdfill(sub,ipnet,nil) )
|
85
77
|
end
|
86
|
-
filled.concat( fwdfill(sub,limit) )
|
87
78
|
end
|
88
79
|
end
|
89
80
|
return filled
|
@@ -133,18 +124,80 @@ module NetAddr
|
|
133
124
|
return filtered
|
134
125
|
end
|
135
126
|
|
136
|
-
# fwdfill returns subnets between given IPv4Net/IPv6Nett and the limit address.
|
137
|
-
|
138
|
-
|
139
|
-
nets = []
|
127
|
+
# fwdfill returns subnets between given IPv4Net/IPv6Nett and the limit address. limit should be > ipnet.
|
128
|
+
def Util.fwdfill(ipnet,supernet,limit)
|
129
|
+
nets = [ipnet]
|
140
130
|
cur = ipnet
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
131
|
+
if (limit != nil) # if limit, then fill gaps between net and limit
|
132
|
+
while true do
|
133
|
+
nextSub = cur.next()
|
134
|
+
# ensure we've not exceed the total address space
|
135
|
+
if (nextSub == nil)
|
136
|
+
break
|
137
|
+
end
|
138
|
+
# ensure we've not exceeded the address space of supernet
|
139
|
+
if (supernet.rel(nextSub) == nil)
|
140
|
+
break
|
141
|
+
end
|
142
|
+
# ensure we've not hit limit
|
143
|
+
if (nextSub.network.addr == limit.network.addr)
|
144
|
+
break
|
145
|
+
end
|
146
|
+
|
147
|
+
# check relationship to limit
|
148
|
+
if (nextSub.rel(limit) != nil) # if related, then nextSub must be a supernet of limit. we need to shrink it.
|
149
|
+
prefixLen = nextSub.netmask.prefix_len
|
150
|
+
while true do
|
151
|
+
prefixLen += 1
|
152
|
+
if (nextSub.kind_of?(IPv4Net))
|
153
|
+
nextSub = IPv4Net.new(nextSub.network, Mask32.new(prefixLen))
|
154
|
+
else
|
155
|
+
nextSub = IPv6Net.new(nextSub.network, Mask128.new(prefixLen))
|
156
|
+
end
|
157
|
+
if (nextSub.rel(limit) == nil) # stop when we no longer overlap with limit
|
158
|
+
break
|
159
|
+
end
|
160
|
+
end
|
161
|
+
else # otherwise, if unrelated then grow until we hit the limit
|
162
|
+
prefixLen = nextSub.netmask.prefix_len
|
163
|
+
mask = nextSub.netmask.mask
|
164
|
+
while true do
|
165
|
+
prefixLen -= 1
|
166
|
+
if (prefixLen == supernet.netmask.prefix_len) # break if we've hit the supernet boundary
|
167
|
+
break
|
168
|
+
end
|
169
|
+
mask = mask << 1
|
170
|
+
if (nextSub.network.addr|mask != mask) # break when bit boundary crossed (there are '1' bits in the host portion)
|
171
|
+
break
|
172
|
+
end
|
173
|
+
if (nextSub.kind_of?(IPv4Net))
|
174
|
+
grown = IPv4Net.new(nextSub.network, Mask32.new(prefixLen))
|
175
|
+
else
|
176
|
+
grown = IPv6Net.new(nextSub.network, Mask128.new(prefixLen))
|
177
|
+
end
|
178
|
+
if (grown.rel(limit) != nil) # if we've overlapped with limit in any way, then break
|
179
|
+
break
|
180
|
+
end
|
181
|
+
nextSub = grown
|
182
|
+
end
|
183
|
+
end
|
184
|
+
nets.push(nextSub)
|
185
|
+
cur = nextSub
|
186
|
+
end
|
187
|
+
else # if no limit, then get next largest sibs until we've exceeded supernet
|
188
|
+
while true do
|
189
|
+
nextSub = cur.next()
|
190
|
+
# ensure we've not exceed the total address space
|
191
|
+
if (nextSub == nil)
|
192
|
+
break
|
193
|
+
end
|
194
|
+
# ensure we've not exceeded the address space of supernet
|
195
|
+
if (supernet.rel(nextSub) == nil)
|
196
|
+
break
|
197
|
+
end
|
198
|
+
nets.push(nextSub)
|
199
|
+
cur = nextSub
|
145
200
|
end
|
146
|
-
nets.push(net)
|
147
|
-
cur = net
|
148
201
|
end
|
149
202
|
return nets
|
150
203
|
end
|
@@ -166,8 +219,7 @@ module NetAddr
|
|
166
219
|
raise ValidationError, "#{ip} contains invalid characters."
|
167
220
|
end
|
168
221
|
|
169
|
-
ip.strip
|
170
|
-
octets = ip.split('.')
|
222
|
+
octets = ip.strip.split('.')
|
171
223
|
if (octets.length != 4)
|
172
224
|
raise ValidationError, "IPv4 requires (4) octets."
|
173
225
|
end
|
@@ -188,14 +240,24 @@ module NetAddr
|
|
188
240
|
# parse_IPv6 parses an IPv6 address String into an Integer
|
189
241
|
def Util.parse_IPv6(ip)
|
190
242
|
# check that only valid characters are present
|
191
|
-
if (ip =~ /[^0-9a-fA-F
|
243
|
+
if (ip =~ /[^0-9a-fA-F\:.]/)
|
192
244
|
raise ValidationError, "#{ip} contains invalid characters."
|
193
245
|
end
|
194
246
|
|
195
|
-
ip.strip
|
247
|
+
ip = ip.strip
|
196
248
|
if (ip == "::")
|
197
249
|
return 0 # zero address
|
198
250
|
end
|
251
|
+
ipv4Int = nil
|
252
|
+
if (ip.include?(".")) # check for ipv4 embedded addresses
|
253
|
+
words = ip.split(":")
|
254
|
+
begin
|
255
|
+
ipv4Int = Util.parse_IPv4(words.last)
|
256
|
+
rescue
|
257
|
+
raise ValidationError, "IPv4-embedded IPv6 address is invalid."
|
258
|
+
end
|
259
|
+
ip = ip.sub(words.last,"0:0") # temporarily remove the ipv4 portion
|
260
|
+
end
|
199
261
|
words = []
|
200
262
|
if (ip.include?("::")) # short format
|
201
263
|
if (ip =~ /:{3,}/) # make sure only i dont have ":::"
|
@@ -231,7 +293,6 @@ module NetAddr
|
|
231
293
|
raise ValidationError, "#{ip} is too short."
|
232
294
|
end
|
233
295
|
end
|
234
|
-
|
235
296
|
ipInt = 0
|
236
297
|
i = 8
|
237
298
|
words.each do |word|
|
@@ -239,7 +300,9 @@ module NetAddr
|
|
239
300
|
word = word.to_i(16) << (16*i)
|
240
301
|
ipInt = ipInt | word
|
241
302
|
end
|
242
|
-
|
303
|
+
if ipv4Int # re-add ipv4 portion if present
|
304
|
+
ipInt = ipInt | ipv4Int
|
305
|
+
end
|
243
306
|
return ipInt
|
244
307
|
end
|
245
308
|
|
data/test/eui48_test.rb
CHANGED
File without changes
|
data/test/eui64_test.rb
CHANGED
File without changes
|
data/test/examples.rb
CHANGED
File without changes
|
data/test/ipv4_test.rb
CHANGED
File without changes
|
data/test/ipv4net_test.rb
CHANGED
@@ -52,6 +52,7 @@ class TestIPv4Net < Test::Unit::TestCase
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def test_fill
|
55
|
+
# filter supernet. remove subnets of subnets. basic fwd fill.
|
55
56
|
parent = NetAddr::IPv4Net.parse("10.0.0.0/24")
|
56
57
|
nets = []
|
57
58
|
["10.0.0.0/24", "10.0.0.0/8", "10.0.0.8/30", "10.0.0.16/30", "10.0.0.16/28"].each do |net|
|
@@ -64,6 +65,7 @@ class TestIPv4Net < Test::Unit::TestCase
|
|
64
65
|
i += 1
|
65
66
|
end
|
66
67
|
|
68
|
+
# basic backfill
|
67
69
|
parent = NetAddr::IPv4Net.parse("128.0.0.0/1")
|
68
70
|
nets = []
|
69
71
|
["192.0.0.0/2"].each do |net|
|
@@ -76,6 +78,7 @@ class TestIPv4Net < Test::Unit::TestCase
|
|
76
78
|
i += 1
|
77
79
|
end
|
78
80
|
|
81
|
+
# basic fwd fill with non-contiguous subnets
|
79
82
|
parent = NetAddr::IPv4Net.parse("1.0.0.0/25")
|
80
83
|
nets = []
|
81
84
|
["1.0.0.0/30", "1.0.0.64/26"].each do |net|
|
@@ -87,6 +90,32 @@ class TestIPv4Net < Test::Unit::TestCase
|
|
87
90
|
assert_equal(expect[i],net.to_s)
|
88
91
|
i += 1
|
89
92
|
end
|
93
|
+
|
94
|
+
# basic backfill. complex fwd fill that uses 'shrink' of the proposed 1.0.16.0/21 subnet
|
95
|
+
parent = NetAddr::IPv4Net.parse("1.0.0.0/19")
|
96
|
+
nets = []
|
97
|
+
["1.0.8.0/21", "1.0.20.0/24"].each do |net|
|
98
|
+
nets.push(NetAddr::IPv4Net.parse(net))
|
99
|
+
end
|
100
|
+
expect = ["1.0.0.0/21","1.0.8.0/21","1.0.16.0/22","1.0.20.0/24","1.0.21.0/24","1.0.22.0/23","1.0.24.0/21"]
|
101
|
+
i = 0
|
102
|
+
parent.fill(nets).each do |net|
|
103
|
+
assert_equal(expect[i],net.to_s)
|
104
|
+
i += 1
|
105
|
+
end
|
106
|
+
|
107
|
+
# list contains the supernet
|
108
|
+
parent = NetAddr::IPv4Net.parse("1.0.0.0/19")
|
109
|
+
nets = []
|
110
|
+
["1.0.0.0/19"].each do |net|
|
111
|
+
nets.push(NetAddr::IPv4Net.parse(net))
|
112
|
+
end
|
113
|
+
expect = []
|
114
|
+
i = 0
|
115
|
+
parent.fill(nets).each do |net|
|
116
|
+
assert_equal(expect[i],net.to_s)
|
117
|
+
i += 1
|
118
|
+
end
|
90
119
|
end
|
91
120
|
|
92
121
|
def test_len
|
data/test/ipv6_test.rb
CHANGED
@@ -39,6 +39,18 @@ class TestIPv6 < Test::Unit::TestCase
|
|
39
39
|
assert_equal(0x00000001000200030004000500060007, NetAddr::IPv6.parse("::1:2:3:4:5:6:7").addr)
|
40
40
|
assert_raise(NetAddr::ValidationError){ NetAddr::IPv6.parse("fec0") }
|
41
41
|
assert_raise(NetAddr::ValidationError){ NetAddr::IPv6.parse("fec0:::1") }
|
42
|
+
|
43
|
+
assert_equal(0x0064ff9b0000000000000000c0000221, NetAddr::IPv6.parse("64:ff9b::192.0.2.33").addr)
|
44
|
+
assert_equal(0x0064ff9b0000000000000000c0000221, NetAddr::IPv6.parse("64:ff9b::0:192.0.2.33").addr)
|
45
|
+
assert_equal(0x0064ff9b0000000000000000c0000221, NetAddr::IPv6.parse("64:ff9b::0:0:192.0.2.33").addr)
|
46
|
+
assert_equal(0x0064ff9b0000000000000000c0000221, NetAddr::IPv6.parse("64:ff9b::0:0:0:192.0.2.33").addr)
|
47
|
+
assert_equal(0x0064ff9b0000000000000000c0000221, NetAddr::IPv6.parse("64:ff9b::0:0:0:0:192.0.2.33").addr)
|
48
|
+
assert_equal(0x0064ff9b0000000000000000c0000221, NetAddr::IPv6.parse("64:ff9b:0:0:0:0:192.0.2.33").addr)
|
49
|
+
assert_raise(NetAddr::ValidationError){ NetAddr::IPv6.parse("64:ff9b::192.0.2") }
|
50
|
+
assert_raise(NetAddr::ValidationError){ NetAddr::IPv6.parse("64:ff9b::192.0.2.33.0") }
|
51
|
+
assert_raise(NetAddr::ValidationError){ NetAddr::IPv6.parse("64:ff9b::192.0.256.33") }
|
52
|
+
assert_raise(NetAddr::ValidationError){ NetAddr::IPv6.parse("64:ff9b:0:0:0:0:0:192.0.2.33") }
|
53
|
+
assert_raise(NetAddr::ValidationError){ NetAddr::IPv6.parse("64:ff9b::0:0:0:0:0:192.0.2.33") }
|
42
54
|
end
|
43
55
|
|
44
56
|
def test_cmp
|
@@ -51,6 +63,32 @@ class TestIPv6 < Test::Unit::TestCase
|
|
51
63
|
assert_equal(0, ip.cmp(ip4))
|
52
64
|
end
|
53
65
|
|
66
|
+
def test_ipv4
|
67
|
+
ipv6 = NetAddr::IPv6.parse("64:ff9b::192.0.2.33")
|
68
|
+
ipv4 = ipv6.ipv4()
|
69
|
+
assert_equal("192.0.2.33", ipv4.to_s)
|
70
|
+
|
71
|
+
ipv6 = NetAddr::IPv6.parse("2001:db8:c000:221::")
|
72
|
+
ipv4 = ipv6.ipv4(32)
|
73
|
+
assert_equal("192.0.2.33", ipv4.to_s)
|
74
|
+
|
75
|
+
ipv6 = NetAddr::IPv6.parse("2001:db8:1c0:2:21::")
|
76
|
+
ipv4 = ipv6.ipv4(40)
|
77
|
+
assert_equal("192.0.2.33", ipv4.to_s)
|
78
|
+
|
79
|
+
ipv6 = NetAddr::IPv6.parse("2001:db8:122:c000:2:2100::")
|
80
|
+
ipv4 = ipv6.ipv4(48)
|
81
|
+
assert_equal("192.0.2.33", ipv4.to_s)
|
82
|
+
|
83
|
+
ipv6 = NetAddr::IPv6.parse("2001:db8:122:3c0:0:221::")
|
84
|
+
ipv4 = ipv6.ipv4(56)
|
85
|
+
assert_equal("192.0.2.33", ipv4.to_s)
|
86
|
+
|
87
|
+
ipv6 = NetAddr::IPv6.parse("2001:db8:122:344:c0:2:2100::")
|
88
|
+
ipv4 = ipv6.ipv4(64)
|
89
|
+
assert_equal("192.0.2.33", ipv4.to_s)
|
90
|
+
end
|
91
|
+
|
54
92
|
def test_long
|
55
93
|
assert_equal("0000:0000:0000:0000:0000:0000:0000:0000", NetAddr::IPv6.parse("::").long)
|
56
94
|
assert_equal("fe80:0000:0000:0000:0000:0000:0000:0001", NetAddr::IPv6.parse("fe80::1").long)
|
@@ -83,6 +121,7 @@ class TestIPv6 < Test::Unit::TestCase
|
|
83
121
|
assert_equal("::1:0:0", NetAddr::IPv6.parse("0:0:0:0:0:1:0:0").to_s)
|
84
122
|
assert_equal("::1:0", NetAddr::IPv6.parse(":0:0:0:0:0:1:0").to_s)
|
85
123
|
assert_equal("::1", NetAddr::IPv6.parse("0:0:0:0:0:0:0:1").to_s)
|
124
|
+
assert_equal("1:0:1:1:1:1:1:1", NetAddr::IPv6.parse("1:0:1:1:1:1:1:1").to_s) # see RFC 5952 section 4.2.2
|
86
125
|
|
87
126
|
assert_equal("1::1", NetAddr::IPv6.parse("1:0:0:0:0:0:0:1").to_s)
|
88
127
|
assert_equal("1:1::1", NetAddr::IPv6.parse("1:1:0:0:0:0:0:1").to_s)
|
data/test/ipv6net_test.rb
CHANGED
@@ -48,18 +48,33 @@ class TestIPv6Net < Test::Unit::TestCase
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def test_fill
|
51
|
+
# filter supernet. remove subnets of subnets. basic fwd fill.
|
51
52
|
parent = NetAddr::IPv6Net.parse("ff00::/8")
|
52
53
|
nets = []
|
53
|
-
["ff08::/14", "fe00::/7", "ff20::/11", "ff20::/12"].each do |net|
|
54
|
+
["ff00::/8", "ff00::/9", "ff08::/14", "fe00::/7", "ff20::/11", "ff20::/12"].each do |net|
|
54
55
|
nets.push(NetAddr::IPv6Net.parse(net))
|
55
56
|
end
|
56
|
-
expect = ["ff00::/
|
57
|
+
expect = ["ff00::/9", "ff80::/9"]
|
57
58
|
i = 0
|
58
59
|
parent.fill(nets).each do |net|
|
59
60
|
assert_equal(expect[i],net.to_s)
|
60
61
|
i += 1
|
61
62
|
end
|
62
63
|
|
64
|
+
# basic backfill
|
65
|
+
parent = NetAddr::IPv6Net.parse("8000::/1")
|
66
|
+
nets = []
|
67
|
+
["c000::/2"].each do |net|
|
68
|
+
nets.push(NetAddr::IPv6Net.parse(net))
|
69
|
+
end
|
70
|
+
expect = ["8000::/2","c000::/2"]
|
71
|
+
i = 0
|
72
|
+
parent.fill(nets).each do |net|
|
73
|
+
assert_equal(expect[i],net.to_s)
|
74
|
+
i += 1
|
75
|
+
end
|
76
|
+
|
77
|
+
# basic fwd fill with non-contiguous subnets
|
63
78
|
parent = NetAddr::IPv6Net.parse("ff00::/121")
|
64
79
|
nets = []
|
65
80
|
["ff00::/126", "ff00::/120"].each do |net|
|
@@ -71,6 +86,33 @@ class TestIPv6Net < Test::Unit::TestCase
|
|
71
86
|
assert_equal(expect[i],net.to_s)
|
72
87
|
i += 1
|
73
88
|
end
|
89
|
+
|
90
|
+
# basic backfill. complex fwd fill that uses 'shrink' of the proposed ffff:ffff:ffff:fff8::/62 subnet. designed to cross the /64 bit boundary.
|
91
|
+
parent = NetAddr::IPv6Net.parse("fff:ffff:ffff:fff0::/60")
|
92
|
+
nets = []
|
93
|
+
["ffff:ffff:ffff:fff4::/62", "ffff:ffff:ffff:fffb::/65"].each do |net|
|
94
|
+
nets.push(NetAddr::IPv6Net.parse(net))
|
95
|
+
end
|
96
|
+
expect = ["ffff:ffff:ffff:fff0::/62", "ffff:ffff:ffff:fff4::/62", "ffff:ffff:ffff:fff8::/63", "ffff:ffff:ffff:fffa::/64", "ffff:ffff:ffff:fffb::/65",
|
97
|
+
"ffff:ffff:ffff:fffb:8000::/65", "ffff:ffff:ffff:fffc::/62"]
|
98
|
+
i = 0
|
99
|
+
parent.fill(nets).each do |net|
|
100
|
+
assert_equal(expect[i],net.to_s)
|
101
|
+
i += 1
|
102
|
+
end
|
103
|
+
|
104
|
+
# list contains the supernet
|
105
|
+
parent = NetAddr::IPv6Net.parse("ffff::/16")
|
106
|
+
nets = []
|
107
|
+
["ffff::/16"].each do |net|
|
108
|
+
nets.push(NetAddr::IPv6Net.parse(net))
|
109
|
+
end
|
110
|
+
expect = []
|
111
|
+
i = 0
|
112
|
+
parent.fill(nets).each do |net|
|
113
|
+
assert_equal(expect[i],net.to_s)
|
114
|
+
i += 1
|
115
|
+
end
|
74
116
|
end
|
75
117
|
|
76
118
|
def test_next
|
data/test/mask128_test.rb
CHANGED
File without changes
|
data/test/mask32_test.rb
CHANGED
@@ -34,6 +34,11 @@ class TestMask32 < Test::Unit::TestCase
|
|
34
34
|
assert_equal(0, m.cmp(m4))
|
35
35
|
end
|
36
36
|
|
37
|
+
def test_extended
|
38
|
+
m32 = NetAddr::Mask32.new(24)
|
39
|
+
assert_equal("255.255.255.0", m32.extended)
|
40
|
+
end
|
41
|
+
|
37
42
|
def test_len
|
38
43
|
m = NetAddr::Mask32.new(24)
|
39
44
|
assert_equal(256, m.len())
|
data/test/netaddr_test.rb
CHANGED
@@ -5,6 +5,17 @@ require 'test/unit'
|
|
5
5
|
|
6
6
|
class TestNetAddr < Test::Unit::TestCase
|
7
7
|
|
8
|
+
def test_parse_ip
|
9
|
+
assert_equal("128.0.0.1", NetAddr.parse_ip("128.0.0.1").to_s)
|
10
|
+
assert_equal("1::1", NetAddr.parse_ip("1::1").to_s)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_parse_net
|
14
|
+
assert_equal("128.0.0.1/32", NetAddr.parse_net("128.0.0.1/32").to_s)
|
15
|
+
assert_equal("1::/24", NetAddr.parse_net("1::1/24").to_s)
|
16
|
+
assert_equal("::ffff:aabb:ccdd/128", NetAddr.parse_net("::ffff:170.187.204.221/128").to_s)
|
17
|
+
end
|
18
|
+
|
8
19
|
def test_ipv4_prefix_len
|
9
20
|
assert_equal(32,NetAddr.ipv4_prefix_len(1))
|
10
21
|
assert_equal(27,NetAddr.ipv4_prefix_len(30))
|
@@ -67,6 +78,17 @@ class TestNetAddr < Test::Unit::TestCase
|
|
67
78
|
assert_equal(expect[i],net.to_s)
|
68
79
|
i += 1
|
69
80
|
end
|
81
|
+
|
82
|
+
nets = []
|
83
|
+
["10.0.0.0/26","10.0.0.64/26","10.0.0.0/24","10.0.0.192/26","10.0.0.128/26"].each do |net| # test out of order
|
84
|
+
nets.push(NetAddr::IPv4Net.parse(net))
|
85
|
+
end
|
86
|
+
expect = ["10.0.0.0/24"]
|
87
|
+
i = 0
|
88
|
+
NetAddr.summ_IPv4Net(nets).each do |net|
|
89
|
+
assert_equal(expect[i],net.to_s)
|
90
|
+
i += 1
|
91
|
+
end
|
70
92
|
end
|
71
93
|
|
72
94
|
def test_sort_IPv6
|
data/test/run_all.rb
CHANGED
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: netaddr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dustin Spinhirne
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -60,8 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
requirements: []
|
63
|
-
|
64
|
-
rubygems_version: 2.5.2.1
|
63
|
+
rubygems_version: 3.3.5
|
65
64
|
signing_key:
|
66
65
|
specification_version: 4
|
67
66
|
summary: A Ruby library for performing calculations on IPv4 and IPv6 subnets.
|