netaddr 1.5.0 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,440 +0,0 @@
1
- module NetAddr
2
- private
3
-
4
- # CIDR METHODS
5
-
6
- #==============================================================================#
7
- # cidr_build()
8
- #==============================================================================#
9
-
10
- # create either a CIDRv4 or CIDRv6 object
11
- #
12
- def cidr_build(version, ip, netmask=nil, tag={}, wildcard_mask=nil, wildcard_mask_bit_flipped=false)
13
- return( NetAddr::CIDRv4.new(ip, netmask, tag, wildcard_mask, wildcard_mask_bit_flipped) ) if (version == 4)
14
- return( NetAddr::CIDRv6.new(ip, netmask, tag, wildcard_mask, wildcard_mask_bit_flipped) )
15
- end
16
- module_function :cidr_build
17
-
18
- #==============================================================================#
19
- # cidr_compare()
20
- #==============================================================================#
21
-
22
- # compare 2 CIDR objects
23
- #
24
- #return:
25
- #* 1 if the cidr1 contains cidr2
26
- #* 0 if the cidr1 and cidr2 are equal
27
- #* -1 if cidr1 is a subnet of cidr2
28
- #* nil if the two are unrelated
29
- #
30
- def cidr_compare(cidr1,cidr2)
31
- comparasin = nil
32
- if ( cidr1.to_i(:network) == cidr2.to_i(:network) )
33
- # same network, check netmask
34
- if (cidr1.to_i(:netmask) == cidr2.to_i(:netmask) )
35
- comparasin = 0
36
- elsif(cidr1.to_i(:netmask) < cidr2.to_i(:netmask))
37
- comparasin = 1
38
- elsif(cidr1.to_i(:netmask) > cidr2.to_i(:netmask))
39
- comparasin = -1
40
- end
41
-
42
- elsif( (cidr2.to_i(:network) | cidr1.to_i(:hostmask)) == (cidr1.to_i(:network) | cidr1.to_i(:hostmask)) )
43
- # cidr1 contains cidr2
44
- comparasin = 1
45
-
46
- elsif( (cidr2.to_i(:network) | cidr2.to_i(:hostmask)) == (cidr1.to_i(:network) | cidr2.to_i(:hostmask)) )
47
- # cidr2 contains cidr1
48
- comparasin = -1
49
- end
50
-
51
- return(comparasin)
52
- end
53
- module_function :cidr_compare
54
-
55
- #==============================================================================#
56
- # cidr_gt_lt()
57
- #==============================================================================#
58
-
59
- # given a pair of CIDRs, determine if first is greater than or less than the second
60
- #
61
- # return 1 if cidr1 > cidr2
62
- # return 0 if cidr1 == cidr2
63
- # return -1 if cidr1 < cidr2
64
- #
65
- def cidr_gt_lt(cidr1,cidr2)
66
- gt_lt = 1
67
- if(cidr1.to_i(:network) < cidr2.to_i(:network))
68
- gt_lt = -1
69
- elsif (cidr1.to_i(:network) == cidr2.to_i(:network))
70
- if (cidr1.to_i(:netmask) < cidr2.to_i(:netmask))
71
- gt_lt = -1
72
- elsif (cidr1.to_i(:netmask) == cidr2.to_i(:netmask))
73
- gt_lt = 0
74
- end
75
- end
76
-
77
- return(gt_lt)
78
- end
79
- module_function :cidr_gt_lt
80
-
81
- #==============================================================================#
82
- # cidr_fill_in()
83
- #==============================================================================#
84
-
85
- #Given a list of subnets of supernet, return a new list with any
86
- #holes (missing subnets) filled in.
87
- #
88
- def cidr_fill_in(supernet,list)
89
- # sort our cidr's and see what is missing
90
- complete_list = []
91
- expected = supernet.to_i(:network)
92
- all_f = supernet.all_f
93
-
94
- NetAddr.cidr_sort(list).each do |cidr|
95
- network = cidr.to_i(:network)
96
- bitstep = (all_f + 1) - cidr.to_i(:netmask)
97
-
98
- if (network > expected) # missing space at beginning of supernet, so fill in the hole
99
- num_ips_missing = network - expected
100
- sub_list = cidr_make_subnets_from_base_and_ip_count(supernet,expected,num_ips_missing)
101
- complete_list.concat(sub_list)
102
- elsif (network < expected)
103
- next
104
- end
105
-
106
- complete_list.push(cidr)
107
- expected = network + bitstep
108
- end
109
-
110
- # if expected is not the next subnet, then we're missing subnets
111
- # at the end of the cidr
112
- next_sub = supernet.next_subnet(:Objectify => true).to_i(:network)
113
- if (expected != next_sub)
114
- num_ips_missing = next_sub - expected
115
- sub_list = cidr_make_subnets_from_base_and_ip_count(supernet,expected,num_ips_missing)
116
- complete_list.concat(sub_list)
117
- end
118
-
119
- return(complete_list)
120
- end
121
- module_function :cidr_fill_in
122
-
123
- #==============================================================================#
124
- # cidr_find_in_list()
125
- #==============================================================================#
126
-
127
- # evaluate cidr against list of cidrs.
128
- #
129
- # return entry from list if entry is supernet of cidr (first matching entry)
130
- # return index # of entry if entry is a duplicate of cidr
131
- # return nil if no match found
132
- #
133
- def cidr_find_in_list(cidr,list)
134
- return(nil) if (list.length == 0)
135
-
136
- match = nil
137
- low = 0
138
- high = list.length - 1
139
- index = low + ( (high-low)/2 )
140
- while ( low <= high)
141
- cmp = cidr_gt_lt(cidr,list[index])
142
- if ( cmp == -1 )
143
- high = index - 1
144
-
145
- elsif ( cmp == 1 )
146
- if (cidr_compare(cidr,list[index]) == -1)
147
- match = list[index]
148
- break
149
- end
150
- low = index + 1
151
-
152
- else
153
- match = index
154
- break
155
- end
156
- index = low + ( (high-low)/2 )
157
- end
158
- return(match)
159
- end
160
- module_function :cidr_find_in_list
161
-
162
- #==============================================================================#
163
- # cidr_make_subnets_from_base_and_ip_count()
164
- #==============================================================================#
165
-
166
- # Make CIDR addresses from a base addr and an number of ip's to encapsulate.
167
- #
168
- #===Arguments:
169
- # * cidr
170
- # * base ip as integer
171
- # * number of ip's required
172
- #
173
- #===Returns:
174
- # * array of NetAddr::CIDR objects
175
- #
176
- def cidr_make_subnets_from_base_and_ip_count(cidr,base_addr,ip_count)
177
- list = []
178
- until (ip_count == 0)
179
- mask = cidr.all_f
180
- multiplier = 0
181
- bitstep = 0
182
- last_addr = base_addr
183
- done = false
184
- until (done == true)
185
- if (bitstep < ip_count && (base_addr & mask == last_addr & mask) )
186
- multiplier += 1
187
- elsif (bitstep > ip_count || (base_addr & mask != last_addr & mask) )
188
- multiplier -= 1
189
- done = true
190
- else
191
- done = true
192
- end
193
- bitstep = 2**multiplier
194
- mask = cidr.all_f << multiplier & cidr.all_f
195
- last_addr = base_addr + bitstep - 1
196
- end
197
-
198
- list.push(NetAddr.cidr_build(cidr.version,base_addr,mask))
199
- ip_count -= bitstep
200
- base_addr += bitstep
201
- end
202
-
203
- return(list)
204
- end
205
- module_function :cidr_make_subnets_from_base_and_ip_count
206
-
207
- #==============================================================================#
208
- # cidr_sort()
209
- #==============================================================================#
210
-
211
- # given a list of NetAddr::CIDRs, return them as a sorted list
212
- #
213
- def cidr_sort(list, desc=false)
214
- # uses simple quicksort algorithm
215
- sorted_list = []
216
- if (list.length < 1)
217
- sorted_list = list
218
- else
219
- less_list = []
220
- greater_list = []
221
- equal_list = []
222
- pivot = list[rand(list.length)]
223
- if (desc)
224
- list.each do |x|
225
- if ( pivot.to_i(:network) < x.to_i(:network) )
226
- less_list.push(x)
227
- elsif ( pivot.to_i(:network) > x.to_i(:network) )
228
- greater_list.push(x)
229
- else
230
- if ( pivot.to_i(:netmask) < x.to_i(:netmask) )
231
- greater_list.push(x)
232
- elsif ( pivot.to_i(:netmask) > x.to_i(:netmask) )
233
- less_list.push(x)
234
- else
235
- equal_list.push(x)
236
- end
237
- end
238
- end
239
- else
240
- list.each do |x|
241
- gt_lt = cidr_gt_lt(pivot,x)
242
- if (gt_lt == 1)
243
- less_list.push(x)
244
- elsif (gt_lt == -1)
245
- greater_list.push(x)
246
- else
247
- equal_list.push(x)
248
- end
249
- end
250
- end
251
-
252
- sorted_list.concat( cidr_sort(less_list, desc) )
253
- sorted_list.concat(equal_list)
254
- sorted_list.concat( cidr_sort(greater_list, desc) )
255
- end
256
-
257
- return(sorted_list)
258
- end
259
- module_function :cidr_sort
260
-
261
- #==============================================================================#
262
- # cidr_summarize()
263
- #==============================================================================#
264
-
265
- # given a list of NetAddr::CIDRs (of the same version) summarize them
266
- #
267
- # return a hash, with the key = summary address and val = array of original cidrs
268
- #
269
- def cidr_summarize(subnet_list)
270
- all_f = subnet_list[0].all_f
271
- version = subnet_list[0].version
272
- subnet_list = cidr_sort(subnet_list)
273
-
274
- # continue summarization attempts until sorted_list stops getting shorter
275
- sorted_list = subnet_list.dup
276
- sorted_list_len = sorted_list.length
277
- while (1)
278
- summarized_list = []
279
- until (sorted_list.length == 0)
280
- cidr = sorted_list.shift
281
- network, netmask = cidr.to_i(:network), cidr.to_i(:netmask)
282
- supermask = (netmask << 1) & all_f
283
- supernet = supermask & network
284
-
285
- if (network == supernet && sorted_list.length > 0)
286
- # network is lower half of supernet, so see if we have the upper half
287
- bitstep = (all_f + 1) - netmask
288
- expected = network + bitstep
289
- next_cidr = sorted_list.shift
290
- next_network, next_netmask = next_cidr.to_i(:network), next_cidr.to_i(:netmask)
291
-
292
- if ( (next_network == expected) && (next_netmask == netmask) )
293
- # we do indeed have the upper half. store new supernet.
294
- summarized_list.push( cidr_build(version,supernet,supermask) )
295
- else
296
- # we do not have the upper half. put next_cidr back into sorted_list
297
- # and store only the original network
298
- sorted_list.unshift(next_cidr)
299
- summarized_list.push(cidr)
300
- end
301
- else
302
- # network is upper half of supernet, so save original network only
303
- summarized_list.push(cidr)
304
- end
305
-
306
- end
307
-
308
- sorted_list = summarized_list.dup
309
- break if (sorted_list.length == sorted_list_len)
310
- sorted_list_len = sorted_list.length
311
- end
312
-
313
- # clean up summarized_list
314
- unique_list = {}
315
- summarized_list.reverse.each do |supernet|
316
- next if ( unique_list.has_key?(supernet.desc) )
317
- # remove duplicates
318
- unique_list[supernet.desc] = supernet
319
-
320
- # remove any summary blocks that are children of other summary blocks
321
- index = 0
322
- until (index >= summarized_list.length)
323
- subnet = summarized_list[index]
324
- if (subnet && cidr_compare(supernet,subnet) == 1 )
325
- subnet_list[index] = nil
326
- end
327
- index += 1
328
- end
329
- end
330
- summarized_list = unique_list.values
331
-
332
- # map original blocks to their summaries
333
- summarized_list.each do |supernet|
334
- supernet.tag[:Subnets] = []
335
- index = 0
336
- until (index >= subnet_list.length)
337
- subnet = subnet_list[index]
338
- if (subnet && cidr_compare(supernet,subnet) == 1 )
339
- subnet_list[index] = nil
340
- supernet.tag[:Subnets].push(subnet)
341
- end
342
- index += 1
343
- end
344
- end
345
-
346
- return( NetAddr.cidr_sort(summarized_list) )
347
- end
348
- module_function :cidr_summarize
349
-
350
- #==============================================================================#
351
- # cidr_supernets()
352
- #==============================================================================#
353
-
354
- # given a list of NetAddr::CIDRs (of the same version), return only the 'top level' blocks (i.e. blocks not
355
- # contained by other blocks
356
-
357
- def cidr_supernets(subnet_list)
358
- summary_list = []
359
- subnet_list = netmask_sort(subnet_list)
360
- subnet_list.each do |child|
361
- is_parent = true
362
- summary_list.each do |parent|
363
- if (NetAddr.cidr_compare(parent,child) == 1)
364
- is_parent = false
365
- parent.tag[:Subnets].push(child)
366
- end
367
- end
368
-
369
- if (is_parent)
370
- child.tag[:Subnets] = []
371
- summary_list.push(child)
372
- end
373
- end
374
-
375
- return(summary_list)
376
- end
377
- module_function :cidr_supernets
378
-
379
- #==============================================================================#
380
- # netmask_sort()
381
- #==============================================================================#
382
-
383
- # given a list of NetAddr::CIDRs, return them as a sorted (by netmask) list
384
- #
385
- def netmask_sort(list, desc=false)
386
- # uses simple quicksort algorithm
387
- sorted_list = []
388
- if (list.length < 1)
389
- sorted_list = list
390
- else
391
- less_list = []
392
- greater_list = []
393
- equal_list = []
394
- pivot = list[rand(list.length)]
395
- if (desc)
396
- list.each do |x|
397
- if ( pivot.to_i(:netmask) < x.to_i(:netmask) )
398
- less_list.push(x)
399
- elsif ( pivot.to_i(:netmask) > x.to_i(:netmask) )
400
- greater_list.push(x)
401
- else
402
- if ( pivot.to_i(:network) < x.to_i(:network) )
403
- greater_list.push(x)
404
- elsif ( pivot.to_i(:network) > x.to_i(:network) )
405
- less_list.push(x)
406
- else
407
- equal_list.push(x)
408
- end
409
- end
410
- end
411
- else
412
- list.each do |x|
413
- if ( pivot.to_i(:netmask) < x.to_i(:netmask) )
414
- greater_list.push(x)
415
- elsif ( pivot.to_i(:netmask) > x.to_i(:netmask) )
416
- less_list.push(x)
417
- else
418
- if ( pivot.to_i(:network) < x.to_i(:network) )
419
- greater_list.push(x)
420
- elsif ( pivot.to_i(:network) > x.to_i(:network) )
421
- less_list.push(x)
422
- else
423
- equal_list.push(x)
424
- end
425
- end
426
- end
427
- end
428
-
429
- sorted_list.concat( netmask_sort(less_list, desc) )
430
- sorted_list.concat(equal_list)
431
- sorted_list.concat( netmask_sort(greater_list, desc) )
432
- end
433
-
434
- return(sorted_list)
435
- end
436
- module_function :netmask_sort
437
-
438
- end # module NetAddr
439
-
440
- __END__