netaddr 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of netaddr might be problematic. Click here for more details.

data/changelog CHANGED
@@ -1,3 +1,19 @@
1
+ ==Version
2
+ ====1.5.0
3
+
4
+ ===Changes
5
+ * fixed bug with EUI48#to_eui64 (credit to Erik Kline)
6
+ * fixed bug with u/l bit toggle on EUI#link_local (credit to Erik Kline)
7
+ * added EUI#to_ipv6
8
+ * added NetAddr#supernets
9
+
10
+
11
+ ==Version
12
+ ====1.4.0
13
+
14
+ ===Changes
15
+ * Added additional options to NetAddr#sort
16
+
1
17
 
2
18
  ==Version
3
19
  ====1.3.0
@@ -737,52 +737,10 @@ end
737
737
  #==============================================================================#
738
738
 
739
739
  #===Synopsis
740
- #Returns network/netmask in CIDR format.
741
- #
742
- # Example:
743
- # cidr4 = NetAddr::CIDR.create('192.168.1.1/24')
744
- # cidr6 = NetAddr::CIDR.create('fec0::/64')
745
- # cidr4.desc(:IP => true) => "192.168.1.1/24"
746
- # cidr4.desc() => "192.168.1.0/24"
747
- # cidr6.desc(:Short => true) => "fec0::/64"
748
- #
749
- #===Arguments:
750
- #* options = Optional hash with the following keys:
751
- # :IP -- if true, return the original ip/netmask passed during initialization
752
- # :Short -- if true, return IPv6 addresses in short-hand notation
753
- #
754
- #===Returns:
755
- #* String
740
+ #See to_s
756
741
  #
757
742
  def desc(options=nil)
758
- known_args = [:IP, :Short]
759
- short = false
760
- orig_ip = false
761
-
762
- if (options)
763
- if (!options.kind_of? Hash)
764
- raise ArgumentError, "Expected Hash, but #{options.class} provided."
765
- end
766
- NetAddr.validate_args(options.keys,known_args)
767
-
768
- if (options.has_key?(:Short) && options[:Short] == true)
769
- short = true
770
- end
771
-
772
- if (options.has_key?(:IP) && options[:IP] == true)
773
- orig_ip = true
774
- end
775
- end
776
-
777
- if (!orig_ip)
778
- ip = NetAddr.ip_int_to_str(@network, @version)
779
- else
780
- ip = NetAddr.ip_int_to_str(@ip, @version)
781
- end
782
- ip = NetAddr.shorten(ip) if (short && @version == 6)
783
- mask = NetAddr.mask_to_bits(@netmask)
784
-
785
- return("#{ip}/#{mask}")
743
+ to_s(options)
786
744
  end
787
745
 
788
746
  #==============================================================================#
@@ -1995,6 +1953,59 @@ end
1995
1953
  end
1996
1954
  end
1997
1955
 
1956
+ #==============================================================================#
1957
+ # to_s()
1958
+ #==============================================================================#
1959
+
1960
+ #===Synopsis
1961
+ #Returns network/netmask in CIDR format.
1962
+ #
1963
+ # Example:
1964
+ # cidr4 = NetAddr::CIDR.create('192.168.1.1/24')
1965
+ # cidr6 = NetAddr::CIDR.create('fec0::/64')
1966
+ # cidr4.desc(:IP => true) => "192.168.1.1/24"
1967
+ # cidr4.to_s => "192.168.1.0/24"
1968
+ # cidr6.to_s(:Short => true) => "fec0::/64"
1969
+ #
1970
+ #===Arguments:
1971
+ #* options = Optional hash with the following keys:
1972
+ # :IP -- if true, return the original ip/netmask passed during initialization
1973
+ # :Short -- if true, return IPv6 addresses in short-hand notation
1974
+ #
1975
+ #===Returns:
1976
+ #* String
1977
+ #
1978
+ def to_s(options=nil)
1979
+ known_args = [:IP, :Short]
1980
+ short = false
1981
+ orig_ip = false
1982
+
1983
+ if (options)
1984
+ if (!options.kind_of? Hash)
1985
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
1986
+ end
1987
+ NetAddr.validate_args(options.keys,known_args)
1988
+
1989
+ if (options.has_key?(:Short) && options[:Short] == true)
1990
+ short = true
1991
+ end
1992
+
1993
+ if (options.has_key?(:IP) && options[:IP] == true)
1994
+ orig_ip = true
1995
+ end
1996
+ end
1997
+
1998
+ if (!orig_ip)
1999
+ ip = NetAddr.ip_int_to_str(@network, @version)
2000
+ else
2001
+ ip = NetAddr.ip_int_to_str(@ip, @version)
2002
+ end
2003
+ ip = NetAddr.shorten(ip) if (short && @version == 6)
2004
+ mask = NetAddr.mask_to_bits(@netmask)
2005
+
2006
+ return("#{ip}/#{mask}")
2007
+ end
2008
+
1998
2009
  #==============================================================================#
1999
2010
  # wildcard_mask()
2000
2011
  #==============================================================================#
@@ -347,6 +347,35 @@ def cidr_summarize(subnet_list)
347
347
  end
348
348
  module_function :cidr_summarize
349
349
 
350
+ #==============================================================================#
351
+ # cidr_supernets()
352
+ #==============================================================================#
353
+
354
+ # given a list of NetAddr::CIDRs (of the same version), return only the 'top level' blocks (i.e. blocks not
355
+ # contained by other blocks
356
+
357
+ def cidr_supernets(subnet_list)
358
+ summary_list = []
359
+ subnet_list = netmask_sort(subnet_list)
360
+ subnet_list.each do |child|
361
+ is_parent = true
362
+ summary_list.each do |parent|
363
+ if (NetAddr.cidr_compare(parent,child) == 1)
364
+ is_parent = false
365
+ parent.tag[:Subnets].push(child)
366
+ end
367
+ end
368
+
369
+ if (is_parent)
370
+ child.tag[:Subnets] = []
371
+ summary_list.push(child)
372
+ end
373
+ end
374
+
375
+ return(summary_list)
376
+ end
377
+ module_function :cidr_supernets
378
+
350
379
  #==============================================================================#
351
380
  # netmask_sort()
352
381
  #==============================================================================#
data/lib/eui.rb CHANGED
@@ -146,7 +146,7 @@ private_class_method :new
146
146
  end
147
147
 
148
148
  if (delimiter == '-' || delimiter == ':')
149
- addr = octets.join(delimiter)
149
+ addr = octets.join(delimiter)
150
150
  elsif (delimiter == '.')
151
151
  toggle = 0
152
152
  octets.each do |x|
@@ -231,39 +231,7 @@ private_class_method :new
231
231
  #* CIDR address String or an NetAddr::CIDR object
232
232
  #
233
233
  def link_local(options=nil)
234
- known_args = [:Short, :Objectify]
235
- objectify = false
236
- short = false
237
-
238
- if (options)
239
- if (!options.kind_of? Hash)
240
- raise ArgumentError, "Expected Hash, but #{options.class} provided."
241
- end
242
- NetAddr.validate_args(options.keys,known_args)
243
-
244
- if (options.has_key?(:Objectify) && options[:Objectify] == true)
245
- objectify = true
246
- end
247
-
248
- if (options.has_key?(:Short) && options[:Short] == true)
249
- short = true
250
- end
251
- end
252
-
253
- if (self.kind_of?(NetAddr::EUI64))
254
- link_local = 'fe80000000000000' << @eui
255
- else
256
- link_local = 'fe80000000000000' << @oui << 'fffe' << @ei
257
- end
258
-
259
- if (!objectify)
260
- link_local = NetAddr.i_to_ip(link_local.to_i(16), :Version => 6)
261
- link_local = NetAddr.shorten(link_local) if (short)
262
- else
263
- link_local = NetAddr::CIDRv6.new(link_local.to_i(16))
264
- end
265
-
266
- return(link_local)
234
+ return( self.to_ipv6('fe80::/64', options) )
267
235
  end
268
236
 
269
237
  #==============================================================================#
@@ -280,7 +248,7 @@ private_class_method :new
280
248
  #
281
249
  #===Arguments:
282
250
  #* options = Hash with the following fields:
283
- # :Delimiter -- delimitation character. valid values are (-, and :)
251
+ # :Delimiter -- delimitation character. valid values are (-, and :)
284
252
  #
285
253
  #===Returns:
286
254
  #* String
@@ -327,6 +295,82 @@ private_class_method :new
327
295
  return(@eui_i)
328
296
  end
329
297
 
298
+ #==============================================================================#
299
+ # to_ipv6
300
+ #==============================================================================#
301
+
302
+ #===Synopsis
303
+ # Given a valid IPv6 subnet, return an IPv6 address based on the current EUI.
304
+ #
305
+ # Example:
306
+ # addr = NetAddr::EUI.create('aabb.ccdd.eeff')
307
+ # addr.to_ipv6('3ffe::/64') => "3ffe:0000:0000:0000:a8bb:ccff:fedd:eeff"
308
+ #
309
+ #===Arguments:
310
+ #* options = Hash with the following fields:
311
+ # :Short -- if true, return IPv6 addresses in short-hand notation
312
+ # :Objectify -- if true, return CIDR objects
313
+ #
314
+ #===Returns:
315
+ #* IPv6 address String or an NetAddr::CIDRv6 object
316
+ #
317
+ def to_ipv6(cidr, options=nil)
318
+ known_args = [:Short, :Objectify]
319
+ objectify = false
320
+ short = false
321
+
322
+ if ( !cidr.kind_of?(NetAddr::CIDR) )
323
+ begin
324
+ cidr = NetAddr::CIDR.create(cidr)
325
+ rescue Exception => error
326
+ raise ArgumentError, "CIDR raised the following errors: #{error}"
327
+ end
328
+ elsif (cidr.kind_of?(NetAddr::CIDRv4) )
329
+ raise ArgumentError, "Expected CIDRv6, but #{cidr.class} provided."
330
+ end
331
+
332
+ if (cidr.bits > 64)
333
+ raise ValidationError, "Prefix length of provided CIDR must be /64 or less but was #{cidr.netmask}."
334
+ end
335
+
336
+ if (options)
337
+ if (!options.kind_of? Hash)
338
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
339
+ end
340
+ NetAddr.validate_args(options.keys,known_args)
341
+
342
+ if (options.has_key?(:Objectify) && options[:Objectify] == true)
343
+ objectify = true
344
+ end
345
+
346
+ if (options.has_key?(:Short) && options[:Short] == true)
347
+ short = true
348
+ end
349
+ end
350
+
351
+ # get integer equiv of addr. conver eui48 to eui64 if needed
352
+ if ( self.kind_of?(NetAddr::EUI48) )
353
+ eui_i = self.to_eui64.to_i
354
+ else
355
+ eui_i = self.to_i
356
+ end
357
+
358
+ # toggle u/l bit
359
+ eui_i = eui_i ^ 0x0200000000000000
360
+
361
+ # create ipv6 address
362
+ ipv6 = cidr.to_i | eui_i
363
+
364
+ if (!objectify)
365
+ ipv6 = NetAddr.i_to_ip(ipv6, :Version => 6)
366
+ ipv6 = NetAddr.shorten(ipv6) if (short)
367
+ else
368
+ ipv6 = NetAddr::CIDRv6.new(ipv6)
369
+ end
370
+
371
+ return(ipv6)
372
+ end
373
+
330
374
  #==============================================================================#
331
375
  # to_s()
332
376
  #==============================================================================#
@@ -400,7 +444,7 @@ class EUI48 < EUI
400
444
  #* NetAddr::EUI64 object
401
445
  #
402
446
  def to_eui64()
403
- eui = @oui << 'fffe' << @ei
447
+ eui = @oui + 'fffe' + @ei
404
448
  return( NetAddr::EUI64.new(eui.to_i(16)) )
405
449
  end
406
450
 
@@ -680,6 +680,106 @@ def sort(list, options=nil)
680
680
  end
681
681
  module_function :sort
682
682
 
683
+ #==============================================================================#
684
+ # supernets()
685
+ #==============================================================================#
686
+
687
+ #===Synopsis
688
+ #Given a list of CIDR addresses or NetAddr::CIDR objects,
689
+ #return only the top-level supernet CIDR addresses.
690
+ #
691
+ #
692
+ #If the :Objectify option is enabled, then returned CIDR objects will
693
+ #store the more specific CIDRs (i.e. subnets of those CIDRs) within the tag value :Subnets
694
+ #For example, cidr_x.tag[:Subnets] would be an Array of CIDR subnets of cidr_x.
695
+ #
696
+ # Example:
697
+ # NetAddr.supernets(['192.168.0.0', '192.168.0.1', '192.168.0.0/31'])
698
+ #
699
+ #===Arguments:
700
+ #* list = Array of CIDR addresses as Strings, or an Array of NetAddr::CIDR objects
701
+ #* options = Hash with the following keys:
702
+ # :Objectify -- if true, return NetAddr::CIDR objects
703
+ # :Short -- if true, return IPv6 addresses in short-hand notation
704
+ #
705
+ #===Returns:
706
+ #* Array of CIDR addresses or NetAddr::CIDR objects
707
+ #
708
+ def supernets(list,options=nil)
709
+ known_args = [:Objectify, :Short]
710
+ short = false
711
+ objectify = false
712
+ verbose = false
713
+
714
+ # validate list
715
+ raise ArgumentError, "Array expected for argument 'list' but #{list.class} provided." if (!list.kind_of?(Array) )
716
+
717
+ # validate options
718
+ if (options)
719
+ raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash) )
720
+ NetAddr.validate_args(options.keys,known_args)
721
+
722
+ if (options.has_key?(:Objectify) && options[:Objectify] == true)
723
+ objectify = true
724
+ end
725
+
726
+ if (options.has_key?(:Short) && options[:Short] == true)
727
+ short = true
728
+ end
729
+ end
730
+
731
+ # make sure all are valid types of the same IP version
732
+ v4_list = []
733
+ v6_list = []
734
+ list.each do |obj|
735
+ if (!obj.kind_of?(NetAddr::CIDR))
736
+ begin
737
+ obj = NetAddr::CIDR.create(obj)
738
+ rescue Exception => error
739
+ raise ArgumentError, "One of the provided CIDR addresses raised the following " +
740
+ "errors: #{error}"
741
+ end
742
+ end
743
+
744
+ if (obj.version == 4)
745
+ v4_list.push(obj)
746
+ else
747
+ v6_list.push(obj)
748
+ end
749
+ end
750
+
751
+ # do summary calcs
752
+ v4_summary = []
753
+ v6_summary = []
754
+ if (v4_list.length != 0)
755
+ v4_summary = NetAddr.cidr_supernets(v4_list)
756
+ end
757
+
758
+ if (v6_list.length != 0)
759
+ v6_summary = NetAddr.cidr_supernets(v6_list)
760
+ end
761
+
762
+ # decide what to return
763
+ summarized_list = []
764
+ if (!objectify)
765
+ summarized_list = []
766
+ if (v4_summary.length != 0)
767
+ v4_summary.each {|x| summarized_list.push(x.desc())}
768
+ end
769
+
770
+ if (v6_summary.length != 0)
771
+ v6_summary.each {|x| summarized_list.push(x.desc(:Short => short))}
772
+ end
773
+
774
+ else
775
+ summarized_list.concat(v4_summary) if (v4_summary.length != 0)
776
+ summarized_list.concat(v6_summary) if (v6_summary.length != 0)
777
+ end
778
+
779
+ return(summarized_list)
780
+ end
781
+ module_function :supernets
782
+
683
783
  #==============================================================================#
684
784
  # unshorten()
685
785
  #==============================================================================#
@@ -65,13 +65,13 @@ class TestEUI < Test::Unit::TestCase
65
65
 
66
66
  def test_link_local
67
67
  mac = NetAddr::EUI.create('aa-bb-cc-dd-ee-ff')
68
- assert_equal('fe80:0000:0000:0000:aabb:ccff:fedd:eeff', mac.link_local )
68
+ assert_equal('fe80:0000:0000:0000:a8bb:ccff:fedd:eeff', mac.link_local )
69
69
 
70
70
  mac = NetAddr::EUI.create('1234.5678.9abc')
71
- assert_equal('fe80:0000:0000:0000:1234:56ff:fe78:9abc', mac.link_local )
71
+ assert_equal('fe80:0000:0000:0000:1034:56ff:fe78:9abc', mac.link_local )
72
72
 
73
73
  mac = NetAddr::EUI.create('1234.5678.9abc.def0')
74
- assert_equal('fe80:0000:0000:0000:1234:5678:9abc:def0', mac.link_local(:Objectify => true).ip )
74
+ assert_equal('fe80:0000:0000:0000:1034:5678:9abc:def0', mac.link_local(:Objectify => true).ip )
75
75
  assert_raise(ArgumentError) {mac.link_local(:test => true)}
76
76
  end
77
77
 
@@ -79,6 +79,23 @@ class TestEUI < Test::Unit::TestCase
79
79
  mac = NetAddr::EUI.create('aa-bb-cc-dd-ee-ff')
80
80
  assert_equal('aa-bb-cc-ff-fe-dd-ee-ff', mac.to_eui64.address )
81
81
 
82
+ # check that to_eui64 has no side effects
83
+ b = mac.to_eui64
84
+ c = mac.to_eui64
85
+ assert_equal(b.to_s, c.to_s)
86
+ end
87
+
88
+ def test_to_ipv6
89
+ mac = NetAddr::EUI.create('aa-bb-cc-dd-ee-ff')
90
+ assert_equal('fe80:0000:0000:0000:a8bb:ccff:fedd:eeff', mac.to_ipv6('fe80::/64') )
91
+
92
+ mac = NetAddr::EUI.create('1234.5678.9abc')
93
+ assert_equal('fe80:0000:0000:0000:1034:56ff:fe78:9abc', mac.to_ipv6('fe80::/64') )
94
+
95
+ mac = NetAddr::EUI.create('1234.5678.9abc.def0')
96
+ assert_equal('fe80:0000:0000:0000:1034:5678:9abc:def0', mac.to_ipv6('fe80::/64', :Objectify => true).ip )
97
+ assert_raise(ArgumentError) {mac.link_local(:test => true)}
98
+ assert_raise(NetAddr::ValidationError) {mac.to_ipv6('fe80::/65')}
82
99
  end
83
100
 
84
101
  end
@@ -187,6 +187,22 @@ class TestMethods < Test::Unit::TestCase
187
187
  assert_equal([cidr4_4,cidr4_3,cidr4_2,cidr4_1,cidr4_5], sort5)
188
188
  end
189
189
 
190
+ def test_supernets
191
+ assert_raise(ArgumentError){ NetAddr.supernets(1) }
192
+ assert_raise(ArgumentError){ NetAddr.supernets({}) }
193
+
194
+ list4 = ['192.168.1.0', '192.168.1.1', '192.168.1.0/31', '10.1.1.0/24', '10.1.1.32/27']
195
+ list6 = ['fec0::/64', 'fec0::', 'fe80::/32', 'fe80::1']
196
+ assert_equal(['10.1.1.0/24','192.168.1.0/31'], NetAddr.supernets(list4) )
197
+ assert_equal(['fe80:0000:0000:0000:0000:0000:0000:0000/32', 'fec0:0000:0000:0000:0000:0000:0000:0000/64'], NetAddr.supernets(list6) )
198
+ assert_equal(['fe80::/32', 'fec0::/64'], NetAddr.supernets(list6, :Short => true) )
199
+
200
+ list4.push( NetAddr::CIDR.create('192.168.0.0/23') )
201
+ list6.push( NetAddr::CIDR.create('fec0::/48') )
202
+ summ = NetAddr.supernets(list4.concat(list6), :Objectify => true)
203
+ assert_equal('192.168.1.0/31', summ[0].tag[:Subnets][0].desc)
204
+ end
205
+
190
206
  def test_unshorten
191
207
  assert_equal('fec0:0000:0000:0000:0000:0000:0000:0000', NetAddr.unshorten('fec0::') )
192
208
  assert_equal('fec0:0000:0000:0000:0002:0000:0000:0001', NetAddr.unshorten('fec0::2:0:0:1') )
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: netaddr
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dustin Spinhirne
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-02-15 00:00:00 -06:00
12
+ date: 2008-11-07 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -57,7 +57,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
57
  requirements: []
58
58
 
59
59
  rubyforge_project:
60
- rubygems_version: 1.0.1
60
+ rubygems_version: 1.2.0
61
61
  signing_key:
62
62
  specification_version: 2
63
63
  summary: A package for manipulating network addresses.