netaddr 2.0.3 → 2.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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 +21 -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: 9a1415cbc9b4353fc9da565edf3ac8a7a9e0494e9a69d5767c1a46219abc4b24
|
4
|
+
data.tar.gz: d6d34f2d5dff1beea5855bfac31d5bbb12a3358f8f12aee2513dc074047037d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb448e9527d5bca2ec9c8f095dcf6b825de2919a429bf6aa50b757b2b71dcc9778b2910a090fbba3af209349f295ab59df29cb95f76057400e16a6b9eb892e93
|
7
|
+
data.tar.gz: b2ff3dffd33f4bc1ce5b0e1fc16f3121cb2a7f75d9a0a6321daf7c1cc7adea85224d1bb1d0a4593706d0125341fa0c82c464a5ed8d3d5f34de79721df0dcf5ac
|
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?(".")) # ipv4
|
52
|
+
return IPv4Net.parse(net)
|
53
|
+
end
|
54
|
+
return IPv6Net.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,16 @@ 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
|
+
end
|
17
|
+
|
8
18
|
def test_ipv4_prefix_len
|
9
19
|
assert_equal(32,NetAddr.ipv4_prefix_len(1))
|
10
20
|
assert_equal(27,NetAddr.ipv4_prefix_len(30))
|
@@ -67,6 +77,17 @@ class TestNetAddr < Test::Unit::TestCase
|
|
67
77
|
assert_equal(expect[i],net.to_s)
|
68
78
|
i += 1
|
69
79
|
end
|
80
|
+
|
81
|
+
nets = []
|
82
|
+
["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
|
83
|
+
nets.push(NetAddr::IPv4Net.parse(net))
|
84
|
+
end
|
85
|
+
expect = ["10.0.0.0/24"]
|
86
|
+
i = 0
|
87
|
+
NetAddr.summ_IPv4Net(nets).each do |net|
|
88
|
+
assert_equal(expect[i],net.to_s)
|
89
|
+
i += 1
|
90
|
+
end
|
70
91
|
end
|
71
92
|
|
72
93
|
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.5
|
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: 2021-10-07 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.1.2
|
65
64
|
signing_key:
|
66
65
|
specification_version: 4
|
67
66
|
summary: A Ruby library for performing calculations on IPv4 and IPv6 subnets.
|