ipadmin 0.1.2 → 0.1.3

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
@@ -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