netaddr 1.5.3 → 2.0.6

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