ipadmin 0.2.2 → 0.3.0

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.
data/README CHANGED
@@ -1,15 +1,33 @@
1
1
 
2
+ =Introduction
3
+
4
+ IPAdmin arose from a work-related project to create a Rails IP
5
+ Administration package. I needed a back-end module that could easily
6
+ handle such advanced tasks as automating the subnetting/supernetting
7
+ of IP space, performing calculations on IP CIDR blocks, and other
8
+ various tasks. At the current time there were no modules that could
9
+ do any of the things that I needed, so I set out to create my own.
10
+ Since it proved to be fairly useful to me, I decided to share the
11
+ code with the Ruby community.
12
+
13
+ I apologize in advance for the short release cycles, but I am making
14
+ changes on a constant basis since this is a very active project.
15
+ I tend to post new releases to rubyforge since it is a very easy
16
+ way for me to distribute my changes to my co-workers.
17
+
18
+ I have added things that I find immediately useful for me. I am
19
+ open to suggestions if there is something that I could add to make
20
+ your life easier. Comments are also welcome (positive ones in particular).
21
+
22
+ Dustin Spinhirne
23
+
24
+
2
25
  Copyright (c) 2006 Dustin Spinhirne - http://www.spinhirne.com
3
26
  Licensed under the same terms as Ruby, No Warranty is provided.
4
27
 
5
-
6
- Comments are welcome. Please include 'IPAdmin' in the title of
7
- any emails.
8
-
9
- Dustin Spinhirne
10
28
 
11
29
 
12
- =CIDR
30
+ =CIDR:
13
31
 
14
32
  A class & series of methods for creating and manipulating CIDR network
15
33
  addresses. Both IPv4 and IPv6 are supported.
@@ -38,49 +56,15 @@
38
56
  You can see how the CIDR object is based around the entire IP space
39
57
  defined by the provided IP/Netmask pair, and not necessarily the individual
40
58
  IP address itself.
41
-
42
-
43
- =Tree
44
-
45
- A class & series of methods for creating and manipulating IP-based
46
- heirarchical trees. Both IPv4 and IPv6 are supported.
47
-
48
- Tree's are useful for creating mini 'routing tables' of CIDR address space.
49
- Using a tree, you can quickly determine the 'route' of another CIDR via
50
- the standard longest-match algorithm.
51
-
52
- Tree's are not dynamic, in that if you modify any of the CIDR objects
53
- contained within, the Tree will not automatically adjust itself accordingly.
54
- For example if you have a tree like the following:
55
-
56
- 192.168.0.0/24
57
- 192.168.0.0/26
58
- 192.168.1.0/24
59
-
60
- You decide to resize 192.168.0.0/24 to 192.168.0.0/23. The tree will now
61
- be incorrect:
62
-
63
- 192.168.0.0/23
64
- 192.168.0.0/26
65
- 192.168.1.0/24
66
-
67
- You would need to remove and re-add the CIDR 192.168.0.0/23 in order for the
68
- tree to rebuild itself properly.
69
-
70
59
 
71
60
 
72
-
73
- =Examples:
74
-
61
+ ====Examples:
75
62
 
76
63
  #!/usr/bin/ruby
77
64
 
78
65
  require 'rubygems'
79
66
  require_gem 'ipadmin'
80
67
 
81
- #============================================================================#
82
- # IPAdmin::CIDR
83
- #============================================================================#
84
68
  puts "IPAdmin::CIDR"
85
69
  print "\n"
86
70
 
@@ -101,8 +85,7 @@
101
85
  puts "updated cidr4 tag '#{cidr4.tag['test']}'"
102
86
  puts "cidr4 version #{cidr4.version}"
103
87
  puts "cidr6 version #{cidr6.version}"
104
- print "\n"
105
-
88
+ print "\n"
106
89
 
107
90
  # arpa
108
91
  puts "arpa"
@@ -154,6 +137,14 @@
154
137
  puts "cidr4 last ip #{cidr4.last()}"
155
138
  puts "cidr6 last ip #{cidr6.last(:Short => true)}"
156
139
  print "\n"
140
+
141
+ # multicast_mac
142
+ mcast = IPAdmin::CIDR.new(:CIDR => '224.0.0.6')
143
+ mcast2 = IPAdmin::CIDR.new(:CIDR => 'ff00::abcd')
144
+ puts "multicast_mac"
145
+ puts "#{mcast.ip} multicast mac is #{mcast.multicast_mac()}"
146
+ puts "#{mcast2.ip} multicast mac is #{mcast2.multicast_mac()}"
147
+ print "\n"
157
148
 
158
149
  # netmask
159
150
  puts "netmask"
@@ -243,15 +234,107 @@
243
234
  puts "#{cidr6.desc(:Short => true)} subnetted into at least 4 /67 ranges"
244
235
  cidr6.subnet(:Subnet => 67, :MinCount => 4, :Short => true).each {|x| puts " #{x}"}
245
236
 
246
- print "\n\n\n"
247
- #=====================================#
248
- #
249
- #=====================================#
237
+
238
+
239
+
240
+
241
+ =EUI:
242
+
243
+ A class & series of methods for creating and manipulating Extended Unique Identifier
244
+ (EUI) addresses. Two types of address formats are supported EUI-48 and EUI-64. The
245
+ most common use for this class will be to manipulate MAC addresses (which are essentially
246
+ a type of EUI-48 address).
247
+
248
+ EUI addresses are separated into two parts, the
249
+ Organizationally Unique Identifier (OUI) and the Extended Identifier (EI). The OUI
250
+ is assigned by the IEEE and is used to identify a particular hardware manufacturer.
251
+ The EI is assigned by the hardware manufacturer as a per device unique address.
252
+
253
+ Probably the most useful feature of this class, and thus the reason it was created,
254
+ is to help automate certain address assignments within IP. For example, IPv6
255
+ Link Local addresses use MAC addresses for IP auto-assignment and multicast MAC addresses
256
+ are determined based on the multicast IP address.
257
+
258
+
259
+ ====Examples:
260
+
261
+ #!/usr/bin/ruby
262
+
263
+ require 'rubygems'
264
+ require_gem 'ipadmin'
265
+
266
+ puts "IPAdmin::EUI"
267
+ print "\n"
268
+
269
+ eui1 = IPAdmin::EUI.new(:EUI => 'aa-bb-cc-dd-ee-ff')
270
+ eui2 = IPAdmin::EUI.new(:EUI => '12-34-56-78-9a-bc-de-f0')
271
+
272
+ # oui
273
+ puts "oui"
274
+ puts "OUI 1 is #{eui1.oui}"
275
+ puts "OUI 2 is #{eui2.oui}"
276
+ print "\n"
277
+
278
+ # ei
279
+ puts "ei"
280
+ puts "EI 1 is #{eui1.ei}"
281
+ puts "EI 2 is #{eui2.ei}"
282
+ print "\n"
283
+
284
+ # address
285
+ puts "address"
286
+ puts "address 1 is #{eui1.address(:Delimiter => '.')}"
287
+ puts "address 2 is #{eui2.address(:Delimiter => '.')}"
288
+ print "\n"
289
+
290
+ # link local
291
+ puts "link local"
292
+ puts "IPv6 link local 1 is #{eui1.link_local(:Short => true)}"
293
+ puts "IPv6 link local 2 is #{eui2.link_local(:Short => true)}"
294
+ print "\n"
295
+
296
+ # type
297
+ puts "type"
298
+ puts "eui 1 type is #{eui1.type}"
299
+ puts "eui 2 type is #{eui2.type}"
300
+
301
+
302
+
303
+ =Tree:
304
+
305
+ A class & series of methods for creating and manipulating IP-based
306
+ heirarchical trees. Both IPv4 and IPv6 are supported.
307
+
308
+ Tree's are useful for creating mini 'routing tables' of CIDR address space.
309
+ Using a tree, you can quickly determine the 'route' of another CIDR via
310
+ the standard longest-match algorithm.
311
+
312
+ Tree's are not dynamic, in that if you modify any of the CIDR objects
313
+ contained within, the Tree will not automatically adjust itself accordingly.
314
+ For example if you have a tree like the following:
315
+
316
+ 192.168.0.0/24
317
+ 192.168.0.0/26
318
+ 192.168.1.0/24
319
+
320
+ You decide to resize 192.168.0.0/24 to 192.168.0.0/23. The tree will now
321
+ be incorrect:
322
+
323
+ 192.168.0.0/23
324
+ 192.168.0.0/26
325
+ 192.168.1.0/24
326
+
327
+ You would need to remove and re-add the CIDR 192.168.0.0/23 in order for the
328
+ tree to rebuild itself properly.
329
+
330
+
331
+ ====Examples:
250
332
 
333
+ #!/usr/bin/ruby
251
334
 
252
- #============================================================================#
253
- # IPAdmin::Tree
254
- #============================================================================#
335
+ require 'rubygems'
336
+ require_gem 'ipadmin'
337
+
255
338
  puts "IPAdmin::Tree"
256
339
  print "\n"
257
340
 
@@ -367,15 +450,21 @@
367
450
  new_tree6 = tree6.collapse()
368
451
  puts new_tree6.show()
369
452
 
370
- print "\n\n\n"
371
- #=====================================#
372
- #
373
- #=====================================#
374
-
375
453
 
376
- #============================================================================#
377
- # IPAdmin Methods
378
- #============================================================================#
454
+
455
+ = IPAdmin General Methods
456
+
457
+ A collection of general purpose methods that dont really fit within
458
+ a particular class.
459
+
460
+
461
+ ====Examples:
462
+
463
+ #!/usr/bin/ruby
464
+
465
+ require 'rubygems'
466
+ require_gem 'ipadmin'
467
+
379
468
  puts "IPAdmin Methods"
380
469
  print "\n"
381
470
 
@@ -430,7 +519,4 @@
430
519
  puts "unshorten"
431
520
  puts "expanded notation for fec0:: is #{IPAdmin.unshorten('fec0::')}"
432
521
 
433
- #=====================================#
434
- #
435
- #=====================================#
436
522
 
data/lib/cidr.rb CHANGED
@@ -364,11 +364,11 @@ class CIDR
364
364
  raise ArgumentError, "Expected Hash, but #{options.class} provided."
365
365
  end
366
366
 
367
- if (options.has_key?(:Short))
367
+ if (options.has_key?(:Short) && options[:Short] == true)
368
368
  short = true
369
369
  end
370
370
 
371
- if (options.has_key?(:IP))
371
+ if (options.has_key?(:IP) && options[:IP] == true)
372
372
  orig_ip = true
373
373
  end
374
374
  end
@@ -424,7 +424,7 @@ class CIDR
424
424
  bitstep = options[:Bitstep]
425
425
  end
426
426
 
427
- if( options.has_key?(:Objectify) )
427
+ if( options.has_key?(:Objectify) && options[:Objectify] == true )
428
428
  objectify = true
429
429
  end
430
430
 
@@ -432,7 +432,7 @@ class CIDR
432
432
  limit = options[:Limit]
433
433
  end
434
434
 
435
- if( options.has_key?(:Short) )
435
+ if( options.has_key?(:Short) && options[:Short] == true )
436
436
  short = true
437
437
  end
438
438
  end
@@ -522,11 +522,11 @@ class CIDR
522
522
  "#{options.class} provided."
523
523
  end
524
524
 
525
- if( options.has_key?(:Short) )
525
+ if( options.has_key?(:Short) && options[:Short] == true )
526
526
  short = true
527
527
  end
528
528
 
529
- if( options.has_key?(:Objectify) )
529
+ if( options.has_key?(:Objectify) && options[:Objectify] == true )
530
530
  objectify = true
531
531
  end
532
532
  end
@@ -563,7 +563,7 @@ class CIDR
563
563
  # * String or CIDR object.
564
564
  #
565
565
  # - Notes:
566
- # * The broadcast() method is liased to this method, and thus works for
566
+ # * The broadcast() method is aliased to this method, and thus works for
567
567
  # IPv6 despite the fact that the IPv6 protocol does not support IP
568
568
  # broadcasting.
569
569
  #
@@ -580,11 +580,11 @@ class CIDR
580
580
  "#{options.class} provided."
581
581
  end
582
582
 
583
- if( options.has_key?(:Short) )
583
+ if( options.has_key?(:Short) && options[:Short] == true )
584
584
  short = true
585
585
  end
586
586
 
587
- if( options.has_key?(:Objectify) )
587
+ if( options.has_key?(:Objectify) && options[:Objectify] == true )
588
588
  objectify = true
589
589
  end
590
590
 
@@ -608,6 +608,69 @@ class CIDR
608
608
  #======================================#
609
609
 
610
610
 
611
+ #==============================================================================#
612
+ # multicast_mac()
613
+ #==============================================================================#
614
+
615
+ # Assuming this CIDR is a valid multicast address (224.0.0.0/4 for IPv4
616
+ # and ff00::/8 for IPv6), return its ethernet MAC address (EUI-48) mapping.
617
+ #
618
+ # - Arguments:
619
+ # * Optional hash with the following fields:
620
+ # - :Objectify -- if true, return EUI objects (optional)
621
+ #
622
+ # - Returns:
623
+ # * EUI object
624
+ #
625
+ # - Note:
626
+ # * MAC address is based on original IP address passed during initialization.
627
+ #
628
+ # Example:
629
+ # mcast = IPAdmin::CIDR.new(:CIDR => '224.0.0.6')
630
+ # puts mcast.multicast_mac.address --> 01-00-5e-00-00-06
631
+ #
632
+ def multicast_mac(options=nil)
633
+ objectify = false
634
+
635
+ if (options)
636
+ if (!options.kind_of? Hash)
637
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
638
+ end
639
+
640
+ if (options.has_key?(:Objectify) && options[:Objectify] == true)
641
+ objectify = true
642
+ end
643
+ end
644
+
645
+ if (@version == 4)
646
+ if (@ip & 0xf0000000 == 0xe0000000)
647
+ # map low order 23-bits of ip to 01:00:5e:00:00:00
648
+ mac = @ip & 0x007fffff | 0x01005e000000
649
+ else
650
+ raise "#{self.ip} is not a valid multicast address. IPv4 multicast " +
651
+ "addresses should be in the range 224.0.0.0/4."
652
+ end
653
+ else
654
+ if (@ip & (0xff << 120) == 0xff << 120)
655
+ # map low order 32-bits of ip to 33:33:00:00:00:00
656
+ mac = @ip & (2**32-1) | 0x333300000000
657
+ else
658
+ raise "#{self.ip} is not a valid multicast address. IPv6 multicast " +
659
+ "addresses should be in the range ff00::/8."
660
+ end
661
+ end
662
+
663
+ eui = IPAdmin::EUI.new(:PackedEUI => mac)
664
+ eui = eui.address if (!objectify)
665
+
666
+ return(eui)
667
+ end
668
+
669
+ #======================================#
670
+ #
671
+ #======================================#
672
+
673
+
611
674
  #==============================================================================#
612
675
  # netmask()
613
676
  #==============================================================================#
@@ -691,11 +754,11 @@ class CIDR
691
754
  "#{options.class} provided."
692
755
  end
693
756
 
694
- if( options.has_key?(:Short) )
757
+ if( options.has_key?(:Short) && options[:Short] == true )
695
758
  short = true
696
759
  end
697
760
 
698
- if( options.has_key?(:Objectify) )
761
+ if( options.has_key?(:Objectify) && options[:Objectify] == true )
699
762
  objectify = true
700
763
  end
701
764
  end
@@ -753,11 +816,11 @@ class CIDR
753
816
  bitstep = options[:Bitstep]
754
817
  end
755
818
 
756
- if( options.has_key?(:Short) )
819
+ if( options.has_key?(:Short) && options[:Short] == true )
757
820
  short = true
758
821
  end
759
822
 
760
- if( options.has_key?(:Objectify) )
823
+ if( options.has_key?(:Objectify) && options[:Objectify] == true )
761
824
  objectify = true
762
825
  end
763
826
  end
@@ -818,11 +881,11 @@ class CIDR
818
881
  bitstep = options[:Bitstep]
819
882
  end
820
883
 
821
- if( options.has_key?(:Short) )
884
+ if( options.has_key?(:Short) && options[:Short] == true )
822
885
  short = true
823
886
  end
824
887
 
825
- if( options.has_key?(:Objectify) )
888
+ if( options.has_key?(:Objectify) && options[:Objectify] == true )
826
889
  objectify = true
827
890
  end
828
891
  end
@@ -883,11 +946,11 @@ class CIDR
883
946
  end
884
947
  index = options[:Index]
885
948
 
886
- if( options.has_key?(:Short) )
949
+ if( options.has_key?(:Short) && options[:Short] == true )
887
950
  short = true
888
951
  end
889
952
 
890
- if( options.has_key?(:Objectify) )
953
+ if( options.has_key?(:Objectify) && options[:Objectify] == true )
891
954
  objectify = true
892
955
  end
893
956
 
@@ -1057,11 +1120,11 @@ class CIDR
1057
1120
  raise ArgumentError, "Index #{indexes[1]} is out of bounds for this CIDR."
1058
1121
  end
1059
1122
 
1060
- if( options.has_key?(:Short) )
1123
+ if( options.has_key?(:Short) && options[:Short] == true )
1061
1124
  short = true
1062
1125
  end
1063
1126
 
1064
- if( options.has_key?(:Objectify) )
1127
+ if( options.has_key?(:Objectify) && options[:Objectify] == true )
1065
1128
  objectify = true
1066
1129
  end
1067
1130
 
@@ -1100,7 +1163,7 @@ class CIDR
1100
1163
  # Given a portion of the current CIDR, provide the remainder of
1101
1164
  # the CIDR. For example if the original CIDR is 192.168.0.0/24 and you
1102
1165
  # provide 192.168.0.64/26 as the portion to exclude, then 192.168.0.0/26,
1103
- # 192.168.0.128/26, and 192.168.0.192/26 will be returned as the remainder.
1166
+ # and 192.168.0.128/25 will be returned as the remainder.
1104
1167
  #
1105
1168
  # - Arguments:
1106
1169
  # * Optional hash with the following fields:
@@ -1134,11 +1197,11 @@ class CIDR
1134
1197
  "for option: Exclude."
1135
1198
  end
1136
1199
 
1137
- if( options.has_key?(:Short) )
1200
+ if( options.has_key?(:Short) && options[:Short] == true )
1138
1201
  short = true
1139
1202
  end
1140
1203
 
1141
- if( options.has_key?(:Objectify) )
1204
+ if( options.has_key?(:Objectify) && options[:Objectify] == true )
1142
1205
  objectify = true
1143
1206
  end
1144
1207
 
@@ -1321,7 +1384,7 @@ class CIDR
1321
1384
  # of specified size. If :MinCount is provided, then method will return at least
1322
1385
  # that number of subnets (of size X) and the remainder of the new subnets
1323
1386
  # will be merged together as tightly as possible. If a size is not provided,
1324
- # then the current object will be split in half.
1387
+ # then the current CIDR will be split in half.
1325
1388
  #
1326
1389
  # - Arguments:
1327
1390
  # * Optional hash with the following fields:
@@ -1368,11 +1431,11 @@ class CIDR
1368
1431
  min_count = options[:MinCount]
1369
1432
  end
1370
1433
 
1371
- if( options.has_key?(:Short) )
1434
+ if( options.has_key?(:Short) && options[:Short] == true )
1372
1435
  short = true
1373
1436
  end
1374
1437
 
1375
- if( options.has_key?(:Objectify) )
1438
+ if( options.has_key?(:Objectify) && options[:Objectify] == true )
1376
1439
  objectify = true
1377
1440
  end
1378
1441