ip 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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:: BSD
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
@@ -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
@@ -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
 
@@ -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) }
@@ -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.0
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: 2012-04-11 00:00:00.000000000 Z
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.8.15
44
+ rubygems_version: 2.1.10
51
45
  signing_key:
52
- specification_version: 3
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
@@ -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
-
@@ -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
@@ -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