ipadmin 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -24,6 +24,7 @@
24
24
  # IPAdmin::IPAddr
25
25
  #============================================================================#
26
26
  puts "IPAdmin::IPAddr"
27
+ print "\n"
27
28
 
28
29
  # new
29
30
  ip4 = IPAdmin::IPAddr.new(:IPAddr => '192.168.1.1/24')
@@ -33,34 +34,50 @@
33
34
  ip6 = IPAdmin::IPAddr.new(:IPAddr => 'fec0::1/64')
34
35
 
35
36
  # reader/writer
36
- puts ip4.tag['test']
37
+ puts "TEST 1"
38
+ puts "ip4 tag '#{ip4.tag['test']}'"
37
39
  ip4.tag['test'] = 'modified ip4 tag'
38
- puts ip4.tag['test']
40
+ puts "updated ip4 tag '#{ip4.tag['test']}'"
41
+ puts "ip4 version #{ip4.version}"
42
+ print "\n"
39
43
 
40
44
  # base
45
+ puts "TEST 2"
41
46
  puts "ip4 base addr #{ip4.base()}"
42
47
  puts "ip6 base addr #{ip6.base()}"
48
+ print "\n"
43
49
 
44
50
  # broadcast
51
+ puts "TEST 3"
45
52
  puts "ip4 bcast addr #{ip4.broadcast()}"
53
+ print "\n"
46
54
 
47
55
  # desc
56
+ puts "TEST 4"
48
57
  puts "ip4 description #{ip4.desc()}"
49
58
  puts "ip6 description #{ip6.desc()}"
59
+ print "\n"
50
60
 
51
61
  # extended masks
62
+ puts "TEST 5"
52
63
  puts "ip4 extended hostmask #{ip4.hostmask_ext()}"
53
- puts "ip6 extended netmask #{ip4.netmask_ext()}"
64
+ puts "ip4 extended netmask #{ip4.netmask_ext()}"
65
+ print "\n"
54
66
 
55
67
  # ip
68
+ puts "TEST 6"
56
69
  puts "ip4 ip addr #{ip4.ip()}"
57
70
  puts "ip6 ip addr #{ip6.ip()}"
71
+ print "\n"
58
72
 
59
73
  # netmask
74
+ puts "TEST 7"
60
75
  puts "ip4 netmask in CIDR format #{ip4.netmask()}"
61
76
  puts "ip6 netmask in CIDR format #{ip6.netmask()}"
77
+ print "\n"
62
78
 
63
79
  # bits
80
+ puts "TEST 8"
64
81
  puts "ip4 netmask in bits #{ip4.bits()}"
65
82
  puts "ip6 netmask in bits #{ip6.bits()}"
66
83
 
@@ -73,6 +90,10 @@
73
90
  # IPAdmin::CIDR
74
91
  #============================================================================#
75
92
  puts "IPAdmin::CIDR"
93
+ print "\n"
94
+
95
+ ip4 = IPAdmin::IPAddr.new(:IPAddr => '192.168.1.1/24')
96
+ ip6 = IPAdmin::IPAddr.new(:IPAddr => 'fec0::1/64')
76
97
 
77
98
  # new
78
99
  cidr4 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0/24')
@@ -81,44 +102,64 @@
81
102
  :Tag => {'test' => 'cidr4 tag'})
82
103
  cidr6 = IPAdmin::CIDR.new(:CIDR => 'fec0::0/64')
83
104
 
84
- # attr reader/writer
85
- puts cidr4.tag['test']
105
+ # reader/writer
106
+ puts "TEST 1"
107
+ puts "cidr4 tag '#{cidr4.tag['test']}'"
86
108
  cidr4.tag['test'] = 'modified cidr4 tag'
87
- puts cidr4.tag['test']
109
+ puts "updated cidr4 tag '#{cidr4.tag['test']}'"
110
+ puts "cidr4 version #{cidr4.version}"
111
+ print "\n"
88
112
 
89
113
  # contains
114
+ puts "TEST 2"
90
115
  puts "#{cidr4.desc} contains #{ip4.desc}" if ( cidr4.contains(ip4) )
91
116
  puts "#{cidr6.desc} contains #{ip6.desc}" if ( cidr6.contains(ip6) )
117
+ print "\n"
92
118
 
93
119
  # desc
120
+ puts "TEST 3"
94
121
  puts "cidr4 description #{cidr4.desc()}"
95
122
  puts "cidr6 description #{cidr6.desc()}"
123
+ print "\n"
96
124
 
97
125
  # extended masks
126
+ puts "TEST 4"
98
127
  puts "cidr4 extended hostmask #{cidr4.hostmask_ext()}"
99
128
  puts "cidr4 extended netmask #{cidr4.netmask_ext()}"
129
+ print "\n"
100
130
 
101
131
  # netmask
132
+ puts "TEST 5"
102
133
  puts "cidr4 netmask in CIDR format #{cidr4.netmask()}"
103
134
  puts "cidr6 netmask in CIDR format #{cidr6.netmask()}"
135
+ print "\n"
104
136
 
105
137
  # bits
138
+ puts "TEST 6"
106
139
  puts "cidr4 netmask in bits #{cidr4.bits()}"
107
140
  puts "cidr6 netmask in bits #{cidr6.bits()}"
141
+ print "\n"
108
142
 
109
143
  # network
144
+ puts "TEST 7"
110
145
  puts "cidr4 network address #{cidr4.network()}"
111
146
  puts "cidr6 network address #{cidr6.network()}"
147
+ print "\n"
112
148
 
113
149
  # nth
150
+ puts "TEST 8"
114
151
  puts "cidr4 1st ip is #{cidr4.nth(:Index => 1)}"
115
152
  puts "cidr6 1st ip is #{(cidr6.nth(:Index => 1, :Objectify => 1)).desc}"
153
+ print "\n"
116
154
 
117
155
  # size
156
+ puts "TEST 9"
118
157
  puts "cidr4 size is #{cidr4.size()}"
119
158
  puts "cidr6 size is #{cidr6.size()}"
159
+ print "\n"
120
160
 
121
161
  # enumerate
162
+ puts "TEST 10"
122
163
  puts "first 4 cidr4 addresses (bitstep 32)"
123
164
  list4 = cidr4.enumerate(:Limit => 4, :Bitstep => 32)
124
165
  list4.each do |addr|
@@ -130,8 +171,10 @@
130
171
  list6.each do |addr|
131
172
  puts " #{addr.desc}"
132
173
  end
174
+ print "\n"
133
175
 
134
176
  # subnet
177
+ puts "TEST 11"
135
178
  puts "cidr4 subnetted into at least 3 /28 ranges"
136
179
  sn4 = cidr4.subnet(:Subnet => 28, :MinCount => 3)
137
180
  sn4.each do |cidr|
@@ -149,76 +192,131 @@
149
192
  #
150
193
  #=====================================#
151
194
 
195
+
152
196
  #============================================================================#
153
- # IPAdmin::CIDRTable
197
+ # IPAdmin::Tree
154
198
  #============================================================================#
155
- puts "IPAdmin::CIDRTable"
199
+ puts "IPAdmin::Tree"
200
+ print "\n"
156
201
 
157
202
  cidr4_1 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0/24')
158
- cidr4_2 = IPAdmin::CIDR.new(:CIDR => '10.1.0.0/24')
159
- cidr4_3 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0/26')
160
- cidr4_4 =IPAdmin::CIDR.new(:CIDR => '192.168.1.0/30')
161
- cidr4_5 = IPAdmin::CIDR.new(:CIDR => '192.168.1.64/26')
162
- cidr4_6 = IPAdmin::CIDR.new(:CIDR => '192.168.1.128/26')
163
- cidr4_7 = IPAdmin::CIDR.new(:CIDR => '192.168.1.192/26')
164
-
165
- cidr6_1 = IPAdmin::CIDR.new(:CIDR => 'fec0::/10')
166
- cidr6_2 = IPAdmin::CIDR.new(:CIDR => 'fe80::/10')
167
- cidr6_3 = IPAdmin::CIDR.new(:CIDR => 'fec0::/64')
168
- cidr6_4 =IPAdmin::CIDR.new(:CIDR => 'fec0::/126')
203
+ cidr4_2 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0/26')
204
+ cidr4_3 = IPAdmin::CIDR.new(:CIDR => '192.168.1.64/26')
205
+ cidr4_4 = IPAdmin::CIDR.new(:CIDR => '192.168.1.128/26')
206
+ cidr4_5 = IPAdmin::CIDR.new(:CIDR => '192.168.1.192/26')
207
+ cidr4_6 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0/27')
208
+ cidr4_7 = IPAdmin::CIDR.new(:CIDR => '192.168.1.32/27')
209
+
210
+ cidr6_1 = IPAdmin::CIDR.new(:CIDR => 'fec0::/64')
211
+ cidr6_2 = IPAdmin::CIDR.new(:CIDR => 'fec0::/66')
212
+ cidr6_3 = IPAdmin::CIDR.new(:CIDR => 'fec0::4000:0:0:0/66')
213
+ cidr6_4 = IPAdmin::CIDR.new(:CIDR => 'fec0::8000:0:0:0/66')
214
+ cidr6_5 = IPAdmin::CIDR.new(:CIDR => 'fec0::c000:0:0:0/66')
215
+ cidr6_6 = IPAdmin::CIDR.new(:CIDR => 'fec0::/67')
216
+ cidr6_7 = IPAdmin::CIDR.new(:CIDR => 'fec0::2000:0:0:0/67')
169
217
 
170
218
  # new
171
- table4 = IPAdmin::CIDRTable.new(4)
172
- table6 = IPAdmin::CIDRTable.new(6)
173
-
174
- # add_cidr
175
- table4.add_cidr(cidr4_1)
176
- table4.add_cidr(cidr4_2)
177
- table4.add_cidr(cidr4_3)
178
- table4.add_cidr(cidr4_4)
179
- table4.add_cidr(cidr4_5)
180
- table4.add_cidr(cidr4_6)
181
- table4.add_cidr(cidr4_7)
182
-
183
- table6.add_cidr(cidr6_1)
184
- table6.add_cidr(cidr6_2)
185
- table6.add_cidr(cidr6_3)
186
- table6.add_cidr(cidr6_4)
187
-
188
- # find_ip
189
- puts "#{ip4.desc} belongs in #{table4.find_ip(ip4).desc}"
190
- puts "#{ip6.desc} belongs in #{table6.find_ip(ip6).desc}"
191
-
192
- # find_space
193
- puts "all blocks that can hold a /27"
194
- list4 = table4.find_space(:Size => 27)
195
- list4.each do |cidr|
196
- puts " #{cidr.desc()}"
219
+ tree4 = IPAdmin::Tree.new(:Version => 4)
220
+ tree6 = IPAdmin::Tree.new(:Version => 6)
221
+
222
+ # add
223
+ tree4.add(cidr4_1)
224
+ tree4.add(cidr4_2)
225
+ tree4.add(cidr4_3)
226
+ tree4.add(cidr4_4)
227
+ tree4.add(cidr4_5)
228
+ tree4.add(cidr4_6)
229
+ tree4.add(cidr4_7)
230
+
231
+ tree6.add(cidr6_1)
232
+ tree6.add(cidr6_2)
233
+ tree6.add(cidr6_3)
234
+ tree6.add(cidr6_4)
235
+ tree6.add(cidr6_5)
236
+ tree6.add(cidr6_6)
237
+ tree6.add(cidr6_7)
238
+
239
+ # show
240
+ puts "TEST 1"
241
+ puts "tree4 is..."
242
+ puts tree4.show()
243
+ print "\n"
244
+ puts "tree6 is..."
245
+ puts tree6.show()
246
+ print "\n"
247
+
248
+ # collapse
249
+ puts "TEST 2"
250
+ puts "collapsed tree4 is..."
251
+ new_tree4 = tree4.collapse()
252
+ puts new_tree4.show()
253
+ print "\n"
254
+ puts "collapsed tree6 is..."
255
+ new_tree6 = tree6.collapse()
256
+ puts new_tree6.show()
257
+ print "\n"
258
+
259
+ # find space
260
+ puts "TEST 3"
261
+ puts "available /27 space"
262
+ space = tree4.find_space(:Size => 27)
263
+ space.each do |obj|
264
+ puts " #{obj.desc}"
197
265
  end
198
-
199
- puts "first block that can hold a /64"
200
- list6 = table6.find_space(:Size => 64, :Limit => 1)
201
- list6.each do |cidr|
202
- puts " #{cidr.desc()}"
266
+ print "\n"
267
+ puts "available /67 space"
268
+ space = tree6.find_space(:Size => 67)
269
+ space.each do |obj|
270
+ puts " #{obj.desc}"
203
271
  end
204
-
272
+ print "\n"
273
+
274
+ # remove
275
+ puts "TEST 4"
276
+ puts "removing #{cidr4_4.desc}"
277
+ tree4.remove(cidr4_4)
278
+ puts tree4.show()
279
+ print "\n"
280
+ puts "removing #{cidr6_4.desc}"
281
+ tree6.remove(cidr6_4)
282
+ puts tree6.show()
283
+ print "\n"
284
+
285
+ # prune
286
+ puts "TEST 5"
287
+ puts "pruning #{cidr4_2.desc}"
288
+ tree4.prune(cidr4_2)
289
+
290
+ puts "pruning #{cidr6_2.desc}"
291
+ tree6.prune(cidr6_2)
292
+ print "\n"
293
+
205
294
  # dump
206
- puts 'dump table4...'
207
- dump4 = table4.dump
208
- dump4.each do |cidr|
209
- puts " #{cidr.desc}"
210
- end
211
- puts 'dump table6...'
212
- dump6 = table6.dump
213
- dump6.each do |cidr|
214
- puts " #{cidr.desc}"
295
+ puts "TEST 6"
296
+ puts "dumping & printing tree4"
297
+ dumped = tree4.dump()
298
+ dumped.each do |val|
299
+ obj = val[:Object]
300
+ depth = val[:Depth]
301
+ if (depth > 0)
302
+ indent = " " * (depth*3)
303
+ puts indent << obj.desc()
304
+ else
305
+ puts obj.desc()
306
+ end
215
307
  end
216
-
217
- puts "remove 192.168.1.0/26 from table4"
218
- table4.rem_cidr(cidr4_3)
219
- dump4 = table4.dump
220
- dump4.each do |cidr|
221
- puts " #{cidr.desc}"
308
+ print "\n"
309
+ puts "dumping & printing tree6"
310
+ dumped = tree6.dump()
311
+ dumped.each do |val|
312
+ obj = val[:Object]
313
+ depth = val[:Depth]
314
+ if (depth > 0)
315
+ indent = " " * (depth*3)
316
+ puts indent << obj.desc()
317
+ else
318
+ puts obj.desc()
319
+ end
222
320
  end
223
321
 
224
322
  print "\n\n\n"
@@ -232,10 +330,13 @@
232
330
  puts "IPAdmin Methods"
233
331
 
234
332
  # validate ip
333
+ puts "TEST 1"
235
334
  puts "192.168.1.0 is valid" if ( IPAdmin.validate_ipv4_addr('192.168.1.0') )
236
335
  puts "192.168.1.0 is valid" if ( IPAdmin.validate_ipv6_addr('fec0::0') )
336
+ print "\n"
237
337
 
238
338
  # validate netmask
339
+ puts "TEST 2"
239
340
  puts "255.255.255.0 is valid" if (IPAdmin.validate_ipv4_netmask('255.255.255.0') )
240
341
  puts "/24 is valid" if ( IPAdmin.validate_ipv4_netmask(24) )
241
342
  puts "/64 is valid" if ( IPAdmin.validate_ipv6_netmask(64) )
@@ -244,10 +345,12 @@
244
345
  cidr4_2 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0/25')
245
346
  cidr6_1 = IPAdmin::CIDR.new(:CIDR => 'fec0::0/10')
246
347
  cidr6_2 = IPAdmin::CIDR.new(:CIDR => 'fec0::0/64')
348
+ print "\n"
247
349
 
248
- # compare_cidr
249
- comp1 = IPAdmin.compare_cidr(cidr4_1,cidr4_2)
250
- comp2 = IPAdmin.compare_cidr(cidr6_1,cidr6_2)
350
+ # compare
351
+ puts "TEST 3"
352
+ comp1 = IPAdmin.compare(cidr4_1,cidr4_2)
353
+ comp2 = IPAdmin.compare(cidr6_1,cidr6_2)
251
354
  puts "#{(comp1[0]).desc} is the supernet of #{(comp1[1]).desc}"
252
355
  puts "#{(comp2[0]).desc} is the supernet of #{(comp2[1]).desc}"
253
356
 
@@ -256,26 +359,28 @@
256
359
  cidr6_1 = IPAdmin::CIDR.new(:CIDR => 'fec0::0/128')
257
360
  cidr6_2 = IPAdmin::CIDR.new(:CIDR => 'fec0::1/128')
258
361
 
259
- # merge_cidr
260
- puts "192.168.1.0/24 and 192.168.0.0/24 merge into #{IPAdmin.merge_cidr([cidr4_1,cidr4_2]).desc}"
261
- puts "fec0::0/128 and fec0::1/128 merge into #{IPAdmin.merge_cidr([cidr6_1,cidr6_2]).desc}"
262
-
263
362
  ip1 = IPAdmin::IPAddr.new(:IPAddr => '192.168.1.0')
264
363
  ip2 = IPAdmin::IPAddr.new(:IPAddr => '192.168.1.50')
364
+ print "\n"
265
365
 
266
366
  # range
367
+ puts "TEST 4"
267
368
  list = IPAdmin.range(:Boundaries => [ip1,ip2], :Bitstep => 20 )
268
369
  puts "ip's between #{ip1.desc} and #{ip2.desc} (bitstep of 20)"
269
370
  list.each do |x|
270
371
  puts " #{x}"
271
372
  end
373
+ print "\n"
272
374
 
273
- # make_arpa
274
- puts "arpa for #{cidr4_1.desc()} is #{IPAdmin.make_arpa(cidr4_1)}"
275
- puts "arpa for #{cidr6_1.desc()} is #{IPAdmin.make_arpa(cidr6_1)}"
375
+ # arpa
376
+ puts "TEST 5"
377
+ puts "arpa for #{cidr4_1.desc()} is #{IPAdmin.arpa(cidr4_1)}"
378
+ puts "arpa for #{cidr6_1.desc()} is #{IPAdmin.arpa(cidr6_1)}"
379
+ print "\n"
276
380
 
277
- # v6_short
278
- puts "shorthand notation for #{cidr6_1.network()} is #{IPAdmin.v6_short(cidr6_1.network)}"
381
+ # shorten
382
+ puts "TEST 6"
383
+ puts "shorthand notation for #{cidr6_1.network()} is #{IPAdmin.shorten(cidr6_1.network)}"
279
384
 
280
385
  print "\n\n\n"
281
386
  #=====================================#
data/lib/ip_admin.rb CHANGED
@@ -1,86 +1,12 @@
1
- module IPAdmin
2
-
3
-
4
-
5
- #============================================================================#
6
- # compare_cidr()
7
- #============================================================================#
8
-
9
- # Compare cidr addresses of two IPAdmin::CIDR objects.
10
- # - Arguments:
11
- # * Two IPAdmin::CIDR objects
12
- #
13
- # - Returns:
14
- # * if one object is a subnet of another, then return an array in order of
15
- # [supernet,subnet]
16
- # * if both are equal, return 1
17
- # * if neither is a subnet of the other, return nil
18
- #
19
- # Example:
20
- # supernet,subnet = IPAdmin.compare_cidr(cidr1,cidr2)
21
- # puts "#{supernet.desc} is the supernet of #{subnet.desc}"
22
- #
23
-
24
- def compare_cidr(cidr1,cidr2)
25
-
26
- # we only accept CIDR objects
27
- unless ( (cidr1.kind_of? IPAdmin::CIDR)&&(cidr2.kind_of? IPAdmin::CIDR) )
28
- raise ArgumentError, "Arguments shouldbe of type IPAdmin::CIDR."
29
- end
30
-
31
- # make sure both are same version
32
- unless (cidr1.version == cidr2.version )
33
- raise "Provider CIDR objects are incompatible: " +
34
- "#{cidr1.desc}/ and #{cidr2.desc}."
35
- end
36
-
37
- network1 = cidr1.packed_network
38
- network2 = cidr2.packed_network
39
- netmask1 = cidr1.packed_netmask
40
- netmask2 = cidr2.packed_netmask
41
-
42
-
43
- # make sure cidr's arent equal. return 1's if they are
44
- if ( (network1 == network2) && (netmask1 == netmask2) )
45
- return(1)
46
- end
47
-
48
-
49
- # whichever netmask is smaller will be the supernet
50
- # if we '&' both networks by the supernet, and they are
51
- # equal, then the supernet is the parent of the other network
52
- if (netmask1 > netmask2)
53
- if ( (netmask2 & network1) == (netmask2 & network2) )
54
- supernet = cidr2
55
- subnet = cidr1
56
- end
57
-
58
- else
59
- if ( (netmask1 & network1) == (netmask1 & network2) )
60
- supernet = cidr1
61
- subnet = cidr2
62
- end
1
+ #Copyright (c) 2006 Dustin Spinhirne <dspinhir@yahoo.com>
2
+ #Licensed under the same terms as Ruby, No Warranty is provided.
63
3
 
64
- end
65
-
66
-
67
- if (supernet)
68
- return([supernet,subnet])
69
- else
70
- return(nil)
71
- end
72
-
73
- end
74
- module_function :compare_cidr
75
-
76
- #=====================================#
77
- #
78
- #=====================================#
4
+ module IPAdmin
79
5
 
80
6
 
81
7
 
82
8
  #============================================================================#
83
- # make_arpa()
9
+ # arpa()
84
10
  #============================================================================#
85
11
 
86
12
  # Given the address in the provided IPAdmin::IPAddr or IPAdmin::CIDR object,
@@ -95,9 +21,9 @@ module_function :compare_cidr
95
21
  # * IP/CIDR address in in-addr.arpa or ip6.arpa format
96
22
  #
97
23
  # Example:
98
- # arpa = IPAdmin.make_arpa(cidr)
24
+ # arpa = IPAdmin.arpa(cidr)
99
25
  #
100
- def make_arpa(object)
26
+ def arpa(object)
101
27
 
102
28
  if (object.kind_of? IPAdmin::CIDR)
103
29
  base = object.network()
@@ -149,6 +75,10 @@ def make_arpa(object)
149
75
  return(arpa)
150
76
 
151
77
  end
78
+ module_function :arpa
79
+
80
+ # DEPRICATED, DO NOT USE - this will be removed in future releases.
81
+ alias make_arpa arpa
152
82
  module_function :make_arpa
153
83
 
154
84
  #=====================================#
@@ -158,23 +88,183 @@ module_function :make_arpa
158
88
 
159
89
 
160
90
  #============================================================================#
161
- # merge_cidr()
91
+ # compare()
162
92
  #============================================================================#
163
93
 
164
- # Merge (supernet) contiguous IPAdmin::CIDR blocks into a single block.
165
- # Blocks must be contiguous, and must be able to form a single supernet.
166
- #
94
+ # Compare IPAdmin::CIDR/IPAdmin::IPAddr objects, and determine if one
95
+ # is the supernet of the other. IPAdmin::IPAddr objects will use a /32 or /128
96
+ # netmask for the comparasin.
167
97
  # - Arguments:
168
- # * array of IPAdmin::CIDR objects to merge
169
- #
98
+ # * Two IPAdmin::CIDR/IPAdmin::IPAddr objects
99
+ #
170
100
  # - Returns:
171
- # * IPAdmin::CIDR object
101
+ # * if one object is a subnet of another, then return an array in order of
102
+ # [supernet,subnet]
103
+ # * if both are equal, return 1
104
+ # * if neither is a supernet of the other, return nil
172
105
  #
173
106
  # Example:
174
- # merged = IPAdmin.merge_cidr([cidr1,cidr2])
107
+ # supernet,subnet = IPAdmin.compare_cidr(cidr1,cidr2)
108
+ # puts "#{supernet.desc} is the supernet of #{subnet.desc}"
109
+ #
110
+
111
+ def compare(obj1,obj2)
112
+
113
+ # we only accept CIDR or IPAddr objects
114
+ unless ( ( (obj1.kind_of?(IPAdmin::CIDR) ) ||
115
+ (obj1.kind_of?(IPAdmin::IPAddr) ) ) &&
116
+ ( (obj2.kind_of?(IPAdmin::CIDR) ) ||
117
+ (obj2.kind_of?(IPAdmin::IPAddr) ) ) )
118
+ raise ArgumentError, "One or more arguments is not of type " +
119
+ "IPAdmin::CIDR or IPAdmin::IPAddr."
120
+ end
121
+
122
+ # make sure both are same version
123
+ unless (obj1.version == obj2.version )
124
+ raise "Provided objects are of different IP versions."
125
+ end
126
+
127
+
128
+ # get network/netmask of each
129
+ if ( obj1.kind_of?(IPAdmin::CIDR) )
130
+ network1 = obj1.packed_network
131
+ netmask1 = obj1.packed_netmask
132
+ else
133
+ network1 = obj1.packed_ip
134
+ if (obj1.version == 4)
135
+ netmask1 = (2**32 - 1)
136
+ else
137
+ netmask1 = (2**128 - 1)
138
+ end
139
+ end
140
+
141
+ if ( obj2.kind_of?(IPAdmin::CIDR) )
142
+ network2 = obj2.packed_network
143
+ netmask2 = obj2.packed_netmask
144
+ else
145
+ network2 = obj2.packed_ip
146
+ if (obj2.version == 4)
147
+ netmask2 = (2**32 - 1)
148
+ else
149
+ netmask2 = (2**128 - 1)
150
+ end
151
+ end
152
+
153
+
154
+ # make sure object's arent equal. return 1's if they are
155
+ if ( (network1 == network2) && (netmask1 == netmask2) )
156
+ return(1)
157
+ end
158
+
159
+
160
+ # whichever netmask is smaller will be the supernet
161
+ # if we '&' both networks by the supernet, and they are
162
+ # equal, then the supernet is the parent of the other network
163
+ if (netmask1 > netmask2)
164
+ if ( (netmask2 & network1) == (netmask2 & network2) )
165
+ supernet = obj2
166
+ subnet = obj1
167
+ end
168
+
169
+ else
170
+ if ( (netmask1 & network1) == (netmask1 & network2) )
171
+ supernet = obj1
172
+ subnet = obj2
173
+ end
174
+
175
+ end
176
+
177
+
178
+ if (supernet)
179
+ return([supernet,subnet])
180
+ else
181
+ return(nil)
182
+ end
183
+
184
+ end
185
+ module_function :compare
186
+
187
+ #=====================================#
188
+ #
189
+ #=====================================#
190
+
191
+
192
+
193
+ #============================================================================#
194
+ # compare_cidr()
195
+ #============================================================================#
196
+
197
+ # DEPRICATED, DO NOT USE - this will be removed in future releases.
198
+ #
199
+ def compare_cidr(cidr1,cidr2)
200
+
201
+ puts "compare_cidr() DEPRICATED, DO NOT USE - this will be removed in future releases."
202
+
203
+ # we only accept CIDR objects
204
+ unless ( (cidr1.kind_of? IPAdmin::CIDR)&&(cidr2.kind_of? IPAdmin::CIDR) )
205
+ raise ArgumentError, "Arguments shouldbe of type IPAdmin::CIDR."
206
+ end
207
+
208
+ # make sure both are same version
209
+ unless (cidr1.version == cidr2.version )
210
+ raise "Provider CIDR objects are incompatible: " +
211
+ "#{cidr1.desc}/ and #{cidr2.desc}."
212
+ end
213
+
214
+ network1 = cidr1.packed_network
215
+ network2 = cidr2.packed_network
216
+ netmask1 = cidr1.packed_netmask
217
+ netmask2 = cidr2.packed_netmask
218
+
219
+
220
+ # make sure cidr's arent equal. return 1's if they are
221
+ if ( (network1 == network2) && (netmask1 == netmask2) )
222
+ return(1)
223
+ end
224
+
225
+
226
+ # whichever netmask is smaller will be the supernet
227
+ # if we '&' both networks by the supernet, and they are
228
+ # equal, then the supernet is the parent of the other network
229
+ if (netmask1 > netmask2)
230
+ if ( (netmask2 & network1) == (netmask2 & network2) )
231
+ supernet = cidr2
232
+ subnet = cidr1
233
+ end
234
+
235
+ else
236
+ if ( (netmask1 & network1) == (netmask1 & network2) )
237
+ supernet = cidr1
238
+ subnet = cidr2
239
+ end
240
+
241
+ end
242
+
243
+
244
+ if (supernet)
245
+ return([supernet,subnet])
246
+ else
247
+ return(nil)
248
+ end
249
+
250
+ end
251
+ module_function :compare_cidr
252
+
253
+ #=====================================#
254
+ #
255
+ #=====================================#
256
+
257
+
258
+
259
+ #============================================================================#
260
+ # merge_cidr()
261
+ #============================================================================#
262
+
263
+ # DEPRICATED, DO NOT USE - this will be removed in future releases.
175
264
  #
176
265
  def merge_cidr(cidr_list)
177
266
 
267
+ puts "merge_cidr() DEPRICATED, DO NOT USE - this will be removed in future releases."
178
268
  # make sure we have an array with at least 2 objects
179
269
  unless ( (cidr_list.kind_of? Array) && (cidr_list.length > 1) )
180
270
  raise ArgumentError, "Array of at least two IPAdmin::CIDR objects required."
@@ -641,52 +731,135 @@ module_function :range
641
731
 
642
732
 
643
733
  #============================================================================#
644
- # unpack_ipv4_addr()
734
+ # shorten()
645
735
  #============================================================================#
646
736
 
647
- # Unack IPv4 address back into a printable string. No attempt at validation
648
- # is performed.
737
+ # Take a standard IPv6 address, and format it in short-hand notation.
738
+ # Address should not contain a netmask.
649
739
  # - Arguments:
650
- # * Byte-packed IPv4 address
740
+ # * IPv6 address
651
741
  #
652
742
  # - Returns:
653
- # * IPv4 address.
654
- #
743
+ # * IPv6 short-hand address.
744
+ #
655
745
  # Example:
656
- # unpacked = IPAdmin.unpack_ipv4_addr(packed)
746
+ # short = IPAdmin.shorten('fec0:0000:0000:0000:0000:0000:0000:0001')
657
747
  #
658
- def unpack_ipv4_addr(packed_ip)
748
+ def shorten(addr)
749
+
750
+ # is this a string?
751
+ unless (addr.kind_of? String)
752
+ raise ArgumentError, "Expected String, but #{addr.class} provided."
753
+ end
754
+
755
+ validate_ipv6_addr(addr)
659
756
 
660
- octets = []
661
- (0..3).each do |x|
662
- octets[x] = packed_ip & 0xFF
663
- octets[x] = (octets[x]).to_s
664
- packed_ip = packed_ip >> 8
757
+ # make sure this isnt already shorthand
758
+ if (addr =~ /::/)
759
+ raise "#{addr} already appears to be in IPv6 shorthand notation."
665
760
  end
666
761
 
667
- octets.reverse!
668
- ip = octets.join('.')
669
762
 
670
- return(ip)
671
- end
672
- module_function :unpack_ipv4_addr
673
-
674
- #=====================================#
675
- #
676
- #=====================================#
677
-
678
-
679
-
680
- #============================================================================#
681
- # unpack_ipv4_netmask()
682
- #============================================================================#
683
-
684
- # Unack IPv4 netmask into a integer representing the number of
685
- # bits in the CIDR mask. No attempt at validation is performed.
686
- # - Arguments:
687
- # * Byte-packed IPv4 netmask
688
- #
689
- # - Returns:
763
+ # look for most 0 fields
764
+ found_zero = nil
765
+ pattern = ""
766
+ zero_fields = []
767
+ fields = addr.split(":")
768
+
769
+ (0..(fields.length-1)).each do |x|
770
+ fields[x] = fields[x].to_i(16)
771
+
772
+ if (fields[x] == 0)
773
+ if (!found_zero)
774
+ found_zero = 1
775
+ end
776
+ pattern << ":0"
777
+ else
778
+ if (found_zero)
779
+ found_zero = nil
780
+ pattern << ":"
781
+ zero_fields.push(pattern)
782
+ pattern = ""
783
+ end
784
+ end
785
+
786
+ fields[x] = fields[x].to_s(16)
787
+ end
788
+
789
+
790
+ # pattern should be the longest set of 0's in a row
791
+ zero_fields.push(pattern) if (pattern != "")
792
+ pattern = ""
793
+ zero_fields.each do |x|
794
+ pattern = x if (x.length > pattern.length)
795
+ end
796
+
797
+
798
+
799
+ short = fields.join(":")
800
+ short.sub!(pattern,"::")
801
+
802
+ return(short)
803
+ end
804
+ module_function :shorten
805
+
806
+ #DEPRICATED, DO NOT USE - this will be removed in future releases.
807
+ alias v6_short shorten
808
+ module_function :v6_short
809
+
810
+ #=====================================#
811
+ #
812
+ #=====================================#
813
+
814
+
815
+
816
+ #============================================================================#
817
+ # unpack_ipv4_addr()
818
+ #============================================================================#
819
+
820
+ # Unack IPv4 address back into a printable string. No attempt at validation
821
+ # is performed.
822
+ # - Arguments:
823
+ # * Byte-packed IPv4 address
824
+ #
825
+ # - Returns:
826
+ # * IPv4 address.
827
+ #
828
+ # Example:
829
+ # unpacked = IPAdmin.unpack_ipv4_addr(packed)
830
+ #
831
+ def unpack_ipv4_addr(packed_ip)
832
+
833
+ octets = []
834
+ (0..3).each do |x|
835
+ octets[x] = packed_ip & 0xFF
836
+ octets[x] = (octets[x]).to_s
837
+ packed_ip = packed_ip >> 8
838
+ end
839
+
840
+ octets.reverse!
841
+ ip = octets.join('.')
842
+
843
+ return(ip)
844
+ end
845
+ module_function :unpack_ipv4_addr
846
+
847
+ #=====================================#
848
+ #
849
+ #=====================================#
850
+
851
+
852
+
853
+ #============================================================================#
854
+ # unpack_ipv4_netmask()
855
+ #============================================================================#
856
+
857
+ # Unack IPv4 netmask into a integer representing the number of
858
+ # bits in the CIDR mask. No attempt at validation is performed.
859
+ # - Arguments:
860
+ # * Byte-packed IPv4 netmask
861
+ #
862
+ # - Returns:
690
863
  # * IPv4 netmask as number of bits (cidr format).
691
864
  #
692
865
  # Example:
@@ -790,85 +963,6 @@ module_function :unpack_ipv6_netmask
790
963
 
791
964
 
792
965
 
793
- #============================================================================#
794
- # v6_short()
795
- #============================================================================#
796
-
797
- # Take a standard IPv6 address, and format it in short-hand notation.
798
- # Address should not contain a netmask.
799
- # - Arguments:
800
- # * IPv6 address
801
- #
802
- # - Returns:
803
- # * IPv6 short-hand address.
804
- #
805
- # Example:
806
- # short = IPAdmin.v6_short('fec0:0000:0000:0000:0000:0000:0000:0001')
807
- #
808
- def v6_short(addr)
809
-
810
- # is this a string?
811
- unless (addr.kind_of? String)
812
- raise ArgumentError, "Expected String, but #{addr.class} provided."
813
- end
814
-
815
- validate_ipv6_addr(addr)
816
-
817
- # make sure this isnt already shorthand
818
- if (addr =~ /::/)
819
- raise "#{addr} already appears to be in IPv6 shorthand notation."
820
- end
821
-
822
-
823
- # look for most 0 fields
824
- found_zero = nil
825
- pattern = ""
826
- zero_fields = []
827
- fields = addr.split(":")
828
-
829
- (0..(fields.length-1)).each do |x|
830
- fields[x] = fields[x].to_i(16)
831
-
832
- if (fields[x] == 0)
833
- if (!found_zero)
834
- found_zero = 1
835
- end
836
- pattern << ":0"
837
- else
838
- if (found_zero)
839
- found_zero = nil
840
- pattern << ":"
841
- zero_fields.push(pattern)
842
- pattern = ""
843
- end
844
- end
845
-
846
- fields[x] = fields[x].to_s(16)
847
- end
848
-
849
-
850
- # pattern should be the longest set of 0's in a row
851
- zero_fields.push(pattern) if (pattern != "")
852
- pattern = ""
853
- zero_fields.each do |x|
854
- pattern = x if (x.length > pattern.length)
855
- end
856
-
857
-
858
-
859
- short = fields.join(":")
860
- short.sub!(pattern,"::")
861
-
862
- return(short)
863
- end
864
- module_function :v6_short
865
-
866
- #=====================================#
867
- #
868
- #=====================================#
869
-
870
-
871
-
872
966
  #============================================================================#
873
967
  # validate_ipv4_addr()
874
968
  #============================================================================#
@@ -1184,7 +1278,11 @@ class CIDR
1184
1278
  # hash of custom tags. should be in the format tag => value
1185
1279
  attr_reader :tag
1186
1280
 
1187
- # attr_writer - hash of custom tags. should be in the format tag => value
1281
+ # Hash of custom tags. should be in the format tag => value
1282
+ #
1283
+ # Example:
1284
+ # cidr4.tag['test'] = 'modified cidr4 tag'
1285
+ #
1188
1286
  def tag=(new_tag)
1189
1287
  unless (new_tag.kind_of? Hash)
1190
1288
  raise ArgumentError, "Expected Hash, but #{new_tag.class} provided."
@@ -1347,8 +1445,8 @@ class CIDR
1347
1445
  # contains()
1348
1446
  #============================================================================#
1349
1447
 
1350
- # Determines if cidr block of IPAdmin::CIDR contains IP address
1351
- # of provided IPAdmin:IPAddr object.
1448
+ # Determines if IPAdmin::CIDR object contains (is supernet of)
1449
+ # provided IPAdmin::CIDR or IPAdmin:IPAddr object.
1352
1450
  # - Arguments:
1353
1451
  # * IPAdmin:IPAddr object
1354
1452
  #
@@ -1358,32 +1456,46 @@ class CIDR
1358
1456
  # Example:
1359
1457
  # contains = cidr.contains(ip)
1360
1458
  #
1361
- def contains(ip_obj)
1459
+ def contains(object)
1460
+ is_contained = nil
1362
1461
 
1363
- unless (ip_obj.kind_of? IPAdmin::IPAddr)
1364
- raise ArgumentError, "Expected IPAdmin::IPAddr object, but #{ip_obj.class} provided."
1462
+ if (object.kind_of?(IPAdmin::CIDR))
1463
+ network = object.packed_network
1464
+ netmask = object.packed_netmask
1465
+
1466
+ elsif (object.kind_of?(IPAdmin::IPAddr))
1467
+ network = object.packed_ip
1468
+
1469
+ else
1470
+ raise ArgumentError, "Expected IPAdmin::CIDR or IPAdmin::IPAddr " +
1471
+ " object but #{object.class} provided."
1365
1472
  end
1366
1473
 
1367
- if ( (ip_obj.version == 4) && (@version == 4) )
1368
- v4_all_f = (2**32)-1
1369
- hostmask = @netmask ^ v4_all_f
1370
- if ( (ip_obj.packed_ip | hostmask) == (@network | hostmask) )
1371
- return(1)
1474
+
1475
+ unless (object.version == @version)
1476
+ raise "Attempted to compare a version #{object.version} IP " +
1477
+ "with a version #{@version} network."
1478
+ end
1479
+
1480
+
1481
+ # if network == @network, then we have to go by netmask length
1482
+ # else we can tell by or'ing network and @network by @hostmask
1483
+ # and comparing the results
1484
+ if (network == @network)
1485
+ if (object.kind_of?(IPAdmin::IPAddr) )
1486
+ is_contained = 1
1487
+ else
1488
+ is_contained = 1 if (netmask > @netmask)
1372
1489
  end
1373
1490
 
1374
- elsif ( (ip_obj.version == 6) && (@version == 6) )
1375
- v6_all_f = (2**128)-1
1376
- hostmask = @netmask ^ v6_all_f
1377
- if ( (ip_obj.packed_ip | hostmask) == (@network | hostmask) )
1378
- return(1)
1379
- end
1380
-
1381
1491
  else
1382
- raise "Attempted to compare a version #{ip_obj.version} IP " +
1383
- "with a version #{@version} network."
1492
+ if ( (network | @hostmask) == (@network | @hostmask) )
1493
+ is_contained = 1
1494
+ end
1384
1495
  end
1385
1496
 
1386
- return(nil)
1497
+
1498
+ return(is_contained)
1387
1499
  end
1388
1500
 
1389
1501
  #=====================================#
@@ -1990,8 +2102,7 @@ end
1990
2102
  #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
1991
2103
 
1992
2104
  =begin rdoc
1993
- A class & series of methods for creating and manipulating CIDR-based
1994
- heirarchical tables. Both IPv4 and IPv6 are supported.
2105
+ DEPRICATED, DO NOT USE - this will be removed in future releases.
1995
2106
  =end
1996
2107
 
1997
2108
  class CIDRTable
@@ -2002,11 +2113,8 @@ class CIDRTable
2002
2113
  # attr_reader / attr_writer
2003
2114
  #============================================================================#
2004
2115
 
2005
-
2006
- # ip table version (4 or 6)
2007
- attr_reader :version
2008
-
2009
- # contains IPAdmin::CIDR entries. hash (IPAdmin::CIDR => IPAdmin::CIDRTable)
2116
+ # attr_reader/attr_writer
2117
+ attr_reader :version
2010
2118
  attr_reader :cidr_table
2011
2119
 
2012
2120
  #=====================================#
@@ -2019,14 +2127,11 @@ class CIDRTable
2019
2127
  # initialize()
2020
2128
  #============================================================================#
2021
2129
 
2022
- # - Arguments:
2023
- # * IP version (4 or 6)
2130
+ # DEPRICATED, DO NOT USE - this will be removed in future releases.
2024
2131
  #
2025
- # Example:
2026
- # table = IPAdmin::CIDRTable.new(4)
2027
- #
2028
2132
  def initialize(version)
2029
2133
 
2134
+ puts "DEPRICATED, DO NOT USE - this will be removed in future releases."
2030
2135
  unless ( version.kind_of? Fixnum )
2031
2136
  raise ArgumentError, "Expected Fixnum, but #{version.class} provided."
2032
2137
  end
@@ -2049,16 +2154,7 @@ class CIDRTable
2049
2154
  # add_cidr()
2050
2155
  #============================================================================#
2051
2156
 
2052
- # Add an IPAdmin::CIDR object to this table
2053
- #
2054
- # - Arguments:
2055
- # * IPAdmin::CIDR object
2056
- #
2057
- # - Returns:
2058
- # * nothing
2059
- #
2060
- # Example:
2061
- # table.add_cidr(cidr)
2157
+ # DEPRICATED, DO NOT USE - this will be removed in future releases.
2062
2158
  #
2063
2159
  def add_cidr(new_cidr)
2064
2160
 
@@ -2134,16 +2230,7 @@ class CIDRTable
2134
2230
  # dump()
2135
2231
  #============================================================================#
2136
2232
 
2137
- # Dump contents of this table
2138
- #
2139
- # - Arguments:
2140
- # * none
2141
- #
2142
- # - Returns:
2143
- # * ordered array of IPAdmin::CIDR objects within this table
2144
- #
2145
- # Example:
2146
- # cidr_list = table.dump()
2233
+ # DEPRICATED, DO NOT USE - this will be removed in future releases.
2147
2234
  #
2148
2235
  def dump()
2149
2236
 
@@ -2182,17 +2269,7 @@ class CIDRTable
2182
2269
  # find_ip()
2183
2270
  #============================================================================#
2184
2271
 
2185
- # Find longest matching IPAdmin::CIDR object whose cidr block contains the IP
2186
- # address within the provided IPAdmin::IPAddr object
2187
- #
2188
- # - Arguments:
2189
- # * IPAdmin::IPAddr object
2190
- #
2191
- # - Returns:
2192
- # * IPAdmin::CIDR object, or nil on no match
2193
- #
2194
- # Example:
2195
- # cidr = table.find_ip(ip)
2272
+ # DEPRICATED, DO NOT USE - this will be removed in future releases.
2196
2273
  #
2197
2274
  def find_ip(ip_obj)
2198
2275
 
@@ -2232,19 +2309,7 @@ class CIDRTable
2232
2309
  # find_space()
2233
2310
  #============================================================================#
2234
2311
 
2235
- # Find CIDR blocks of at least X size. Returns only the smallest matching
2236
- # subnets of each supernet.
2237
- #
2238
- # - Arguments:
2239
- # * Hash with the following fields:
2240
- # - :Size -- subnet size (number of bits)
2241
- # - :Limit -- max entries to return
2242
- #
2243
- # - Returns:
2244
- # * ordered array of IPAdmin::CIDR objects, or nil on no match
2245
- #
2246
- # Example:
2247
- # cidr_list = table.find_space(:Size => 27)
2312
+ # DEPRICATED, DO NOT USE - this will be removed in future releases.
2248
2313
  #
2249
2314
  def find_space(options)
2250
2315
  limit = nil
@@ -2338,16 +2403,7 @@ class CIDRTable
2338
2403
  # rem_cidr()
2339
2404
  #============================================================================#
2340
2405
 
2341
- # Remove an IPAdmin::CIDR object from this table
2342
- #
2343
- # - Arguments:
2344
- # * IPAdmin::CIDR object
2345
- #
2346
- # - Returns:
2347
- # * nothing
2348
- #
2349
- # Example:
2350
- # table.rem_cidr(cidr)
2406
+ # DEPRICATED, DO NOT USE - this will be removed in future releases.
2351
2407
  #
2352
2408
  def rem_cidr(cidr)
2353
2409
 
@@ -2434,7 +2490,11 @@ class IPAddr
2434
2490
  # hash of custom tags. should be in the format tag => value
2435
2491
  attr_reader :tag
2436
2492
 
2437
- # attr_writer - hash of custom tags. should be in the format tag => value
2493
+ # Hash of custom tags. should be in the format tag => value
2494
+ #
2495
+ # Example:
2496
+ # ip4.tag['test'] = 'modified ip4 tag'
2497
+ #
2438
2498
  def tag=(new_tag)
2439
2499
  unless (new_tag.kind_of? Hash)
2440
2500
  raise ArgumentError, "Expected Hash, but #{new_tag.class} provided."
@@ -2911,6 +2971,883 @@ end
2911
2971
  #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
2912
2972
 
2913
2973
 
2974
+
2975
+
2976
+
2977
+
2978
+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
2979
+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
2980
+ #
2981
+ # BEGIN class Tree
2982
+ #
2983
+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
2984
+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
2985
+
2986
+ =begin rdoc
2987
+ A class & series of methods for creating and manipulating IP-based
2988
+ heirarchical trees. Both IPv4 and IPv6 are supported.
2989
+ =end
2990
+
2991
+ class Tree
2992
+
2993
+ # define structure for our tree leaves
2994
+ NetStruct = Struct.new(:network, :netmask, :object, :subnets)
2995
+
2996
+ #============================================================================#
2997
+ # attr_reader / attr_writer
2998
+ #============================================================================#
2999
+
3000
+
3001
+ # IP version for this tree (4 or 6)
3002
+ attr_reader :version
3003
+
3004
+ #=====================================#
3005
+ #
3006
+ #=====================================#
3007
+
3008
+
3009
+
3010
+ #============================================================================#
3011
+ # initialize()
3012
+ #============================================================================#
3013
+
3014
+ # - Arguments:
3015
+ # * Hash with the following fields
3016
+ # - :Version -- IP version for this tree (4 or 6)
3017
+ #
3018
+ # Example:
3019
+ # table = IPAdmin::CIDRTable.new(:Version => 4)
3020
+ #
3021
+ def initialize(options)
3022
+ unless (options.kind_of? Hash)
3023
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
3024
+ end
3025
+
3026
+ if ( options.has_key?(:Version) )
3027
+ @version = options[:Version]
3028
+
3029
+ unless ( @version == 4 || @version == 6 )
3030
+ raise "IP version should be either 4 or 6."
3031
+ end
3032
+ else
3033
+ raise ArgumentError, "Missing arguments: Version."
3034
+ end
3035
+
3036
+ if (@version == 4)
3037
+ @all_f = 2**32 - 1
3038
+ else
3039
+ @all_f = 2**128 - 1
3040
+ end
3041
+
3042
+ # root of our ordered IP tree
3043
+ @root = []
3044
+
3045
+ end
3046
+
3047
+ #=====================================#
3048
+ #
3049
+ #=====================================#
3050
+
3051
+
3052
+
3053
+ #============================================================================#
3054
+ # add()
3055
+ #============================================================================#
3056
+
3057
+ # Add an IPAdmin::CIDR/IPAdmin::IPAddr object to the tree. IPAdmin::IPAddr
3058
+ # objects will be treated as either /32 or /128 addresses when added to the
3059
+ # tree.
3060
+ #
3061
+ # - Arguments:
3062
+ # * IPAdmin::CIDR/IPAdmin::IPAddr object
3063
+ #
3064
+ # - Returns:
3065
+ # * nothing
3066
+ #
3067
+ # Example:
3068
+ # tree.add(cidr)
3069
+ #
3070
+ def add(object)
3071
+
3072
+ # make sure we have an array with at least 2 objects
3073
+ unless ( object.kind_of?(IPAdmin::CIDR) ||
3074
+ object.kind_of?(IPAdmin::IPAddr) )
3075
+ raise ArgumentError, "IPAdmin::CIDR/IPAdmin::IPAddr object " +
3076
+ "required but #{object.class} provided."
3077
+ end
3078
+
3079
+ unless (object.version == @version )
3080
+ raise "IP version #{object.version} is incompatible with " +
3081
+ "Tree IP version #{@version}."
3082
+ end
3083
+
3084
+
3085
+ net_struct = create_struct(object)
3086
+
3087
+
3088
+ # search tree for it's home branch
3089
+ search_results = find_home(net_struct, @root)
3090
+ home_struct = search_results[0] if (search_results)
3091
+ home_branch = home_struct.subnets if (search_results)
3092
+ home_branch = @root if (!home_branch)
3093
+
3094
+ # make sure we dont have a duplicate
3095
+ if (home_struct)
3096
+ if ( (net_struct.network == home_struct.network) &&
3097
+ (net_struct.netmask == home_struct.netmask) )
3098
+ raise "Attempted to add #{object.desc()} multiple times."
3099
+ end
3100
+ end
3101
+
3102
+
3103
+ # now that we have our branch location, check that other entries
3104
+ # of this branch are not subnets of our new object. if they are
3105
+ # then make them a branch of our new object
3106
+ home_branch.each do |entry|
3107
+ is_contained = contains(net_struct, entry)
3108
+
3109
+ if (is_contained)
3110
+ net_struct.subnets.push(entry)
3111
+ end
3112
+ end
3113
+
3114
+ net_struct.subnets.each do |entry|
3115
+ home_branch.delete(entry)
3116
+ end
3117
+
3118
+
3119
+ # add new object as an ordered entry to home_branch
3120
+ add_to_branch(net_struct,home_branch)
3121
+
3122
+ return(nil)
3123
+ end
3124
+
3125
+ #=====================================#
3126
+ #
3127
+ #=====================================#
3128
+
3129
+
3130
+
3131
+ #============================================================================#
3132
+ # add_to_branch() private
3133
+ #============================================================================#
3134
+
3135
+ # Add Netstruct object to an array of NetStruct's
3136
+ #
3137
+ # - Arguments:
3138
+ # * NetStruct, and array of NetStruct's in which to add it
3139
+ #
3140
+ # - Returns:
3141
+ # * none
3142
+ #
3143
+ # Example:
3144
+ # add_to_branch(net_struct,branch)
3145
+ #
3146
+ def add_to_branch(net_struct,branch)
3147
+ index = 0
3148
+ branch.each do
3149
+ if(net_struct.network < (branch[index]).network)
3150
+ break
3151
+ end
3152
+ index += 1
3153
+ end
3154
+
3155
+ branch.insert(index, net_struct)
3156
+
3157
+ return()
3158
+ end
3159
+
3160
+ #=====================================#
3161
+ #
3162
+ #=====================================#
3163
+
3164
+
3165
+
3166
+ #============================================================================#
3167
+ # collapse()
3168
+ #============================================================================#
3169
+
3170
+ # Collapse (supernet) all subnets of the tree,
3171
+ # and return a new tree. The supernetting of subnets will only occur in
3172
+ # situations where the newly created supernet will not result in the
3173
+ # 'creation' of additional space. For example the following blocks
3174
+ # (192.168.0.0/24, 192.168.1.0/24, and 192.168.2.0/24) would merge into
3175
+ # 192.168.0.0/23 and 192.168.2.0/24 rather than into 192.168.0.0/22.
3176
+ #
3177
+ # - Arguments:
3178
+ # * none
3179
+ #
3180
+ # - Returns:
3181
+ # * IPAdmin::Tree object
3182
+ #
3183
+ # Example:
3184
+ # new_tree = tree.collapse()
3185
+ #
3186
+ def collapse()
3187
+ tree = IPAdmin::Tree.new(:Version => @version)
3188
+ branch = collapse_branch(@root)
3189
+ dumped = dump_branch(branch)
3190
+ dumped.each do |entry|
3191
+ net_struct = entry[:NetStruct]
3192
+
3193
+ if (@version == 4)
3194
+ network = IPAdmin.unpack_ipv4_addr(net_struct.network)
3195
+ netmask = IPAdmin.unpack_ipv4_netmask(net_struct.netmask)
3196
+ else
3197
+ network = IPAdmin.unpack_ipv6_addr(net_struct.network)
3198
+ netmask = IPAdmin.unpack_ipv6_netmask(net_struct.netmask)
3199
+ end
3200
+ cidr = IPAdmin::CIDR.new(:CIDR => "#{network}/#{netmask}")
3201
+ tree.add(cidr)
3202
+ end
3203
+ return(tree)
3204
+ end
3205
+
3206
+ #=====================================#
3207
+ #
3208
+ #=====================================#
3209
+
3210
+
3211
+
3212
+ #============================================================================#
3213
+ # collapse_branch() private
3214
+ #============================================================================#
3215
+
3216
+ # Collapse this branch, and any child branches that it may have.
3217
+ #
3218
+ # - Arguments:
3219
+ # * Array of NetStruct objects
3220
+ #
3221
+ # - Returns:
3222
+ # * Array of NetStruct objects. The 'object' filed will be null.
3223
+ #
3224
+ # Example:
3225
+ # new_branch = collapse_branch(old_branch)
3226
+ #
3227
+ def collapse_branch(old_branch)
3228
+ new_branch = []
3229
+
3230
+ # create new_branch from old one
3231
+ old_branch.each do |entry|
3232
+ net_struct = NetStruct.new(entry.network,entry.netmask,nil,[])
3233
+
3234
+ if (entry.subnets.length > 0)
3235
+ # get all child subnets of this branch entry
3236
+ children = collapse_branch(entry.subnets)
3237
+ grandchildren = nil
3238
+
3239
+ # if any child subnets are equal to this branch entry
3240
+ # then copy the grandchild subnets and delete it
3241
+ children.each do |child|
3242
+ if ( (entry.network == child.network) &&
3243
+ (entry.netmask == child.netmask) )
3244
+ if (child.subnets.length > 0)
3245
+ grandchildren = child.subnets
3246
+ end
3247
+ children.delete(child)
3248
+ break
3249
+ end
3250
+ end
3251
+
3252
+ net_struct.subnets.concat(children)
3253
+ if (grandchildren)
3254
+ grandchildren.each do |grandchild|
3255
+ add_to_branch(grandchild,net_struct.subnets)
3256
+ end
3257
+ end
3258
+ end
3259
+
3260
+ new_branch.push(net_struct)
3261
+ end
3262
+
3263
+ # merge subnets of this new branch by removing them from 'new_branch',
3264
+ # and categorizing them into hash of arrays (key=netmask)
3265
+ # within each categorization we merge contiguous subnets
3266
+ # and then remove them from that category & put them back into
3267
+ # 'new_branch'. we do this until our list stops getting any shorter
3268
+ categories = {}
3269
+ branch_length = 0
3270
+ until (branch_length == new_branch.length)
3271
+ branch_length = new_branch.length
3272
+
3273
+ # bust in to categories
3274
+ new_branch.each do |entry|
3275
+ netmask = entry.netmask
3276
+ if (categories.has_key?(netmask) )
3277
+ (categories[netmask]).push(entry)
3278
+ else
3279
+ categories[netmask] = [entry]
3280
+ end
3281
+ end
3282
+ new_branch.clear
3283
+
3284
+ categories.each_key do |netmask|
3285
+ entries = categories[netmask]
3286
+
3287
+ until (entries.length == 0)
3288
+ supernet = nil
3289
+ supermask = nil
3290
+ multiplier = 0
3291
+ first = entries[0]
3292
+ to_merge = []
3293
+
3294
+ # take first entry and use it to form a base
3295
+ # supernet address. this supernet should have
3296
+ # x number of subnets in it, so we look for
3297
+ # those subnets & if found store them
3298
+ entries.each do |entry|
3299
+ num_required = 2**multiplier
3300
+ supermask = (netmask << multiplier) & @all_f
3301
+ supernet = supermask & first.network if (!supernet)
3302
+
3303
+ if ( (entry.network & supermask) == supernet)
3304
+ to_merge.push(entry)
3305
+ if ( (to_merge.length == num_required) &&
3306
+ (entries.length > (2**multiplier) ) )
3307
+ multiplier += 1
3308
+ end
3309
+ else
3310
+ multiplier -= 1
3311
+ supermask = (netmask << multiplier) & @all_f
3312
+ break
3313
+ end
3314
+ end
3315
+
3316
+ # now that we have the child members of our new supernet
3317
+ # take any grandchild subnets that they may have and
3318
+ # add them to the new supernet. then kill the children
3319
+ net_struct = NetStruct.new(supernet,supermask,nil,[])
3320
+ (2**multiplier).times do
3321
+ to_kill = to_merge.shift
3322
+ net_struct.subnets.concat(to_kill.subnets)
3323
+ entries.delete(to_kill)
3324
+ end
3325
+ new_branch.push(net_struct)
3326
+
3327
+ end
3328
+ end
3329
+ categories.clear
3330
+ end
3331
+
3332
+ return(new_branch)
3333
+ end
3334
+
3335
+ #=====================================#
3336
+ #
3337
+ #=====================================#
3338
+
3339
+
3340
+
3341
+ #============================================================================#
3342
+ # contains() private
3343
+ #============================================================================#
3344
+
3345
+ # Is the first NetStruct object the supernet of the second?
3346
+ #
3347
+ # - Arguments:
3348
+ # * Two NetStruct objects
3349
+ #
3350
+ # - Returns:
3351
+ # * 1 if struct1 contains or is equal to struct2, or nil if not.
3352
+ #
3353
+ # Example:
3354
+ # is_contained = contains(struct1,struct2)
3355
+ #
3356
+ def contains(struct1,struct2)
3357
+
3358
+ # make sure we have appropriate types
3359
+ unless (struct1.kind_of?(IPAdmin::Tree::NetStruct) &&
3360
+ struct2.kind_of?(IPAdmin::Tree::NetStruct) )
3361
+ raise ArgumentError, "Incorrect argument types " +
3362
+ "#{struct1.class} and #{struct2.class}."
3363
+ end
3364
+
3365
+ network1 = struct1.network
3366
+ netmask1 = struct1.netmask
3367
+ network2 = struct2.network
3368
+ netmask2 = struct2.netmask
3369
+ hostmask1 = netmask1 ^ @all_f
3370
+
3371
+
3372
+ # if network1 == network2, then we have to go by netmask length
3373
+ # else we can tell by or'ing network1 and network2 by hostmask1
3374
+ # and comparing the results
3375
+ is_contained = nil
3376
+ if (network1 == network2)
3377
+ if (netmask2 >= netmask1)
3378
+ is_contained = 1
3379
+ end
3380
+ else
3381
+ if ( (network1 | hostmask1) == (network2 | hostmask1) )
3382
+ is_contained = 1
3383
+ end
3384
+ end
3385
+
3386
+ return(is_contained)
3387
+ end
3388
+
3389
+ #=====================================#
3390
+ #
3391
+ #=====================================#
3392
+
3393
+
3394
+
3395
+ #============================================================================#
3396
+ # create_struct() private
3397
+ #============================================================================#
3398
+
3399
+ # Create a NetStruct object from a CIDR or IPAddr object
3400
+ #
3401
+ # - Arguments:
3402
+ # * IPAdmin::CIDR or IPAdmin::IPAddr object
3403
+ #
3404
+ # - Returns:
3405
+ # * IPAdmin::Tree::NetStruct object
3406
+ #
3407
+ # Example:
3408
+ # net_struct = create_struct(object)
3409
+ #
3410
+ def create_struct(object)
3411
+
3412
+ if ( object.kind_of?(IPAdmin::CIDR) )
3413
+ network = object.packed_network
3414
+ netmask = object.packed_netmask
3415
+
3416
+ elsif ( object.kind_of?(IPAdmin::IPAddr) )
3417
+ network = object.packed_ip
3418
+ netmask = @all_f
3419
+ end
3420
+
3421
+ net_struct = NetStruct.new(network, netmask, object, [])
3422
+
3423
+ return(net_struct)
3424
+ end
3425
+
3426
+ #=====================================#
3427
+ #
3428
+ #=====================================#
3429
+
3430
+
3431
+
3432
+ #============================================================================#
3433
+ # dump
3434
+ #============================================================================#
3435
+
3436
+ # Dump the contents of this tree.
3437
+ #
3438
+ # - Arguments:
3439
+ # * none
3440
+ #
3441
+ # - Returns:
3442
+ # * ordered array of hashes in the form: :Object => CIDR or IPAddr object
3443
+ # :Depth => (depth level in tree)
3444
+ # Example:
3445
+ # dumped = tree.dump()
3446
+ #
3447
+ def dump()
3448
+ list = []
3449
+ dumped = dump_branch(@root)
3450
+
3451
+ dumped.each do |entry|
3452
+ depth = entry[:Depth]
3453
+ net_struct = entry[:NetStruct]
3454
+ object = net_struct.object
3455
+ list.push({:Depth => depth, :Object => object})
3456
+ end
3457
+
3458
+ return(list)
3459
+ end
3460
+
3461
+ #=====================================#
3462
+ #
3463
+ #=====================================#
3464
+
3465
+
3466
+
3467
+ #============================================================================#
3468
+ # dump_branch() private
3469
+ #============================================================================#
3470
+
3471
+ # Dump contents of an Array of NetStruct objects
3472
+ #
3473
+ # - Arguments:
3474
+ # * array of NetStruct objects, and an optional depth within the tree
3475
+ #
3476
+ # - Returns:
3477
+ # * array of hashes in form: :NetStruct => IPAdmin::Tree::NetStruct object
3478
+ # :Depth => (depth level in tree)
3479
+ # Example:
3480
+ # dumped = dump_branch(branch)
3481
+ #
3482
+ def dump_branch(branch,depth=nil)
3483
+ list = []
3484
+ depth = 0 if (!depth)
3485
+
3486
+ branch.each do |entry|
3487
+ subnets = entry.subnets
3488
+ list.push({:NetStruct => entry, :Depth => depth})
3489
+
3490
+ if (subnets.length > 0)
3491
+ list.concat( dump_branch(subnets, (depth+1) ) )
3492
+ end
3493
+
3494
+ end
3495
+
3496
+ return(list)
3497
+ end
3498
+
3499
+ #=====================================#
3500
+ #
3501
+ #=====================================#
3502
+
3503
+
3504
+
3505
+ #============================================================================#
3506
+ # find()
3507
+ #============================================================================#
3508
+
3509
+ # Find the branch of this tree to which an IPAdmin::CIDR or IPAdmin::IPAddr
3510
+ # would belong if added. This is useful for finding the longest match for
3511
+ # an IP address.
3512
+ #
3513
+ # - Arguments:
3514
+ # * IPAdmin::CIDR or IPAdmin::IPAddr object
3515
+ #
3516
+ # - Returns:
3517
+ # * IPAdmin::CIDR object, or nil if not found
3518
+ #
3519
+ # Example:
3520
+ # longest_match = tree.find(ip)
3521
+ #
3522
+ def find(object)
3523
+ unless ( object.kind_of?(IPAdmin::CIDR) ||
3524
+ object.kind_of?(IPAdmin::IPAddr) )
3525
+ raise ArgumentError, "IPAdmin::CIDR/IPAdmin::IPAddr object " +
3526
+ "required but #{object.class} provided."
3527
+ end
3528
+
3529
+ unless (object.version == @version )
3530
+ raise "IP version #{object.version} is incompatible with " +
3531
+ "Tree IP version #{@version}."
3532
+ end
3533
+
3534
+ net_struct = create_struct(object)
3535
+ home_struct,home_branch = find_home(net_struct, @root)
3536
+ found_obj = home_struct.object if (home_struct)
3537
+
3538
+ return(found_obj)
3539
+ end
3540
+
3541
+ #=====================================#
3542
+ #
3543
+ #=====================================#
3544
+
3545
+
3546
+
3547
+ #============================================================================#
3548
+ # find_home() private
3549
+ #============================================================================#
3550
+
3551
+ # Find the branch to which a NetStruct object belongs.
3552
+ #
3553
+ # - Arguments:
3554
+ # * IPAdmin::Tree::NetStruct to find, and Array of
3555
+ # IPAdmin::Tree::NetStruct's to search
3556
+ #
3557
+ # - Returns:
3558
+ # * array of: container IPAdmin::Tree::NetStruct object,
3559
+ # and container branch, or nil
3560
+ #
3561
+ # Example:
3562
+ # branch = find_home(net_struct,branch)
3563
+ #
3564
+ def find_home(net_struct,branch)
3565
+ ret_val = nil
3566
+
3567
+ branch.each do |entry|
3568
+ is_contained = contains(entry,net_struct)
3569
+
3570
+ if (is_contained)
3571
+ home_struct = entry
3572
+ home_branch = branch
3573
+
3574
+ if (home_struct.subnets.length > 0)
3575
+ search_results = find_home(net_struct,home_struct.subnets)
3576
+ if (search_results)
3577
+ home_struct = search_results[0]
3578
+ home_branch = search_results[1]
3579
+ end
3580
+ end
3581
+
3582
+ ret_val = [home_struct,home_branch]
3583
+ break
3584
+ end
3585
+ end
3586
+
3587
+ return(ret_val)
3588
+ end
3589
+
3590
+ #=====================================#
3591
+ #
3592
+ #=====================================#
3593
+
3594
+
3595
+
3596
+ #============================================================================#
3597
+ # find_space()
3598
+ #============================================================================#
3599
+
3600
+ # Find Tree entries of at least X size. Returns only the smallest matching
3601
+ # subnets of each supernet.
3602
+ #
3603
+ # - Arguments:
3604
+ # * Hash with the following fields:
3605
+ # - :Size -- subnet size (number of bits)
3606
+ # - :Limit -- max entries to return
3607
+ #
3608
+ # - Returns:
3609
+ # * ordered array of IPAdmin::CIDR/IPAdmin::IPAddr objects
3610
+ #
3611
+ # Example:
3612
+ # list = tree.find_space(:Size => 27)
3613
+ #
3614
+ def find_space(options)
3615
+ limit = nil
3616
+ list = []
3617
+
3618
+ # validate options
3619
+ unless (options.kind_of? Hash)
3620
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
3621
+ end
3622
+
3623
+ unless ( options.has_key?(:Size) )
3624
+ raise ArgumentError, "Missing argument :Size."
3625
+ end
3626
+ subnet_size = options[:Size]
3627
+
3628
+ if ( options.has_key?(:Limit) )
3629
+ limit = options[:Limit]
3630
+ end
3631
+
3632
+
3633
+ # check that subnet_size is a valid size
3634
+ if (@version == 4)
3635
+ unless ( (subnet_size > 0) && (subnet_size < 33) )
3636
+ raise "#{subnet_size} is out of range for an " +
3637
+ "IP version #{@version} Tree."
3638
+ end
3639
+
3640
+ else
3641
+ unless ( (subnet_size > 0) && (subnet_size < 129) )
3642
+ raise "#{subnet_size} is out of range for an " +
3643
+ "IP version #{@version} Tree."
3644
+ end
3645
+ end
3646
+
3647
+ search_list = dump_branch(@root)
3648
+
3649
+ search_list.each do |entry|
3650
+ depth = entry[:Depth]
3651
+ net_struct = entry[:NetStruct]
3652
+
3653
+ # we only want leaf nodes of type IPAdmin::CIDR
3654
+ if ( (net_struct.subnets.length == 0) &&
3655
+ (net_struct.object.kind_of?(IPAdmin::CIDR)) )
3656
+
3657
+ if (subnet_size >= net_struct.object.bits)
3658
+ list.push(net_struct.object)
3659
+ end
3660
+ end
3661
+
3662
+ if (limit && (list.length >= limit) )
3663
+ break
3664
+ end
3665
+
3666
+ end
3667
+
3668
+ return(list)
3669
+
3670
+ end
3671
+
3672
+ #=====================================#
3673
+ #
3674
+ #=====================================#
3675
+
3676
+
3677
+
3678
+ #============================================================================#
3679
+ # prune()
3680
+ #============================================================================#
3681
+
3682
+ # Remove an IPAdmin::CIDR/IPAdmin::IPAddr object, and all child
3683
+ # objects from the tree.
3684
+ #
3685
+ # - Arguments:
3686
+ # * IPAdmin::CIDR or IPAdmin::IPAddr object
3687
+ #
3688
+ # - Returns:
3689
+ # * 1 on success, or nil
3690
+ #
3691
+ # Example:
3692
+ # did_prune = tree.prune(ip)
3693
+ #
3694
+ def prune(object)
3695
+ unless ( object.kind_of?(IPAdmin::CIDR) ||
3696
+ object.kind_of?(IPAdmin::IPAddr) )
3697
+ raise ArgumentError, "IPAdmin::CIDR/IPAdmin::IPAddr object " +
3698
+ "required but #{object.class} provided."
3699
+ end
3700
+
3701
+ unless (object.version == @version )
3702
+ raise "IP version #{object.version} is incompatible with " +
3703
+ "Tree IP version #{@version}."
3704
+ end
3705
+
3706
+ net_struct = create_struct(object)
3707
+ home_struct,home_branch = find_home(net_struct, @root)
3708
+
3709
+ # remove if home_struct.object = object
3710
+ if (home_struct.object = object)
3711
+ home_branch.delete(home_struct)
3712
+ pruned = 1
3713
+ end
3714
+
3715
+ return(pruned)
3716
+ end
3717
+
3718
+ #=====================================#
3719
+ #
3720
+ #=====================================#
3721
+
3722
+
3723
+
3724
+ #============================================================================#
3725
+ # remove()
3726
+ #============================================================================#
3727
+
3728
+ # Remove a single IPAdmin::CIDR/IPAdmin::IPAddr object from the tree.
3729
+ #
3730
+ # - Arguments:
3731
+ # * IPAdmin::CIDR or IPAdmin::IPAddr object
3732
+ #
3733
+ # - Returns:
3734
+ # * 1 on success, or nil
3735
+ #
3736
+ # Example:
3737
+ # did_remove = tree.remove(ip)
3738
+ #
3739
+ def remove(object)
3740
+ unless ( object.kind_of?(IPAdmin::CIDR) ||
3741
+ object.kind_of?(IPAdmin::IPAddr) )
3742
+ raise ArgumentError, "IPAdmin::CIDR/IPAdmin::IPAddr object " +
3743
+ "required but #{object.class} provided."
3744
+ end
3745
+
3746
+ unless (object.version == @version )
3747
+ raise "IP version #{object.version} is incompatible with " +
3748
+ "Tree IP version #{@version}."
3749
+ end
3750
+
3751
+ net_struct = create_struct(object)
3752
+ home_struct,home_branch = find_home(net_struct, @root)
3753
+
3754
+ # remove if home_struct.object = object
3755
+ if (home_struct.object = object)
3756
+
3757
+ # if we have children subnets, move them up one level
3758
+ if (home_struct.subnets.length > 0)
3759
+ home_struct.subnets.each do |entry|
3760
+ index = 0
3761
+ home_branch.each do
3762
+ if(entry.network < (home_branch[index]).network)
3763
+ break
3764
+ end
3765
+ index += 1
3766
+ end
3767
+ home_branch.insert(index, entry)
3768
+ end
3769
+ end
3770
+
3771
+ home_branch.delete(home_struct)
3772
+ removed = 1
3773
+ end
3774
+
3775
+ return(removed)
3776
+ end
3777
+
3778
+ #=====================================#
3779
+ #
3780
+ #=====================================#
3781
+
3782
+
3783
+
3784
+ #============================================================================#
3785
+ # show()
3786
+ #============================================================================#
3787
+
3788
+ # Print the tree in a nicely formatted string.
3789
+ #
3790
+ # - Arguments:
3791
+ # * none
3792
+ #
3793
+ # - Returns:
3794
+ # * string representing the contents of the tree
3795
+ #
3796
+ # Example:
3797
+ # puts tree.show()
3798
+ #
3799
+ def show()
3800
+ printed = ""
3801
+ list = dump_branch(@root)
3802
+
3803
+ list.each do |entry|
3804
+ net_struct = entry[:NetStruct]
3805
+ depth = entry[:Depth]
3806
+
3807
+ if (@version == 4)
3808
+ network = IPAdmin.unpack_ipv4_addr(net_struct.network)
3809
+ netmask = IPAdmin.unpack_ipv4_netmask(net_struct.netmask)
3810
+
3811
+ else
3812
+ network = IPAdmin.unpack_ipv6_addr(net_struct.network)
3813
+ netmask = IPAdmin.unpack_ipv6_netmask(net_struct.netmask)
3814
+ network = IPAdmin.shorten(network)
3815
+ end
3816
+
3817
+ if (depth == 0)
3818
+ indent = ""
3819
+ else
3820
+ indent = " " * (depth*3)
3821
+ end
3822
+
3823
+ printed << "#{indent}#{network}/#{netmask}\n"
3824
+ end
3825
+
3826
+ return(printed)
3827
+ end
3828
+
3829
+ #=====================================#
3830
+ #
3831
+ #=====================================#
3832
+
3833
+
3834
+
3835
+ private :add_to_branch, :contains, :collapse_branch, :create_struct,
3836
+ :dump_branch, :find_home
3837
+
3838
+ end
3839
+
3840
+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
3841
+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
3842
+ #
3843
+ # END class Tree
3844
+ #
3845
+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
3846
+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
3847
+
3848
+
3849
+
3850
+
2914
3851
  end # module IPAdmin
2915
3852
 
2916
3853