netaddr 2.0.3 → 2.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 89ce300b6a351757d48c569e132c3e1346f7b09a
4
- data.tar.gz: 5f11179793ee8a0d5a42758524b7aa49f71392cc
2
+ SHA256:
3
+ metadata.gz: 13e871a188dbf2b94f5c57fe638c5dac249792134a8eece5386fbc36d1ea88d6
4
+ data.tar.gz: 14e02af771158f3003e49181ed49fe7e2fa8d201991215bda51fc2a48b15a96a
5
5
  SHA512:
6
- metadata.gz: 36acfbba061405495f4e4d08c271f6be19c9810de6c5a44f78a2ebf407cf24637dac6b50277c82cc6048e36d00785e143aa37170e0101d40638b36f77e575c5a
7
- data.tar.gz: c9baee3f002fb16def0f60f8e9304b44015739f0a5f844b1413f8b20d2d80c9bc73678654f81906ef14255f9928b64a3153eba120e387f4044bd558e5d6f5df3
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 0 words in a row
104
- if (finalStart != -1)
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.to_i)
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
- return Mask32.new(mask[1..-1].to_i) # remove "/"
32
- elsif (!mask.include?("."))
33
- return Mask32.new(mask.to_i)
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.intToMask32(@mask)
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
- unrelated = []
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
- unrelated.push(net)
33
- elsif (rel == -1) # last is subnet of net
34
- supernets.push(net)
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
- cleaned = []
39
- if (supernets.length > 0)
40
- cleaned = discard_subnets(supernets)
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
- if (unrelated.length > 0)
46
- cleaned.concat( discard_subnets(unrelated) )
43
+ if keep_last
44
+ keepers.unshift(last)
47
45
  end
48
- return cleaned
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 & git rid of non subnets
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
- limit = subs[i+1].network.addr
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
- # limit should be > ipnet. will create subnets up to limit.
138
- def Util.fwdfill(ipnet,limit)
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
- while true do
142
- net = cur.next
143
- if (net == nil || net.network.addr >= limit)
144
- break
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::/13", "ff08::/14", "ff0c::/14", "ff10::/12", "ff20::/11", "ff40::/10", "ff80::/9"]
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.3
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: 2018-03-23 00:00:00.000000000 Z
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
- rubyforge_project:
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.