ip 0.3.0 → 0.3.1
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.
- checksums.yaml +7 -0
- data/lib/ip.rb +2 -29
- data/lib/ip/address.rb +50 -50
- data/lib/ip/cidr.rb +22 -22
- data/lib/ip/range.rb +6 -6
- data/lib/ip/util.rb +22 -22
- metadata +9 -15
- data/Rakefile +0 -76
- data/examples/check-included.rb +0 -27
- data/examples/check-overlap.rb +0 -26
- data/examples/generate-a-records.rb +0 -26
- data/test/test_ip.rb +0 -313
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c3086640a7e7397faa00f2ba00d9e819dcbc0283
|
4
|
+
data.tar.gz: 500578f6568f2efffa81e5059e0a1bf0c5161189
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: af8209509af45f35f3047d876e7a6417527d2c489f4ce6c17323fe1903a2a50fdc08f62e8b114e216c7b112897defbe197f2be0d8b28d807910989fdc63df22d
|
7
|
+
data.tar.gz: ac60f52cd2982a6445438cbd6ada38ca2ac814e8ec738e71485689f99b4ad8fcbfa1e544d83c6924f0ae6a2a35b91285757abd7700f18eef61a19d11482c2a97
|
data/lib/ip.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# Version:: 0.3.0
|
5
5
|
# Author:: Erik Hollensbe
|
6
|
-
# License::
|
6
|
+
# License:: MIT
|
7
7
|
# Contact:: erik@hollensbe.org
|
8
8
|
# Copyright:: Copyright (c) 2005-2006 Erik Hollensbe
|
9
9
|
#
|
@@ -30,36 +30,9 @@
|
|
30
30
|
# 'trial by fire' as this package came out of it's shell. Writing new
|
31
31
|
# methods that made code easier to understand and/or clearer, and
|
32
32
|
# making plenty of suggestions made creating this module much easier.
|
33
|
-
#
|
34
|
-
#--
|
35
|
-
#
|
36
|
-
# The compilation of software known as ip.rb is distributed under the
|
37
|
-
# following terms:
|
38
|
-
# Copyright (C) 2005-2006 Erik Hollensbe. All rights reserved.
|
39
|
-
#
|
40
|
-
# Redistribution and use in source form, with or without
|
41
|
-
# modification, are permitted provided that the following conditions
|
42
|
-
# are met:
|
43
|
-
# 1. Redistributions of source code must retain the above copyright
|
44
|
-
# notice, this list of conditions and the following disclaimer.
|
45
|
-
#
|
46
|
-
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
47
|
-
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
48
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
49
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
50
|
-
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
51
|
-
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
52
|
-
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
53
|
-
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
54
|
-
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
55
|
-
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
56
|
-
# SUCH DAMAGE.
|
57
|
-
#
|
58
|
-
#++
|
59
33
|
|
60
34
|
class IP
|
61
|
-
|
62
|
-
VERSION = "0.3.0"
|
35
|
+
VERSION = "0.3.1"
|
63
36
|
|
64
37
|
#
|
65
38
|
# A IP::AddressException is thrown when an IP address cannot be
|
data/lib/ip/address.rb
CHANGED
@@ -10,7 +10,7 @@ class IP::Address
|
|
10
10
|
attr_reader :ip_address
|
11
11
|
#
|
12
12
|
# This returns an Array of Integer which contains the octets of
|
13
|
-
# the IP, in descending order.
|
13
|
+
# the IP, in descending order.
|
14
14
|
#
|
15
15
|
attr_reader :octets
|
16
16
|
|
@@ -24,12 +24,12 @@ class IP::Address
|
|
24
24
|
end
|
25
25
|
return @octets[num]
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
#
|
29
29
|
# See [].
|
30
30
|
#
|
31
31
|
alias_method :octet, :[]
|
32
|
-
|
32
|
+
|
33
33
|
#
|
34
34
|
# Returns a 128-bit integer representing the address.
|
35
35
|
#
|
@@ -66,42 +66,42 @@ class IP::Address::IPv4 < IP::Address
|
|
66
66
|
# unpack to generate a string, and parse that.
|
67
67
|
# overwrites 'ip_address'
|
68
68
|
# horribly inefficient, but general.
|
69
|
-
|
69
|
+
|
70
70
|
raw = IP::Address::Util.raw_unpack(ip_address)[0..1]
|
71
71
|
octets = []
|
72
|
-
|
72
|
+
|
73
73
|
2.times do |x|
|
74
74
|
octets.push(raw[x] & 0x00FF)
|
75
75
|
octets.push((raw[x] & 0xFF00) >> 8)
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
ip_address = octets.reverse.join(".")
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
if ! ip_address.kind_of? String
|
82
82
|
raise IP::AddressException.new("Fed IP address '#{ip_address}' is not String or Fixnum")
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
@ip_address = ip_address
|
86
|
-
|
86
|
+
|
87
87
|
#
|
88
88
|
# Unbeknowest by me, to_i will not throw an exception if the string
|
89
89
|
# can't be converted cleanly - it just truncates, similar to atoi() and perl's int().
|
90
90
|
#
|
91
91
|
# Code below does a final sanity check.
|
92
92
|
#
|
93
|
-
|
93
|
+
|
94
94
|
octets = ip_address.split(/\./)
|
95
95
|
octets_i = octets.collect { |x| x.to_i }
|
96
|
-
|
96
|
+
|
97
97
|
0.upto(octets.length - 1) do |octet|
|
98
98
|
if octets[octet] != octets_i[octet].to_s
|
99
99
|
raise IP::AddressException.new("Integer conversion failed")
|
100
100
|
end
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
@octets = octets_i
|
104
|
-
|
104
|
+
|
105
105
|
# I made a design decision to allow 0.0.0.0 here.
|
106
106
|
if @octets.length != 4 or @octets.find_all { |x| x > 255 }.length > 0
|
107
107
|
raise IP::AddressException.new("IP address is improperly formed")
|
@@ -116,14 +116,14 @@ class IP::Address::IPv4 < IP::Address
|
|
116
116
|
# that the IP address is of a certain size and has certain numeric limits.
|
117
117
|
myip = self.octets
|
118
118
|
packval = [0] * 6
|
119
|
-
|
119
|
+
|
120
120
|
#
|
121
121
|
# this ensures that the octets are 8 bit, and combines the octets in order to
|
122
122
|
# form two 16-bit integers suitable for pushing into the last places in 'packval'
|
123
123
|
#
|
124
|
-
|
124
|
+
|
125
125
|
(0..3).step(2) { |x| packval.push(((myip[x] & 0xFF) << 8) | (myip[x+1] & 0xFF)) }
|
126
|
-
|
126
|
+
|
127
127
|
return IP::Address::Util.raw_pack(packval)
|
128
128
|
end
|
129
129
|
|
@@ -151,7 +151,7 @@ class IP::Address::IPv6 < IP::Address
|
|
151
151
|
#
|
152
152
|
# * A string which contains a valid, RFC4291-compliant IPv6 address
|
153
153
|
# (all forms are supported, including the
|
154
|
-
# backwards-compatibility IPv4 methods)
|
154
|
+
# backwards-compatibility IPv4 methods)
|
155
155
|
#
|
156
156
|
# * A 128-bit integer which is a sum of all the octets, left-most
|
157
157
|
# octet being the highest 32-bit portion (see IP::Address::Util
|
@@ -163,20 +163,20 @@ class IP::Address::IPv6 < IP::Address
|
|
163
163
|
# unpack to generate a string, and parse that.
|
164
164
|
# overwrites 'ip_address'
|
165
165
|
# horribly inefficient, but general.
|
166
|
-
|
166
|
+
|
167
167
|
raw = IP::Address::Util.raw_unpack(ip_address)
|
168
|
-
|
168
|
+
|
169
169
|
ip_address = format_address(raw.reverse)
|
170
170
|
end
|
171
|
-
|
171
|
+
|
172
172
|
if ! ip_address.kind_of? String
|
173
173
|
raise IP::AddressException.new("Fed IP address '#{ip_address}' is not String or Fixnum")
|
174
174
|
end
|
175
|
-
|
175
|
+
|
176
176
|
@ip_address = ip_address
|
177
|
-
|
177
|
+
|
178
178
|
octets = parse_address(ip_address)
|
179
|
-
|
179
|
+
|
180
180
|
if octets.length != 8
|
181
181
|
raise IP::AddressException.new("IPv6 address '#{ip_address}' does not have 8 octets or a floating range specifier")
|
182
182
|
end
|
@@ -185,14 +185,14 @@ class IP::Address::IPv6 < IP::Address
|
|
185
185
|
# Now we check the contents of the address, to be sure we have
|
186
186
|
# proper hexidecimal values
|
187
187
|
#
|
188
|
-
|
188
|
+
|
189
189
|
@octets = octets_atoi(octets)
|
190
190
|
end
|
191
|
-
|
191
|
+
|
192
192
|
#
|
193
|
-
# parses an ip address and stores it as the current object.
|
193
|
+
# parses an ip address and stores it as the current object.
|
194
194
|
#
|
195
|
-
|
195
|
+
|
196
196
|
def IPv6.parse(ip_address)
|
197
197
|
return IP::Address::IPv6.new(ip_address)
|
198
198
|
end
|
@@ -212,7 +212,7 @@ class IP::Address::IPv6 < IP::Address
|
|
212
212
|
#
|
213
213
|
# IP::Address::IPv6.new("DEAD::BEEF").long_address => "DEAD:0:0:0:0:0:0:BEEF"
|
214
214
|
#
|
215
|
-
|
215
|
+
|
216
216
|
def long_address
|
217
217
|
return format_address
|
218
218
|
end
|
@@ -220,7 +220,7 @@ class IP::Address::IPv6 < IP::Address
|
|
220
220
|
#
|
221
221
|
# Returns a shortened address using the :: range specifier.
|
222
222
|
#
|
223
|
-
# This will replace any sequential octets that are equal to '0' with '::'.
|
223
|
+
# This will replace any sequential octets that are equal to '0' with '::'.
|
224
224
|
# It does this searching from right to left, looking for a sequence
|
225
225
|
# of them. Per specification, only one sequence can be replaced in
|
226
226
|
# this fashion. It will return a long address if it can't find
|
@@ -235,13 +235,13 @@ class IP::Address::IPv6 < IP::Address
|
|
235
235
|
|
236
236
|
# short circuit: if less than 2 octets are equal to 0, don't
|
237
237
|
# bother - return a long address.
|
238
|
-
|
238
|
+
|
239
239
|
if octets.find_all { |x| x == 0 }.length < 2
|
240
240
|
return format_address(octets)
|
241
241
|
end
|
242
242
|
|
243
243
|
filling = false
|
244
|
-
|
244
|
+
|
245
245
|
left = []
|
246
246
|
right = []
|
247
247
|
|
@@ -259,18 +259,18 @@ class IP::Address::IPv6 < IP::Address
|
|
259
259
|
right.push(octets[x])
|
260
260
|
end
|
261
261
|
end
|
262
|
-
|
262
|
+
|
263
263
|
return format_address(left.reverse) + "::" + format_address(right.reverse)
|
264
|
-
|
264
|
+
|
265
265
|
end
|
266
|
-
|
266
|
+
|
267
267
|
#
|
268
268
|
# Returns a 128-bit integer representing the address.
|
269
269
|
#
|
270
270
|
def pack
|
271
271
|
return IP::Address::Util.raw_pack(self.octets.dup)
|
272
272
|
end
|
273
|
-
|
273
|
+
|
274
274
|
#
|
275
275
|
# An IP Address is equal if the ip address match
|
276
276
|
#
|
@@ -317,35 +317,35 @@ class IP::Address::IPv6 < IP::Address
|
|
317
317
|
octets = address.split(":")
|
318
318
|
|
319
319
|
if octets.length < 8
|
320
|
-
|
320
|
+
|
321
321
|
if octets[-1].index(".").nil? and address.match(/::/)
|
322
322
|
octets = handle_wildcard_in_address(octets)
|
323
323
|
elsif octets[-1].index(".")
|
324
324
|
# we have a dotted quad IPv4 compatibility address.
|
325
325
|
# create an IPv4 object, get the raw value and stuff it into
|
326
326
|
# the lower two octets.
|
327
|
-
|
327
|
+
|
328
328
|
raw = IP::Address::IPv4.new(octets.pop).pack
|
329
329
|
raw = raw & 0xFFFFFFFF
|
330
330
|
low = raw & 0xFFFF
|
331
331
|
high = (raw >> 16) & 0xFFFF
|
332
332
|
octets = handle_wildcard_in_address(octets)[0..5] + ([high, low].collect { |x| format_octet(x) })
|
333
|
-
else
|
333
|
+
else
|
334
334
|
raise IP::AddressException.new("IPv6 address '#{address}' has less than 8 octets")
|
335
335
|
end
|
336
|
-
|
336
|
+
|
337
337
|
elsif octets.length > 8
|
338
338
|
raise IP::AddressException.new("IPv6 address '#{address}' has more than 8 octets")
|
339
339
|
end
|
340
|
-
|
340
|
+
|
341
341
|
return octets
|
342
342
|
end
|
343
|
-
|
343
|
+
|
344
344
|
|
345
345
|
#
|
346
346
|
# This handles :: addressing in IPv6 and generates a full set of
|
347
347
|
# octets in response.
|
348
|
-
#
|
348
|
+
#
|
349
349
|
# The series of octets handed to this routine are expected to be the
|
350
350
|
# result of splitting the address by ':'.
|
351
351
|
#
|
@@ -353,9 +353,9 @@ class IP::Address::IPv6 < IP::Address
|
|
353
353
|
def handle_wildcard_in_address(octets)
|
354
354
|
lhs = []
|
355
355
|
rhs = []
|
356
|
-
|
356
|
+
|
357
357
|
i = octets.index("") # find ::
|
358
|
-
|
358
|
+
|
359
359
|
# easy out for xxxx:xxxx:: and so on
|
360
360
|
if i.nil?
|
361
361
|
lhs = octets.dup
|
@@ -367,14 +367,14 @@ class IP::Address::IPv6 < IP::Address
|
|
367
367
|
lhs = octets[0..(i-1)]
|
368
368
|
rhs = octets[(i+1)..-1]
|
369
369
|
end
|
370
|
-
|
370
|
+
|
371
371
|
unless rhs.index("").nil?
|
372
372
|
raise IP::AddressException.new("IPv6 address '#{ip_address}' has more than one floating range ('::') specifier")
|
373
373
|
end
|
374
|
-
|
374
|
+
|
375
375
|
missing = (8 - (lhs.length + rhs.length))
|
376
376
|
missing.times { lhs.push("0") }
|
377
|
-
|
377
|
+
|
378
378
|
octets = lhs + rhs
|
379
379
|
|
380
380
|
return octets
|
@@ -386,7 +386,7 @@ class IP::Address::IPv6 < IP::Address
|
|
386
386
|
|
387
387
|
def octets_atoi(octets)
|
388
388
|
new_octets = []
|
389
|
-
|
389
|
+
|
390
390
|
octets.each do |x|
|
391
391
|
if x.length > 4
|
392
392
|
raise IP::AddressException.new("IPv6 address '#{ip_address}' has an octet that is larger than 32 bits")
|
@@ -395,7 +395,7 @@ class IP::Address::IPv6 < IP::Address
|
|
395
395
|
octet = x.hex
|
396
396
|
|
397
397
|
# normalize the octet to 4 places with leading zeroes, uppercase.
|
398
|
-
x = ("0" * (4 - x.length)) + x.upcase
|
398
|
+
x = ("0" * (4 - x.length)) + x.upcase
|
399
399
|
|
400
400
|
unless ("%0.4X" % octet) == x
|
401
401
|
raise IP::AddressException.new("IPv6 address '#{ip_address}' has octets that contain non-hexidecimal data")
|
@@ -403,7 +403,7 @@ class IP::Address::IPv6 < IP::Address
|
|
403
403
|
|
404
404
|
new_octets.push(octet)
|
405
405
|
end
|
406
|
-
|
406
|
+
|
407
407
|
return new_octets
|
408
408
|
|
409
409
|
end
|
data/lib/ip/cidr.rb
CHANGED
@@ -18,7 +18,7 @@ class IP::CIDR
|
|
18
18
|
# integer.
|
19
19
|
#
|
20
20
|
attr_reader :mask
|
21
|
-
|
21
|
+
|
22
22
|
#
|
23
23
|
# Given a string of format X.X.X.X/X, in standard CIDR notation,
|
24
24
|
# this will construct a IP::CIDR object.
|
@@ -27,7 +27,7 @@ class IP::CIDR
|
|
27
27
|
if !cidr.kind_of? String
|
28
28
|
raise IP::AddressException.new("CIDR value is not of type String")
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
@cidr = cidr
|
32
32
|
@ip, @mask = cidr.split(/\//, 2)
|
33
33
|
|
@@ -36,8 +36,8 @@ class IP::CIDR
|
|
36
36
|
if @ip.nil? or @mask.nil?
|
37
37
|
raise IP::AddressException.new("CIDR is not valid - invalid format")
|
38
38
|
end
|
39
|
-
|
40
|
-
if @mask.length == 0 or /[^0-9.]/.match @mask or
|
39
|
+
|
40
|
+
if @mask.length == 0 or /[^0-9.]/.match @mask or
|
41
41
|
(@ip.kind_of? IP::Address::IPv6 and @mask.to_i.to_s != @mask)
|
42
42
|
raise IP::AddressException.new("CIDR RHS is not valid - #{@mask}")
|
43
43
|
end
|
@@ -46,15 +46,15 @@ class IP::CIDR
|
|
46
46
|
# get the short netmask for IPv4 - this will throw an exception if the netmask is malformed.
|
47
47
|
@mask = IP::Address::Util.short_netmask(IP::Address::IPv4.new(@mask))
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
@mask = @mask.to_i
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def netmask
|
54
54
|
warn "IP::CIDR#netmask is deprecated. Please use IP::CIDR#long_netmask instead."
|
55
55
|
return self.long_netmask
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
#
|
59
59
|
# This produces the long netmask (eg. 255.255.255.255) of the CIDR in an
|
60
60
|
# IP::Address object.
|
@@ -65,19 +65,19 @@ class IP::CIDR
|
|
65
65
|
if @ip.kind_of? IP::Address::IPv6
|
66
66
|
raise IP::AddressException.new("IPv6 does not support a long netmask.")
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
return IP::Address::Util.long_netmask_ipv4(@mask)
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
#
|
73
73
|
# This produces the short netmask (eg. 32) of the CIDR in an IP::Address
|
74
74
|
# object.
|
75
75
|
#
|
76
|
-
|
76
|
+
|
77
77
|
def short_netmask
|
78
78
|
return @mask
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
#
|
82
82
|
# This produces a range ala IP::Range, but only for the subnet
|
83
83
|
# defined by the CIDR object.
|
@@ -85,18 +85,18 @@ class IP::CIDR
|
|
85
85
|
def range
|
86
86
|
return IP::Range[self.first_ip, self.last_ip]
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
#
|
90
90
|
# This returns the first ip address of the cidr as an IP::Address object.
|
91
91
|
#
|
92
92
|
def first_ip
|
93
|
-
rawip = @ip.pack
|
94
|
-
|
93
|
+
rawip = @ip.pack
|
94
|
+
|
95
95
|
#
|
96
96
|
# since our actual mask calculation is done with the full 128 bits,
|
97
97
|
# we have to shift calculations that we want in IPv4 to the left to
|
98
98
|
# get proper return values.
|
99
|
-
#
|
99
|
+
#
|
100
100
|
|
101
101
|
if @ip.kind_of? IP::Address::IPv4
|
102
102
|
rawip = rawip << 96
|
@@ -120,13 +120,13 @@ class IP::CIDR
|
|
120
120
|
end
|
121
121
|
|
122
122
|
end
|
123
|
-
|
123
|
+
|
124
124
|
#
|
125
125
|
# This returns the last ip address of the cidr as an IP::Address object.
|
126
126
|
#
|
127
127
|
def last_ip
|
128
128
|
rawip = @ip.pack
|
129
|
-
|
129
|
+
|
130
130
|
# see #first_ip for the reason that we shift this way for IPv4.
|
131
131
|
if @ip.kind_of? IP::Address::IPv4
|
132
132
|
rawip = rawip << 96
|
@@ -149,7 +149,7 @@ class IP::CIDR
|
|
149
149
|
raise IP::AddressException.new("Cannot determine type of IP address")
|
150
150
|
end
|
151
151
|
end
|
152
|
-
|
152
|
+
|
153
153
|
#
|
154
154
|
# This will take another IP::CIDR object as an argument and check to see
|
155
155
|
# if it overlaps with this cidr object. Returns true/false on overlap.
|
@@ -158,13 +158,13 @@ class IP::CIDR
|
|
158
158
|
#
|
159
159
|
def overlaps?(other_cidr)
|
160
160
|
raise TypeError.new("Expected object of type IP::CIDR") unless(other_cidr.kind_of?(IP::CIDR))
|
161
|
-
|
161
|
+
|
162
162
|
myfirst = self.first_ip.pack
|
163
163
|
mylast = self.last_ip.pack
|
164
|
-
|
164
|
+
|
165
165
|
otherfirst = other_cidr.first_ip.pack
|
166
166
|
otherlast = other_cidr.last_ip.pack
|
167
|
-
|
167
|
+
|
168
168
|
return ((myfirst >= otherfirst && myfirst <= otherlast) ||
|
169
169
|
(mylast <= otherlast && mylast >= otherfirst) ||
|
170
170
|
(otherfirst >= myfirst && otherfirst <= mylast)) ? true : false;
|
@@ -185,7 +185,7 @@ class IP::CIDR
|
|
185
185
|
raw = address.pack
|
186
186
|
first = first_ip.pack
|
187
187
|
last = last_ip.pack
|
188
|
-
|
188
|
+
|
189
189
|
return (raw >= first) && (raw <= last)
|
190
190
|
end
|
191
191
|
|
data/lib/ip/range.rb
CHANGED
@@ -14,22 +14,22 @@
|
|
14
14
|
#
|
15
15
|
|
16
16
|
class IP::Range
|
17
|
-
|
17
|
+
|
18
18
|
#
|
19
19
|
# See the documentation for IP::Range for more information on this
|
20
20
|
# method.
|
21
21
|
#
|
22
|
-
|
22
|
+
|
23
23
|
def self.[](addr1, addr2)
|
24
24
|
raw1, raw2 = [nil, nil]
|
25
25
|
tmpip = nil
|
26
|
-
|
26
|
+
|
27
27
|
if addr1.kind_of? String
|
28
28
|
addr1 = IP::Address::Util.string_to_ip(addr1)
|
29
29
|
elsif ! addr1.kind_of? IP::Address
|
30
30
|
raise IP::AddressException.new("IP Address is not type String or IP::Address")
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
if addr2.kind_of? String
|
34
34
|
addr2 = IP::Address::Util.string_to_ip(addr2)
|
35
35
|
elsif ! addr2.kind_of? IP::Address
|
@@ -39,12 +39,12 @@ class IP::Range
|
|
39
39
|
if addr2.class.name != addr1.class.name
|
40
40
|
raise IP::AddressException.new("First and Second IP in range are not of the same type")
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
raw1 = addr1.pack
|
44
44
|
raw2 = addr2.pack
|
45
45
|
|
46
46
|
range = []
|
47
|
-
|
47
|
+
|
48
48
|
# use the class we were given to force certain results, instead
|
49
49
|
# of relying on the fairly inaccurate unpack facility.
|
50
50
|
range = (raw1..raw2).collect { |x| addr1.class.new(x) }
|
data/lib/ip/util.rb
CHANGED
@@ -8,13 +8,13 @@ module IP::Address::Util
|
|
8
8
|
# 'FixNum' type. Can take both IP::Address::IPv4 and
|
9
9
|
# IP::Address::IPv6 objects.
|
10
10
|
#
|
11
|
-
|
11
|
+
|
12
12
|
def pack(ip)
|
13
13
|
return ip.pack
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
module_function :pack
|
17
|
-
|
17
|
+
|
18
18
|
#
|
19
19
|
# This routine takes an array of integers which are intended to be
|
20
20
|
# an IP address, and joins them into a single integer used for easy
|
@@ -23,16 +23,16 @@ module IP::Address::Util
|
|
23
23
|
# IPv4 and IPv6 objects are packed into the same size, a 128-bit
|
24
24
|
# integer. This is done for easier processing within the library.
|
25
25
|
#
|
26
|
-
|
26
|
+
|
27
27
|
def raw_pack(array)
|
28
28
|
ret = 0
|
29
29
|
myip = array.reverse
|
30
30
|
8.times { |x| ret = ret | myip[x] << 16*x }
|
31
31
|
return ret
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
module_function :raw_pack
|
35
|
-
|
35
|
+
|
36
36
|
#
|
37
37
|
# Take an 'Integer' type and return an IP::Address object.
|
38
38
|
#
|
@@ -46,31 +46,31 @@ module IP::Address::Util
|
|
46
46
|
#
|
47
47
|
def unpack(ip)
|
48
48
|
ret = raw_unpack(ip)
|
49
|
-
|
49
|
+
|
50
50
|
# any IPv6 address should meet this criteria.
|
51
51
|
if ret[2..8].any? { |x| x > 0 }
|
52
52
|
return IP::Address::IPv6.new(ip)
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
return IP::Address::IPv4.new(ip)
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
module_function :unpack
|
59
|
-
|
59
|
+
|
60
60
|
#
|
61
61
|
# Take a 'FixNum' and return it's in-place octet
|
62
62
|
# representation. This is mostly a helper method for the unpack
|
63
63
|
# routines.
|
64
64
|
#
|
65
|
-
|
65
|
+
|
66
66
|
def raw_unpack(ip)
|
67
67
|
ret = []
|
68
68
|
8.times { |x| ret.push((ip >> 16*x) & 0xFFFF) }
|
69
69
|
return ret
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
module_function :raw_unpack
|
73
|
-
|
73
|
+
|
74
74
|
#
|
75
75
|
# Returns a short subnet mask - works for all IP::Address objects.
|
76
76
|
#
|
@@ -78,7 +78,7 @@ module IP::Address::Util
|
|
78
78
|
# short_netmask(IP::Address::IPv4.new("255.255.255.255")) => 32
|
79
79
|
# short_netmask(IP::Address::IPv6.new("2001:0DB8:0000:CD30:0000:0000:0000:0000")) => 60
|
80
80
|
#
|
81
|
-
|
81
|
+
|
82
82
|
def short_netmask(ip)
|
83
83
|
#
|
84
84
|
# This method handles 128-bit integers better for both types of
|
@@ -86,7 +86,7 @@ module IP::Address::Util
|
|
86
86
|
#
|
87
87
|
# TODO: there really is probably a better way to do this.
|
88
88
|
#
|
89
|
-
|
89
|
+
|
90
90
|
s = ip.pack.to_s(2)
|
91
91
|
|
92
92
|
pad = 0
|
@@ -102,16 +102,16 @@ module IP::Address::Util
|
|
102
102
|
|
103
103
|
return s.rindex("1") + 1
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
module_function :short_netmask
|
107
|
-
|
107
|
+
|
108
108
|
def long_netmask(short)
|
109
109
|
warn "This function is deprecated, please use IP::Address::Util.long_netmask_ipv4 instead."
|
110
110
|
return long_netmask_ipv4(short)
|
111
111
|
end
|
112
|
-
|
112
|
+
|
113
113
|
module_function :long_netmask
|
114
|
-
|
114
|
+
|
115
115
|
#
|
116
116
|
# Given a CIDR-notation "short" netmask, returns a IP::Address object containing
|
117
117
|
# the equivalent "long" netmask.
|
@@ -120,14 +120,14 @@ module IP::Address::Util
|
|
120
120
|
# long_netmask(32) => IP::Address object of "255.255.255.255"
|
121
121
|
# long_netmask(28) => IP::Address object of "255.255.255.240"
|
122
122
|
#
|
123
|
-
|
123
|
+
|
124
124
|
def long_netmask_ipv4(short)
|
125
125
|
raw = (0xFFFFFFFF << (32 - short)) & 0xFFFFFFFF
|
126
126
|
return IP::Address::Util.unpack(raw)
|
127
127
|
end
|
128
|
-
|
128
|
+
|
129
129
|
module_function :long_netmask_ipv4
|
130
|
-
|
130
|
+
|
131
131
|
#
|
132
132
|
# This takes a string which supposedly contains an IP address, and
|
133
133
|
# tries to figure out if it is a IPv6 or IPv4 address. Returns a
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Erik Hollensbe
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-01-21 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
13
|
description:
|
15
14
|
email: erik@hollensbe.org
|
@@ -17,38 +16,33 @@ executables: []
|
|
17
16
|
extensions: []
|
18
17
|
extra_rdoc_files: []
|
19
18
|
files:
|
20
|
-
- Rakefile
|
21
|
-
- examples/check-included.rb
|
22
|
-
- examples/check-overlap.rb
|
23
|
-
- examples/generate-a-records.rb
|
24
19
|
- lib/ip.rb
|
25
|
-
- test/test_ip.rb
|
26
20
|
- lib/ip/address.rb
|
27
21
|
- lib/ip/cidr.rb
|
28
22
|
- lib/ip/range.rb
|
29
23
|
- lib/ip/util.rb
|
30
24
|
homepage: http://github.com/erikh/ip
|
31
|
-
licenses:
|
25
|
+
licenses:
|
26
|
+
- MIT
|
27
|
+
metadata: {}
|
32
28
|
post_install_message:
|
33
29
|
rdoc_options: []
|
34
30
|
require_paths:
|
35
31
|
- lib
|
36
32
|
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
-
none: false
|
38
33
|
requirements:
|
39
|
-
- -
|
34
|
+
- - '>='
|
40
35
|
- !ruby/object:Gem::Version
|
41
36
|
version: '0'
|
42
37
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
-
none: false
|
44
38
|
requirements:
|
45
|
-
- -
|
39
|
+
- - '>='
|
46
40
|
- !ruby/object:Gem::Version
|
47
41
|
version: '0'
|
48
42
|
requirements: []
|
49
43
|
rubyforge_project: ip-address
|
50
|
-
rubygems_version: 1.
|
44
|
+
rubygems_version: 2.1.10
|
51
45
|
signing_key:
|
52
|
-
specification_version:
|
46
|
+
specification_version: 4
|
53
47
|
summary: Ruby classes to work with IP address, ranges, and netmasks
|
54
48
|
test_files: []
|
data/Rakefile
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Please see the COPYING file in the source distribution for copyright information.
|
3
|
-
#
|
4
|
-
|
5
|
-
begin
|
6
|
-
require 'rubygems'
|
7
|
-
gem 'test-unit'
|
8
|
-
rescue LoadError
|
9
|
-
end
|
10
|
-
|
11
|
-
$:.unshift 'lib'
|
12
|
-
require 'rake/testtask'
|
13
|
-
require 'rake/packagetask'
|
14
|
-
require 'rake/gempackagetask'
|
15
|
-
require 'rake/rdoctask'
|
16
|
-
require 'ip'
|
17
|
-
|
18
|
-
task :default => [ :dist ]
|
19
|
-
|
20
|
-
#
|
21
|
-
# Tests
|
22
|
-
#
|
23
|
-
|
24
|
-
Rake::TestTask.new do |t|
|
25
|
-
t.libs << 'lib'
|
26
|
-
t.test_files = FileList['test/test*.rb']
|
27
|
-
t.verbose = true
|
28
|
-
end
|
29
|
-
|
30
|
-
#
|
31
|
-
# Distribution
|
32
|
-
#
|
33
|
-
|
34
|
-
task :dist => [:test, :repackage, :gem, :rdoc]
|
35
|
-
task :distclean => [:clobber_package, :clobber_rdoc]
|
36
|
-
task :clean => [:distclean]
|
37
|
-
|
38
|
-
#
|
39
|
-
# Documentation
|
40
|
-
#
|
41
|
-
|
42
|
-
Rake::RDocTask.new do |rd|
|
43
|
-
rd.rdoc_dir = "rdoc"
|
44
|
-
rd.main = "IP"
|
45
|
-
rd.rdoc_files.include("./lib/**/*.rb")
|
46
|
-
rd.options = %w(-ap)
|
47
|
-
end
|
48
|
-
|
49
|
-
#
|
50
|
-
# Packaging
|
51
|
-
#
|
52
|
-
|
53
|
-
spec = Gem::Specification.new do |s|
|
54
|
-
s.name = "ip"
|
55
|
-
s.version = IP::VERSION
|
56
|
-
s.author = "Erik Hollensbe"
|
57
|
-
s.email = "erik@hollensbe.org"
|
58
|
-
s.summary = "Ruby classes to work with IP address, ranges, and netmasks"
|
59
|
-
s.has_rdoc = true
|
60
|
-
s.files = Dir['Rakefile'] + Dir['examples/*.rb'] + Dir['lib/*.rb'] + Dir['test/*.rb'] + Dir['lib/ip/*.rb']
|
61
|
-
s.rubyforge_project = 'ip-address'
|
62
|
-
s.homepage = "http://github.com/erikh/ip"
|
63
|
-
end
|
64
|
-
|
65
|
-
Rake::GemPackageTask.new(spec) do |s|
|
66
|
-
end
|
67
|
-
|
68
|
-
Rake::PackageTask.new(spec.name, spec.version) do |p|
|
69
|
-
p.need_tar_gz = true
|
70
|
-
p.need_zip = true
|
71
|
-
p.package_files.include("./setup.rb")
|
72
|
-
p.package_files.include("./Rakefile")
|
73
|
-
p.package_files.include("./examples/**/*.rb")
|
74
|
-
p.package_files.include("./lib/**/*.rb")
|
75
|
-
p.package_files.include("./test/**/*")
|
76
|
-
end
|
data/examples/check-included.rb
DELETED
@@ -1,27 +0,0 @@
|
|
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
|
-
|
data/examples/check-overlap.rb
DELETED
@@ -1,26 +0,0 @@
|
|
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
|
@@ -1,26 +0,0 @@
|
|
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/test/test_ip.rb
DELETED
@@ -1,313 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'rubygems'
|
3
|
-
gem 'test-unit'
|
4
|
-
rescue LoadError => e
|
5
|
-
end
|
6
|
-
|
7
|
-
require 'test/unit'
|
8
|
-
load 'lib/ip.rb'
|
9
|
-
|
10
|
-
class CIDRTest < Test::Unit::TestCase
|
11
|
-
|
12
|
-
def name
|
13
|
-
return "IP::CIDR tests"
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_init_generic
|
17
|
-
assert_raise(IP::AddressException) { IP::CIDR.new(Hash.new) }
|
18
|
-
assert_raise(IP::AddressException) { IP::CIDR.new("foomatic_wootmaster/32") }
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_init_ipv6
|
22
|
-
assert_raise(IP::AddressException) { IP::CIDR.new("F00F:DEAD:BEEF::") }
|
23
|
-
assert_raise(IP::AddressException) { IP::CIDR.new("F00F:DEAD:BEEF::/") }
|
24
|
-
assert_raise(IP::AddressException) { IP::CIDR.new("F00F:DEAD:BEEF::/asdf/32") }
|
25
|
-
assert_raise(IP::AddressException) { IP::CIDR.new("F00F:DEAD:BEEF::/foomatic_wootmaster") }
|
26
|
-
assert_raise(IP::AddressException) { IP::CIDR.new("F00F:DEAD:BEEF::/255.255.255.255") }
|
27
|
-
|
28
|
-
cidr = nil
|
29
|
-
assert_nothing_raised() { cidr = IP::CIDR.new("F00F:DEAD:BEEF::0001/128") }
|
30
|
-
|
31
|
-
# this sort of indirectly tests the ipv6 address manipulation.
|
32
|
-
assert_equal("F00F:DEAD:BEEF::1", cidr.ip.short_address, "ipv6 object constructed clean")
|
33
|
-
assert_equal(128, cidr.mask, "mask is set properly")
|
34
|
-
assert_equal("F00F:DEAD:BEEF::0001/128", cidr.cidr, "original CIDR preserved")
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_init_ipv4
|
38
|
-
assert_raise(IP::AddressException) { IP::CIDR.new("10.0.0.1") }
|
39
|
-
assert_raise(IP::AddressException) { IP::CIDR.new("10.0.0.1/") }
|
40
|
-
assert_raise(IP::AddressException) { IP::CIDR.new("10.0.0.1/asdf/32") }
|
41
|
-
assert_raise(IP::AddressException) { IP::CIDR.new("10.0.0.1/foomatic_wootmaster") }
|
42
|
-
assert_raise(IP::AddressException) { IP::CIDR.new("10.0.0.1/255") }
|
43
|
-
|
44
|
-
cidr = nil
|
45
|
-
|
46
|
-
assert_nothing_raised() { cidr = IP::CIDR.new("10.0.0.1/32") }
|
47
|
-
|
48
|
-
assert_equal("10.0.0.1", cidr.ip.ip_address, "ipv4 data integrity test #1")
|
49
|
-
assert_equal(32, cidr.mask, "ipv4 data integrity test #2")
|
50
|
-
assert_equal("10.0.0.1/32", cidr.cidr, "ipv4 data integrity test #3")
|
51
|
-
|
52
|
-
assert_nothing_raised() { cidr = IP::CIDR.new("10.0.0.1/255.255.255.255") }
|
53
|
-
|
54
|
-
assert_equal("10.0.0.1", cidr.ip.ip_address, "ipv4 data integrity test #4")
|
55
|
-
assert_equal(32, cidr.mask, "ipv4 data integrity test #5")
|
56
|
-
assert_equal("10.0.0.1/255.255.255.255", cidr.cidr, "ipv4 data integrity test #6")
|
57
|
-
end
|
58
|
-
|
59
|
-
def test_netmasks
|
60
|
-
cidr = nil
|
61
|
-
assert_nothing_raised() { cidr = IP::CIDR.new("10.0.0.1/32") }
|
62
|
-
assert_equal(32, cidr.short_netmask, "ipv4 netmask test #1")
|
63
|
-
assert_equal("255.255.255.255", cidr.long_netmask.ip_address, "ipv4 netmask test #2")
|
64
|
-
|
65
|
-
assert_nothing_raised() { cidr = IP::CIDR.new("10.0.0.1/255.255.255.248") }
|
66
|
-
assert_equal(29, cidr.short_netmask, "ipv4 netmask test #3")
|
67
|
-
assert_equal("255.255.255.248", cidr.long_netmask.ip_address, "ipv4 netmask test #4")
|
68
|
-
|
69
|
-
assert_nothing_raised() { cidr = IP::CIDR.new("F00F:DEAD::/16") }
|
70
|
-
assert_equal(16, cidr.short_netmask, "ipv6 has proper short netmask")
|
71
|
-
assert_raise(IP::AddressException) { cidr.long_netmask }
|
72
|
-
end
|
73
|
-
|
74
|
-
def test_first_last
|
75
|
-
cidr = nil
|
76
|
-
assert_nothing_raised() { cidr = IP::CIDR.new("10.0.0.2/24") }
|
77
|
-
assert_equal("10.0.0.0", cidr.first_ip.ip_address, "ipv4 first/last test #1")
|
78
|
-
assert_equal("10.0.0.255", cidr.last_ip.ip_address, "ipv4 first/last test #2")
|
79
|
-
end
|
80
|
-
|
81
|
-
def test_range
|
82
|
-
cidr = nil
|
83
|
-
assert_nothing_raised() { cidr = IP::CIDR.new("10.0.0.2/24") }
|
84
|
-
assert_equal(1, cidr.range.find_all { |x| x.ip_address == "10.0.0.1" }.length, "ipv4 range test #1")
|
85
|
-
assert_equal(0, cidr.range.find_all { |x| x.ip_address == "10.0.1.0" }.length, "ipv4 range test #2")
|
86
|
-
|
87
|
-
assert_nothing_raised() { cidr = IP::CIDR.new("::0001/120") }
|
88
|
-
assert_equal(1, cidr.range.find_all { |x| x.ip_address == "0:0:0:0:0:0:0:00FF" }.length, "ipv6 range test (included)")
|
89
|
-
assert_equal(0, cidr.range.find_all { |x| x.ip_address ==" 0:0:0:0:0:0:0:0F00" }.length, "ipv6 range test (not included)")
|
90
|
-
end
|
91
|
-
|
92
|
-
def test_overlaps
|
93
|
-
cidr, cidr2 = [nil, nil]
|
94
|
-
|
95
|
-
assert_nothing_raised() do
|
96
|
-
cidr = IP::CIDR.new("10.0.0.2/24")
|
97
|
-
cidr2 = IP::CIDR.new("10.0.0.1/29")
|
98
|
-
end
|
99
|
-
|
100
|
-
assert(cidr.overlaps?(cidr2), "ipv4 overlaps test #1")
|
101
|
-
|
102
|
-
assert_nothing_raised() { cidr2 = IP::CIDR.new("10.0.0.1/16") }
|
103
|
-
|
104
|
-
assert(cidr2.overlaps?(cidr), "ipv4 overlaps test #2")
|
105
|
-
assert(cidr.overlaps?(cidr2), "ipv4 overlaps test #3")
|
106
|
-
|
107
|
-
assert_nothing_raised() do
|
108
|
-
cidr = IP::CIDR.new("F00F:DEAD::/16")
|
109
|
-
cidr2 = IP::CIDR.new("F00F:BEEF::/16")
|
110
|
-
end
|
111
|
-
|
112
|
-
assert(cidr.overlaps?(cidr2), "ipv6 #overlaps? reports correctly #1")
|
113
|
-
assert(cidr2.overlaps?(cidr), "ipv6 #overlaps? reports correctly #2")
|
114
|
-
end
|
115
|
-
|
116
|
-
def test_includes
|
117
|
-
cidr, ip = [nil, nil]
|
118
|
-
assert_nothing_raised() do
|
119
|
-
cidr = IP::CIDR.new("10.0.0.2/24")
|
120
|
-
ip = IP::Address::IPv4.new("10.0.0.1")
|
121
|
-
end
|
122
|
-
|
123
|
-
assert(cidr.includes?(ip), "ipv4 #includes? reports correctly (included)")
|
124
|
-
|
125
|
-
assert_nothing_raised() { ip = IP::Address::IPv4.new("10.0.1.0") }
|
126
|
-
|
127
|
-
assert(!cidr.includes?(ip), "ipv4 #includes? reports correctly (not included)")
|
128
|
-
|
129
|
-
assert_nothing_raised() do
|
130
|
-
cidr = IP::CIDR.new("FF00::/16")
|
131
|
-
ip = IP::Address::IPv6.new("FF00::DEAD")
|
132
|
-
end
|
133
|
-
assert(cidr.includes?(ip), "ipv6 #includes? reports correctly (included)")
|
134
|
-
|
135
|
-
assert_nothing_raised() { ip = IP::Address::IPv6.new("F000::DEAD") }
|
136
|
-
|
137
|
-
assert(!cidr.includes?(ip), "ipv6 #includes? reports correctly (not included)")
|
138
|
-
end
|
139
|
-
|
140
|
-
end
|
141
|
-
|
142
|
-
class RangeTest < Test::Unit::TestCase
|
143
|
-
def name
|
144
|
-
return "IP::Range tests"
|
145
|
-
end
|
146
|
-
|
147
|
-
def test_range_generic
|
148
|
-
assert_raise(IP::AddressException) { IP::Range[Hash.new, ""] }
|
149
|
-
assert_raise(IP::AddressException) { IP::Range["", Hash.new] }
|
150
|
-
assert_raise(IP::AddressException) { IP::Range[IP::Address::IPv6.new("F00F::"), IP::Address::IPv4.new("10.0.0.1")] }
|
151
|
-
assert_raise(IP::AddressException) { IP::Range[IP::Address::IPv4.new("10.0.0.1"), IP::Address::IPv6.new("F00F::")] }
|
152
|
-
end
|
153
|
-
|
154
|
-
def test_range_ipv6
|
155
|
-
assert_nothing_raised() do
|
156
|
-
IP::Range["::0001", "::00F0"]
|
157
|
-
IP::Range[IP::Address::IPv6.new("::0001"), IP::Address::IPv6.new("::00F0")]
|
158
|
-
end
|
159
|
-
|
160
|
-
range = nil
|
161
|
-
|
162
|
-
assert_nothing_raised() { range = IP::Range["::0001", "::0010"] }
|
163
|
-
|
164
|
-
assert_equal(1, range.find_all { |x| x.short_address == "::1" }.length, "ipv6 range check #1")
|
165
|
-
assert_equal(1, range.find_all { |x| x.short_address == "::0010" }.length, "ipv6 range check #2")
|
166
|
-
assert_equal(1, range.find_all { |x| x.short_address == "::000A" }.length, "ipv6 range check #3")
|
167
|
-
assert_equal(0, range.find_all { |x| x.short_address == "::0011" }.length, "ipv6 range check #4")
|
168
|
-
end
|
169
|
-
|
170
|
-
def test_range_ipv4
|
171
|
-
assert_nothing_raised() do
|
172
|
-
IP::Range["10.0.0.1", "10.0.0.2"]
|
173
|
-
IP::Range[IP::Address::IPv4.new("10.0.0.1"), IP::Address::IPv4.new("10.0.0.2")]
|
174
|
-
end
|
175
|
-
|
176
|
-
range = nil
|
177
|
-
assert_nothing_raised() { range = IP::Range["10.0.0.1", "10.0.0.10"] }
|
178
|
-
|
179
|
-
assert_equal(1, range.find_all { |x| x.ip_address == "10.0.0.1" }.length, "ipv4 range check #1")
|
180
|
-
assert_equal(1, range.find_all { |x| x.ip_address == "10.0.0.10" }.length, "ipv4 range check #2")
|
181
|
-
assert_equal(1, range.find_all { |x| x.ip_address == "10.0.0.7" }.length, "ipv4 range check #3")
|
182
|
-
assert_equal(0, range.find_all { |x| x.ip_address == "10.0.0.11" }.length, "ipv4 range check #4")
|
183
|
-
end
|
184
|
-
|
185
|
-
end
|
186
|
-
|
187
|
-
class IPv6AddressTest < Test::Unit::TestCase
|
188
|
-
def name
|
189
|
-
return "IP::Address::IPv6 tests"
|
190
|
-
end
|
191
|
-
|
192
|
-
def test_init
|
193
|
-
assert_nothing_raised() do
|
194
|
-
IP::Address::IPv6.new("0000:0000:0000:0000:0000:0000:0000:0001")
|
195
|
-
IP::Address::IPv6.new("::0001")
|
196
|
-
IP::Address::IPv6.new("FF00::")
|
197
|
-
IP::Address::IPv6.new("FF00::0001")
|
198
|
-
IP::Address::IPv6.new("FF00:BEEF::0001")
|
199
|
-
IP::Address::IPv6.new("FF00::BEEF:0001")
|
200
|
-
IP::Address::IPv6.new("::1.2.3.4")
|
201
|
-
IP::Address::IPv6.new("FFFF::1.2.3.4")
|
202
|
-
IP::Address::IPv6.new("FFFF:0000:0000:0000:0000:0000:1.2.3.4")
|
203
|
-
end
|
204
|
-
|
205
|
-
# now, the tests that should fail
|
206
|
-
|
207
|
-
assert_raise(IP::AddressException) { IP::Address::IPv6.new("FF00:BEEF:") }
|
208
|
-
assert_raise(IP::AddressException) { IP::Address::IPv6.new("FF00::BEEF::") }
|
209
|
-
assert_raise(IP::AddressException) { IP::Address::IPv6.new("FF00::BEEF::DEAD") }
|
210
|
-
assert_raise(IP::AddressException) { IP::Address::IPv6.new("HF00::0001") }
|
211
|
-
assert_raise(IP::AddressException) { IP::Address::IPv6.new("1.2.3.4::0001") }
|
212
|
-
end
|
213
|
-
|
214
|
-
def test_accessors
|
215
|
-
ip = nil
|
216
|
-
assert_nothing_raised() { ip = IP::Address::IPv6.new("F00F::DEAD:BEEF") }
|
217
|
-
|
218
|
-
assert_equal(ip[0], ip.octet(0), "ip[0] eq ip.octet(0)")
|
219
|
-
assert_equal(61455, ip[0], "ip[0] is correct")
|
220
|
-
assert_equal("F00F", ip.octet_as_hex(0), "octet converts to hex properly")
|
221
|
-
assert_equal("F00F::DEAD:BEEF", ip.ip_address, '#ip_address preserves original address')
|
222
|
-
end
|
223
|
-
|
224
|
-
def test_address
|
225
|
-
ip = nil
|
226
|
-
assert_nothing_raised() { ip = IP::Address::IPv6.new("F00F::DEAD:BEEF") }
|
227
|
-
assert_equal("F00F::DEAD:BEEF", ip.short_address, 'wildcard left - #short_address returns a compressed version')
|
228
|
-
assert_equal("F00F:0:0:0:0:0:DEAD:BEEF", ip.long_address, 'wildcard left - #long_address returns the right thing')
|
229
|
-
|
230
|
-
assert_nothing_raised() { ip = IP::Address::IPv6.new("F00F:DEAD::BEEF") }
|
231
|
-
assert_equal("F00F:DEAD::BEEF", ip.short_address, 'wildcard right - #short_address returns a compressed version')
|
232
|
-
assert_equal("F00F:DEAD:0:0:0:0:0:BEEF", ip.long_address, 'wildcard right - #long_address returns the right thing')
|
233
|
-
|
234
|
-
assert_nothing_raised() { ip = IP::Address::IPv6.new("F00F:DEAD:0:0:0:0:0:BEEF") }
|
235
|
-
assert_equal("F00F:DEAD::BEEF", ip.short_address, 'no wildcard - #short_address returns a compressed version')
|
236
|
-
assert_equal("F00F:DEAD:0:0:0:0:0:BEEF", ip.long_address, 'no wildcard - #long_address returns the right thing')
|
237
|
-
|
238
|
-
assert_nothing_raised() { ip = IP::Address::IPv6.new("F00F::DEAD:BEEF:0:0") }
|
239
|
-
assert_equal("F00F:0:0:0:DEAD:BEEF::", ip.short_address, '#short_address returns a compressed version with wildcard @ right')
|
240
|
-
end
|
241
|
-
|
242
|
-
def test_equal
|
243
|
-
assert_equal(IP::Address::IPv6.new("F00F::DEAD:BEEF"),IP::Address::IPv6.new("F00F::DEAD:BEEF"))
|
244
|
-
assert_equal(IP::Address::IPv6.new("F00F::DEAD:BEEF"), "F00F::DEAD:BEEF")
|
245
|
-
assert_equal(IP::Address::IPv6.new("F00F::DEAD:BEEF"), "F00F:0:0:0:0:0:DEAD:BEEF")
|
246
|
-
assert_equal(IP::Address::IPv6.new("F00F::DEAD:BEEF"), 319092603441257831911341651915956928239)
|
247
|
-
assert !(IP::Address::IPv6.new("F00D::DEAD:BEEF") == IP::Address::IPv6.new("F00F::DEAD:BEEF"))
|
248
|
-
assert !(IP::Address::IPv6.new("F00D::DEAD:BEEF") == :someting_else)
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
|
253
|
-
class IPv4AddressTest < Test::Unit::TestCase
|
254
|
-
def name
|
255
|
-
return "IP::Address::IPv4 tests"
|
256
|
-
end
|
257
|
-
|
258
|
-
def test_init
|
259
|
-
assert_raise(IP::AddressException) { IP::Address::IPv4.new(Hash.new) }
|
260
|
-
assert_raise(IP::AddressException) { IP::Address::IPv4.new("asdf") }
|
261
|
-
assert_raise(IP::AddressException) { IP::Address::IPv4.new("0.0.0") }
|
262
|
-
assert_raise(IP::AddressException) { IP::Address::IPv4.new("256.255.255.255") }
|
263
|
-
assert_raise(IP::AddressException) { IP::Address::IPv4.new("255.255.255.255aaaa") }
|
264
|
-
assert_raise(IP::AddressException) { IP::Address::IPv4.new("255.255.255.") }
|
265
|
-
end
|
266
|
-
|
267
|
-
def test_accessor
|
268
|
-
ip = nil
|
269
|
-
assert_nothing_raised() { ip = IP::Address::IPv4.new("10.1.2.3") }
|
270
|
-
assert_equal("10.1.2.3", ip.ip_address, "accessor test #1")
|
271
|
-
assert_equal(10, ip.octets[0], "accessor test #2")
|
272
|
-
assert_equal(3, ip.octets[3], "accessor test #3")
|
273
|
-
assert_equal(nil, ip.octets[4], "accessor test #4")
|
274
|
-
|
275
|
-
assert_equal(ip.octet(1), ip[1], "accessor test #5")
|
276
|
-
assert_equal(1, ip[1], "accessor test #5")
|
277
|
-
|
278
|
-
assert_raise(IP::BoundaryException) { ip[4] }
|
279
|
-
end
|
280
|
-
|
281
|
-
end
|
282
|
-
|
283
|
-
class UtilTest < Test::Unit::TestCase
|
284
|
-
def name
|
285
|
-
return "IP::Address::Util tests"
|
286
|
-
end
|
287
|
-
|
288
|
-
def test_pack_unpack
|
289
|
-
address = "10.0.0.1"
|
290
|
-
assert_equal("10.0.0.1", IP::Address::Util.unpack(IP::Address::Util.pack(IP::Address::IPv4.new(address))).ip_address, "pack/unpack test")
|
291
|
-
end
|
292
|
-
|
293
|
-
def test_short_netmask
|
294
|
-
ip = nil
|
295
|
-
assert_nothing_raised() { ip = IP::Address::IPv4.new("255.255.255.255") }
|
296
|
-
assert_equal(32, IP::Address::Util.short_netmask(ip), "Short Netmask Test #1")
|
297
|
-
assert_nothing_raised() { ip = IP::Address::IPv4.new("255.255.255.248") }
|
298
|
-
assert_equal(29, IP::Address::Util.short_netmask(ip), "Short Netmask Test #2")
|
299
|
-
end
|
300
|
-
|
301
|
-
def test_long_netmask
|
302
|
-
assert_equal("255.255.255.255", IP::Address::Util.long_netmask_ipv4(32).ip_address, "Long Netmask Test #1")
|
303
|
-
assert_equal("255.255.255.248", IP::Address::Util.long_netmask_ipv4(29).ip_address, "Long Netmask Test #2")
|
304
|
-
end
|
305
|
-
|
306
|
-
def test_equal
|
307
|
-
assert_equal(IP::Address::IPv4.new("255.255.255.255"),IP::Address::IPv4.new("255.255.255.255"))
|
308
|
-
assert_equal(IP::Address::IPv4.new("255.255.255.255"), "255.255.255.255")
|
309
|
-
assert_equal(IP::Address::IPv4.new("255.255.255.255"), 4294967295) # 255.255.255.255
|
310
|
-
assert !(IP::Address::IPv4.new("255.255.255.255") == IP::Address::IPv4.new("255.255.255.254"))
|
311
|
-
assert !(IP::Address::IPv4.new("255.255.255.255") == :something_else)
|
312
|
-
end
|
313
|
-
end
|