ipadmin 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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