ip 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Checks if a given IP address exists in a subnet.
4
+ #
5
+ # Takes either IPv6 or IPv4.
6
+ #
7
+
8
+ begin
9
+ require 'rubygems'
10
+ rescue LoadError => e
11
+ end
12
+
13
+ require 'ip'
14
+
15
+ if !ARGV[0] or !ARGV[1]
16
+ $stderr.puts "usage: #{File.basename($0)} <cidr> <ip>"
17
+ exit -1
18
+ end
19
+
20
+ if IP::CIDR.new(ARGV[0]).includes? IP::Address::Util.string_to_ip(ARGV[1])
21
+ $stderr.puts "IP #{ARGV[1]} exists in the #{ARGV[0]} subnet"
22
+ exit 0
23
+ else
24
+ $stderr.puts "IP #{ARGV[1]} does not exist in the #{ARGV[0]} subnet"
25
+ exit 1
26
+ end
27
+
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # given two CIDR formatted addresses, check for overlaps.
4
+ #
5
+ # Takes either IPv6 or IPv4.
6
+ #
7
+
8
+ begin
9
+ require 'rubygems'
10
+ rescue LoadError => e
11
+ end
12
+
13
+ require 'ip'
14
+
15
+ if !ARGV[0] or !ARGV[1]
16
+ $stderr.puts "usage: #{File.basename($0)} <cidr> <cidr>"
17
+ exit -1
18
+ end
19
+
20
+ if IP::CIDR.new(ARGV[0]).overlaps? IP::CIDR.new(ARGV[1])
21
+ $stderr.puts "These address ranges overlap."
22
+ exit 1
23
+ else
24
+ $stderr.puts "No overlaps"
25
+ exit 0
26
+ end
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Generate a set of A records suitable for inclusion in a
4
+ # zone.
5
+ #
6
+ # Takes two IP addresses as a range to generate.
7
+ #
8
+
9
+ begin
10
+ require 'rubygems'
11
+ rescue LoadError => e
12
+ end
13
+
14
+ require 'ip'
15
+
16
+ if !ARGV[0] or !ARGV[1]
17
+ $stderr.puts "usage: #{File.basename($0)} <start ip> <end ip>"
18
+ exit -1
19
+ end
20
+
21
+ $fmt = "%15.15s IN A %15.15s"
22
+
23
+ IP::Range[ARGV[0], ARGV[1]].each do |ip|
24
+ hostname = ip.ip_address.gsub(/\./, "-")
25
+ puts ($fmt % [hostname, ip.ip_address])
26
+ end
data/lib/ip.rb CHANGED
@@ -5,6 +5,7 @@
5
5
  # Author:: Erik Hollensbe
6
6
  # License:: BSD
7
7
  # Contact:: erik@hollensbe.org
8
+ # Copyright:: Copyright (c) 2005-2006 Erik Hollensbe
8
9
  #
9
10
  # IP is, as mentioned above, a collection of tools to work
10
11
  # with IP addresses. There are three major classes included
@@ -30,7 +31,7 @@
30
31
  # methods that made code easier to understand and/or clearer, and
31
32
  # making plenty of suggestions made creating this module much easier.
32
33
  #
33
- # ================================================================
34
+ #--
34
35
  #
35
36
  # The compilation of software known as ip.rb is distributed under the
36
37
  # following terms:
@@ -54,6 +55,7 @@
54
55
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55
56
  # SUCH DAMAGE.
56
57
  #
58
+ #++
57
59
 
58
60
  class IP
59
61
 
@@ -74,344 +76,12 @@ class IP
74
76
  class BoundaryException < Exception
75
77
  end
76
78
 
77
- #
78
- # IP::Range - Calculates a range of IP addresses, and returns an
79
- # Array of IP::Address objects.
80
- #
81
- # Usage::
82
- #
83
- # IP::Range['10.0.0.1', '10.0.0.2'] => IP::Address objects between
84
- # 10.0.0.1 and 10.0.0.2 (inclusive)
85
- #
86
- # IP::Range can also take two IP::Address objects.
87
- #
88
- # Will throw a IP::AddressException if for some reason addresses
89
- # cannot be parsed.
90
- #
91
-
92
- class Range
93
-
94
- #
95
- # See the documentation for IP::Range for more information on this
96
- # method.
97
- #
98
-
99
- def Range.[](addr1, addr2)
100
- raw1, raw2 = [nil, nil]
101
-
102
- if addr1.kind_of? String
103
- raw1 = IP::Address::Util.pack(IP::Address.new(addr1))
104
- elsif addr1.kind_of? IP::Address
105
- raw1 = IP::Address::Util.pack(addr1)
106
- else
107
- raise IP::AddressException("IP Address is not type String or IP::Address")
108
- end
109
-
110
- if addr2.kind_of? String
111
- raw2 = IP::Address::Util.pack(IP::Address.new(addr2))
112
- elsif addr2.kind_of? IP::Address
113
- raw2 = IP::Address::Util.pack(addr2)
114
- else
115
- raise IP::AddressException("IP Address is not type String or IP::Address")
116
- end
117
-
118
- range = []
119
-
120
- (raw1..raw2).each { |x| range.push(IP::Address::Util.unpack(x)) }
121
-
122
- return range
123
- end
124
- end
125
-
126
- #
127
- # IP::CIDR - Works with Classless Inter-Domain Routing formats, such
128
- # as 10.0.0.1/32 or 10.0.0.1/255.255.255.255
129
- #
130
-
131
- class CIDR
132
- #
133
- # Contains the original CIDR you fed it, returned as a string.
134
- #
135
- attr_reader :cidr
136
- #
137
- # Contains the IP address (LHS) only. Returned as an IP::Address
138
- # object.
139
- #
140
- attr_reader :ip
141
- #
142
- # Contains the integer-based (short) netmask (RHS) only. Returned as an
143
- # integer.
144
- #
145
- attr_reader :mask
146
-
147
- #
148
- # Given a string of format X.X.X.X/X, in standard CIDR notation,
149
- # this will construct a IP::CIDR object.
150
- #
151
- def initialize(cidr)
152
- if !cidr.kind_of? String
153
- raise IP::AddressException.new("CIDR value is not of type String")
154
- end
155
-
156
- @cidr = cidr
157
- @ip, @mask = cidr.split(/\//, 2)
158
-
159
- if @ip.nil? or @mask.nil?
160
- raise IP::AddressException.new("CIDR is not valid - invalid format")
161
- end
162
-
163
- if @mask.length == 0 or /[^0-9.]/.match @mask
164
- raise IP::AddressException.new("CIDR RHS is not valid - #{@mask}")
165
- end
166
-
167
- if @mask.length > 2
168
- # this will throw an exception if the netmask is malformed.
169
- @mask = IP::Address::Util.short_netmask(IP::Address.new(@mask))
170
- end
171
-
172
- @ip = IP::Address.new(@ip)
173
- @mask = @mask.to_i
174
- end
175
-
176
- def netmask
177
- warn "IP::CIDR#netmask is deprecated. Please use IP::CIDR#long_netmask instead."
178
- return self.long_netmask
179
- end
180
-
181
- #
182
- # This produces the long netmask (eg. 255.255.255.255) of the CIDR in an
183
- # IP::Address object.
184
- #
185
- def long_netmask
186
- return IP::Address::Util.long_netmask(@mask)
187
- end
188
-
189
- #
190
- # This produces the short netmask (eg. 32) of the CIDR in an IP::Address
191
- # object.
192
- #
193
-
194
- def short_netmask
195
- return @mask
196
- end
197
-
198
- #
199
- # This produces a range ala IP::Range, but only for the subnet
200
- # defined by the CIDR object.
201
- #
202
- def range
203
- return IP::Range[self.first_ip, self.last_ip]
204
- end
205
-
206
- #
207
- # This returns the first ip address of the cidr as an IP::Address object.
208
- #
209
- def first_ip
210
- rawip = IP::Address::Util.pack(@ip)
211
- rawnm = 0xFFFFFFFF << (32 - @mask)
212
- lower = rawip & rawnm
213
- return IP::Address::Util.unpack(lower)
214
- end
215
-
216
- #
217
- # This returns the last ip address of the cidr as an IP::Address object.
218
- #
219
- def last_ip
220
- rawip = IP::Address::Util.pack(@ip)
221
- rawnm = 0xFFFFFFFF << (32 - @mask)
222
- upper = rawip | ~rawnm
223
- return IP::Address::Util.unpack(upper)
224
- end
225
-
226
- #
227
- # This will take another IP::CIDR object as an argument and check to see
228
- # if it overlaps with this cidr object. Returns true/false on overlap.
229
- #
230
- # This also throws a TypeError if passed invalid data.
231
- #
232
- def overlaps?(other_cidr)
233
- raise TypeError.new("Expected object of type IP::CIDR") unless(other_cidr.kind_of?(IP::CIDR))
234
-
235
- myfirst = IP::Address::Util.pack(self.first_ip)
236
- mylast = IP::Address::Util.pack(self.last_ip)
237
-
238
- otherfirst = IP::Address::Util.pack(other_cidr.first_ip)
239
- otherlast = IP::Address::Util.pack(other_cidr.last_ip)
240
-
241
- return ((myfirst >= otherfirst && myfirst <= otherlast) ||
242
- (mylast <= otherlast && mylast >= otherfirst) ||
243
- (otherfirst >= myfirst && otherfirst <= mylast)) ? true : false;
244
- end
245
-
246
- end
247
-
248
- #
249
- # IP::Address - utility class to work with dotted-quad IP addresses.
250
- #
251
- class Address
252
- #
253
- # This original IP Address you passed it, returned as a string.
254
- #
255
- attr_reader :ip_address
256
- #
257
- # This returns an Array of Integer which contains the octets of
258
- # the IP, in descending order.
259
- #
260
- attr_reader :octets
261
-
262
- #
263
- # When given a string, constructs an IP::Address object.
264
- #
265
- def initialize(ip_address)
266
- if ! ip_address.kind_of? String
267
- raise IP::AddressException.new("Fed IP address is not String")
268
- end
269
- @ip_address = ip_address
270
-
271
- #
272
- # Unbeknowest by me, to_i will not throw an exception if the string
273
- # can't be converted cleanly - it just truncates, similar to atoi() and perl's int().
274
- #
275
- # Code below does a final sanity check.
276
- #
277
-
278
- octets = ip_address.split(/\./)
279
- octets_i = octets.collect { |x| x.to_i }
280
-
281
- 0.upto(octets.length - 1) do |octet|
282
- if octets[octet] != octets_i[octet].to_s
283
- raise IP::AddressException.new("Integer conversion failed")
284
- end
285
- end
286
-
287
- @octets = octets_i
288
-
289
- # I made a design decision to allow 0.0.0.0 here.
290
- if @octets.length != 4 or @octets.find_all { |x| x > 255 }.length > 0
291
- raise IP::AddressException.new("IP address is improperly formed")
292
- end
293
- end
294
-
295
- #
296
- # Returns an octet given the proper index. The octets returned are
297
- # Integer types.
298
- #
299
- def [](num)
300
- if num > 3
301
- raise IP::BoundaryException.new("Max octet number is 3")
302
- end
303
- return @octets[num]
304
- end
305
-
306
- #
307
- # See [].
308
- #
309
- alias_method :octet, :[]
310
-
311
- #
312
- # Class method to pack an IP::Address object into a long integer
313
- # used for calculation. Returns a 'FixNum' type.
314
- #
315
- # This method is deprecated. Please use IP::Address::Util#pack instead.
316
- #
317
- def Address.pack(ip)
318
- warn "IP::Address#pack is deprecated. Please use IP::Address::Util#pack instead."
319
- return IP::Address::Util.pack(ip)
320
- end
321
-
322
- #
323
- # Class method to take a 'FixNum' type and return an IP::Address
324
- # object.
325
- #
326
- # This method is deprecated. Please use IP::Address::Util#unpack instead.
327
- #
328
- def Address.unpack(ip)
329
- warn "IP::Address#unpack is deprecated. Please use IP::Address::Util#unpack instead."
330
- return IP::Address::Util.unpack(ip)
331
- end
332
-
333
- end
334
-
335
79
  end
336
80
 
337
- module IP::Address::Util
338
- #
339
- # Pack an IP::Address object into a long integer
340
- # used for calculation. Returns a 'FixNum' type.
341
- #
342
- def pack(ip)
343
- ret = 0
344
- myip = ip.octets.reverse
345
- 4.times { |x| ret = ret | (myip[x] & 0xFF) << 8*x }
346
- return ret
347
- end
348
-
349
- module_function :pack
350
-
351
- #
352
- # Take a 'FixNum' type and return an IP::Address object.
353
- #
354
- def unpack(ip)
355
- ret = []
356
- 4.times { |x| ret.push((ip >> 8*x) & 0xFF) }
357
- return IP::Address.new(ret.reverse.join("."))
358
- end
359
-
360
- module_function :unpack
361
-
362
- #
363
- # Given an IP::Address object suitable for a netmask, returns the CIDR-notation
364
- # "short" netmask.
365
- #
366
- # ex:
367
- # short_netmask(IP::Address.new("255.255.255.255")) => 32
368
- # short_netmask(IP::Address.new("255.255.255.240")) => 28
369
- #
370
-
371
- def short_netmask(ip)
372
- a = []
373
- (0..3).each do |x|
374
- if x < 3 && ip[x] < 255 && ip[x+1] > 0
375
- raise IP::BoundaryException.new("Invalid Netmask")
376
- end
377
- a += binary_vector(ip[x])
378
- end
379
- retval = 0
380
- a.each { |x| retval += x }
381
- return retval
382
- end
383
-
384
- module_function :short_netmask
385
-
386
- #
387
- # Given a CIDR-notation "short" netmask, returns a IP::Address object containing
388
- # the equivalent "long" netmask.
389
- #
390
- # ex:
391
- # long_netmask(32) => IP::Address object of "255.255.255.255"
392
- # long_netmask(28) => IP::Address object of "255.255.255.240"
393
- #
394
-
395
- def long_netmask(short)
396
- raw = 0xFFFFFFFF << (32 - short)
397
- return IP::Address::Util.unpack(raw)
398
- end
399
-
400
- module_function :long_netmask
401
-
402
- #
403
- # Given a number (presumably an octet), will produce a binary vector indicating the
404
- # on/off positions as 1 or 0.
405
- #
406
- # ex:
407
- # binary_vector(255) => [1, 1, 1, 1, 1, 1, 1, 1]
408
- # binary_vector(240) => [1, 1, 1, 1, 0, 0, 0, 0]
409
- #
81
+ $:.unshift(File.dirname(__FILE__))
82
+ require 'ip/address'
83
+ require 'ip/cidr'
84
+ require 'ip/range'
85
+ require 'ip/util'
86
+ $:.shift
410
87
 
411
- def binary_vector(octet)
412
- return octet.to_i.to_s(2).split(//).collect { |x| x.to_i }
413
- end
414
-
415
- module_function :binary_vector
416
-
417
- end