ip 0.1.1 → 0.2.0

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