ipaddr 1.2.5 → 1.2.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/ipaddr.rb +92 -34
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 566f76e26928f5a6014a11f985f08d1299dd06e7cb273cbc90b2553182b90006
|
4
|
+
data.tar.gz: f966e0490212bdb9194d05e6ee1d7e8df85ce622ed3692c46b2539c648e0315f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02e29f8adc3da01f5db2c02101dab218015ab78c9b628060945bbbf328e10391962afd254c0ce5cb9d6a86d68486120f9298673ca9ff133325fd7df700804af6
|
7
|
+
data.tar.gz: b14fd4218bfdb839dee0fa22a334a217a39a8493ea9e7977684a0418819a337386727d0c47f67868848d018e7f7659f52dabeef686e20ad948a462683915d69c
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
IPAddr provides a set of methods to manipulate an IP address. Both
|
4
4
|
IPv4 and IPv6 are supported.
|
5
5
|
|
6
|
-
[![
|
6
|
+
[![build](https://github.com/ruby/ipaddr/actions/workflows/test.yml/badge.svg)](https://github.com/ruby/ipaddr/actions/workflows/test.yml)
|
7
7
|
|
8
8
|
## Installation
|
9
9
|
|
data/lib/ipaddr.rb
CHANGED
@@ -40,7 +40,7 @@ require 'socket'
|
|
40
40
|
# p ipaddr3 #=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0>
|
41
41
|
|
42
42
|
class IPAddr
|
43
|
-
VERSION = "1.2.
|
43
|
+
VERSION = "1.2.7"
|
44
44
|
|
45
45
|
# 32 bit mask for IPv4
|
46
46
|
IN4MASK = 0xffffffff
|
@@ -52,7 +52,7 @@ class IPAddr
|
|
52
52
|
# Regexp _internally_ used for parsing IPv4 address.
|
53
53
|
RE_IPV4ADDRLIKE = %r{
|
54
54
|
\A
|
55
|
-
|
55
|
+
\d+ \. \d+ \. \d+ \. \d+
|
56
56
|
\z
|
57
57
|
}x
|
58
58
|
|
@@ -110,8 +110,13 @@ class IPAddr
|
|
110
110
|
|
111
111
|
# Convert a network byte ordered string form of an IP address into
|
112
112
|
# human readable form.
|
113
|
+
# It expects the string to be encoded in Encoding::ASCII_8BIT (BINARY).
|
113
114
|
def self.ntop(addr)
|
114
|
-
|
115
|
+
if addr.is_a?(String) && addr.encoding != Encoding::BINARY
|
116
|
+
raise InvalidAddressError, "invalid encoding (given #{addr.encoding}, expected BINARY)"
|
117
|
+
end
|
118
|
+
|
119
|
+
case addr.bytesize
|
115
120
|
when 4
|
116
121
|
addr.unpack('C4').join('.')
|
117
122
|
when 16
|
@@ -176,9 +181,7 @@ class IPAddr
|
|
176
181
|
def include?(other)
|
177
182
|
other = coerce_other(other)
|
178
183
|
return false unless other.family == family
|
179
|
-
|
180
|
-
other = other.to_range
|
181
|
-
range.begin <= other.begin && range.end >= other.end
|
184
|
+
begin_addr <= other.begin_addr && end_addr >= other.end_addr
|
182
185
|
end
|
183
186
|
alias === include?
|
184
187
|
|
@@ -224,6 +227,28 @@ class IPAddr
|
|
224
227
|
return str
|
225
228
|
end
|
226
229
|
|
230
|
+
# Returns a string containing the IP address representation with prefix.
|
231
|
+
def as_json(*)
|
232
|
+
if ipv4? && prefix == 32
|
233
|
+
to_s
|
234
|
+
elsif ipv6? && prefix == 128
|
235
|
+
to_s
|
236
|
+
else
|
237
|
+
cidr
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Returns a json string containing the IP address representation.
|
242
|
+
def to_json(*a)
|
243
|
+
%Q{"#{as_json(*a)}"}
|
244
|
+
end
|
245
|
+
|
246
|
+
# Returns a string containing the IP address representation in
|
247
|
+
# cidr notation
|
248
|
+
def cidr
|
249
|
+
"#{to_s}/#{prefix}"
|
250
|
+
end
|
251
|
+
|
227
252
|
# Returns a network byte ordered string form of the IP address.
|
228
253
|
def hton
|
229
254
|
case @family
|
@@ -249,12 +274,17 @@ class IPAddr
|
|
249
274
|
end
|
250
275
|
|
251
276
|
# Returns true if the ipaddr is a loopback address.
|
277
|
+
# Loopback IPv4 addresses in the IPv4-mapped IPv6
|
278
|
+
# address range are also considered as loopback addresses.
|
252
279
|
def loopback?
|
253
280
|
case @family
|
254
281
|
when Socket::AF_INET
|
255
|
-
@addr & 0xff000000 == 0x7f000000
|
282
|
+
@addr & 0xff000000 == 0x7f000000 # 127.0.0.1/8
|
256
283
|
when Socket::AF_INET6
|
257
|
-
@addr == 1
|
284
|
+
@addr == 1 || # ::1
|
285
|
+
(@addr & 0xffff_0000_0000 == 0xffff_0000_0000 && (
|
286
|
+
@addr & 0xff000000 == 0x7f000000 # ::ffff:127.0.0.1/8
|
287
|
+
))
|
258
288
|
else
|
259
289
|
raise AddressFamilyError, "unsupported address family"
|
260
290
|
end
|
@@ -263,7 +293,8 @@ class IPAddr
|
|
263
293
|
# Returns true if the ipaddr is a private address. IPv4 addresses
|
264
294
|
# in 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16 as defined in RFC
|
265
295
|
# 1918 and IPv6 Unique Local Addresses in fc00::/7 as defined in RFC
|
266
|
-
# 4193 are considered private.
|
296
|
+
# 4193 are considered private. Private IPv4 addresses in the
|
297
|
+
# IPv4-mapped IPv6 address range are also considered private.
|
267
298
|
def private?
|
268
299
|
case @family
|
269
300
|
when Socket::AF_INET
|
@@ -271,22 +302,31 @@ class IPAddr
|
|
271
302
|
@addr & 0xfff00000 == 0xac100000 || # 172.16.0.0/12
|
272
303
|
@addr & 0xffff0000 == 0xc0a80000 # 192.168.0.0/16
|
273
304
|
when Socket::AF_INET6
|
274
|
-
@addr & 0xfe00_0000_0000_0000_0000_0000_0000_0000 == 0xfc00_0000_0000_0000_0000_0000_0000_0000
|
305
|
+
@addr & 0xfe00_0000_0000_0000_0000_0000_0000_0000 == 0xfc00_0000_0000_0000_0000_0000_0000_0000 ||
|
306
|
+
(@addr & 0xffff_0000_0000 == 0xffff_0000_0000 && (
|
307
|
+
@addr & 0xff000000 == 0x0a000000 || # ::ffff:10.0.0.0/8
|
308
|
+
@addr & 0xfff00000 == 0xac100000 || # ::ffff::172.16.0.0/12
|
309
|
+
@addr & 0xffff0000 == 0xc0a80000 # ::ffff::192.168.0.0/16
|
310
|
+
))
|
275
311
|
else
|
276
312
|
raise AddressFamilyError, "unsupported address family"
|
277
313
|
end
|
278
314
|
end
|
279
315
|
|
280
316
|
# Returns true if the ipaddr is a link-local address. IPv4
|
281
|
-
# addresses in 169.254.0.0/16 reserved by RFC 3927 and
|
317
|
+
# addresses in 169.254.0.0/16 reserved by RFC 3927 and link-local
|
282
318
|
# IPv6 Unicast Addresses in fe80::/10 reserved by RFC 4291 are
|
283
|
-
# considered link-local.
|
319
|
+
# considered link-local. Link-local IPv4 addresses in the
|
320
|
+
# IPv4-mapped IPv6 address range are also considered link-local.
|
284
321
|
def link_local?
|
285
322
|
case @family
|
286
323
|
when Socket::AF_INET
|
287
324
|
@addr & 0xffff0000 == 0xa9fe0000 # 169.254.0.0/16
|
288
325
|
when Socket::AF_INET6
|
289
|
-
@addr & 0xffc0_0000_0000_0000_0000_0000_0000_0000 == 0xfe80_0000_0000_0000_0000_0000_0000_0000
|
326
|
+
@addr & 0xffc0_0000_0000_0000_0000_0000_0000_0000 == 0xfe80_0000_0000_0000_0000_0000_0000_0000 || # fe80::/10
|
327
|
+
(@addr & 0xffff_0000_0000 == 0xffff_0000_0000 && (
|
328
|
+
@addr & 0xffff0000 == 0xa9fe0000 # ::ffff:169.254.0.0/16
|
329
|
+
))
|
290
330
|
else
|
291
331
|
raise AddressFamilyError, "unsupported address family"
|
292
332
|
end
|
@@ -400,17 +440,6 @@ class IPAddr
|
|
400
440
|
|
401
441
|
# Creates a Range object for the network address.
|
402
442
|
def to_range
|
403
|
-
begin_addr = (@addr & @mask_addr)
|
404
|
-
|
405
|
-
case @family
|
406
|
-
when Socket::AF_INET
|
407
|
-
end_addr = (@addr | (IN4MASK ^ @mask_addr))
|
408
|
-
when Socket::AF_INET6
|
409
|
-
end_addr = (@addr | (IN6MASK ^ @mask_addr))
|
410
|
-
else
|
411
|
-
raise AddressFamilyError, "unsupported address family"
|
412
|
-
end
|
413
|
-
|
414
443
|
self.class.new(begin_addr, @family)..self.class.new(end_addr, @family)
|
415
444
|
end
|
416
445
|
|
@@ -439,7 +468,7 @@ class IPAddr
|
|
439
468
|
when Integer
|
440
469
|
mask!(prefix)
|
441
470
|
else
|
442
|
-
raise InvalidPrefixError, "prefix must be an integer
|
471
|
+
raise InvalidPrefixError, "prefix must be an integer"
|
443
472
|
end
|
444
473
|
end
|
445
474
|
|
@@ -464,6 +493,20 @@ class IPAddr
|
|
464
493
|
_to_string(@mask_addr)
|
465
494
|
end
|
466
495
|
|
496
|
+
# Returns the wildcard mask in string format e.g. 0.0.255.255
|
497
|
+
def wildcard_mask
|
498
|
+
case @family
|
499
|
+
when Socket::AF_INET
|
500
|
+
mask = IN4MASK ^ @mask_addr
|
501
|
+
when Socket::AF_INET6
|
502
|
+
mask = IN6MASK ^ @mask_addr
|
503
|
+
else
|
504
|
+
raise AddressFamilyError, "unsupported address family"
|
505
|
+
end
|
506
|
+
|
507
|
+
_to_string(mask)
|
508
|
+
end
|
509
|
+
|
467
510
|
# Returns the IPv6 zone identifier, if present.
|
468
511
|
# Raises InvalidAddressError if not an IPv6 address.
|
469
512
|
def zone_id
|
@@ -491,6 +534,21 @@ class IPAddr
|
|
491
534
|
|
492
535
|
protected
|
493
536
|
|
537
|
+
def begin_addr
|
538
|
+
@addr & @mask_addr
|
539
|
+
end
|
540
|
+
|
541
|
+
def end_addr
|
542
|
+
case @family
|
543
|
+
when Socket::AF_INET
|
544
|
+
@addr | (IN4MASK ^ @mask_addr)
|
545
|
+
when Socket::AF_INET6
|
546
|
+
@addr | (IN6MASK ^ @mask_addr)
|
547
|
+
else
|
548
|
+
raise AddressFamilyError, "unsupported address family"
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
494
552
|
# Set +@addr+, the internal stored ip address, to given +addr+. The
|
495
553
|
# parameter +addr+ is validated using the first +family+ member,
|
496
554
|
# which is +Socket::AF_INET+ or +Socket::AF_INET6+.
|
@@ -498,11 +556,11 @@ class IPAddr
|
|
498
556
|
case family[0] ? family[0] : @family
|
499
557
|
when Socket::AF_INET
|
500
558
|
if addr < 0 || addr > IN4MASK
|
501
|
-
raise InvalidAddressError, "invalid address: #{
|
559
|
+
raise InvalidAddressError, "invalid address: #{addr}"
|
502
560
|
end
|
503
561
|
when Socket::AF_INET6
|
504
562
|
if addr < 0 || addr > IN6MASK
|
505
|
-
raise InvalidAddressError, "invalid address: #{
|
563
|
+
raise InvalidAddressError, "invalid address: #{addr}"
|
506
564
|
end
|
507
565
|
else
|
508
566
|
raise AddressFamilyError, "unsupported address family"
|
@@ -529,12 +587,12 @@ class IPAddr
|
|
529
587
|
else
|
530
588
|
m = IPAddr.new(mask)
|
531
589
|
if m.family != @family
|
532
|
-
raise InvalidPrefixError, "address family is not same
|
590
|
+
raise InvalidPrefixError, "address family is not same"
|
533
591
|
end
|
534
592
|
@mask_addr = m.to_i
|
535
593
|
n = @mask_addr ^ m.instance_variable_get(:@mask_addr)
|
536
594
|
unless ((n + 1) & n).zero?
|
537
|
-
raise InvalidPrefixError, "invalid mask #{mask}
|
595
|
+
raise InvalidPrefixError, "invalid mask #{mask}"
|
538
596
|
end
|
539
597
|
@addr &= @mask_addr
|
540
598
|
return self
|
@@ -545,13 +603,13 @@ class IPAddr
|
|
545
603
|
case @family
|
546
604
|
when Socket::AF_INET
|
547
605
|
if prefixlen < 0 || prefixlen > 32
|
548
|
-
raise InvalidPrefixError, "invalid length
|
606
|
+
raise InvalidPrefixError, "invalid length"
|
549
607
|
end
|
550
608
|
masklen = 32 - prefixlen
|
551
609
|
@mask_addr = ((IN4MASK >> masklen) << masklen)
|
552
610
|
when Socket::AF_INET6
|
553
611
|
if prefixlen < 0 || prefixlen > 128
|
554
|
-
raise InvalidPrefixError, "invalid length
|
612
|
+
raise InvalidPrefixError, "invalid length"
|
555
613
|
end
|
556
614
|
masklen = 128 - prefixlen
|
557
615
|
@mask_addr = ((IN6MASK >> masklen) << masklen)
|
@@ -647,12 +705,12 @@ class IPAddr
|
|
647
705
|
when Array
|
648
706
|
octets = addr
|
649
707
|
else
|
650
|
-
|
651
|
-
octets =
|
708
|
+
RE_IPV4ADDRLIKE.match?(addr) or return nil
|
709
|
+
octets = addr.split('.')
|
652
710
|
end
|
653
711
|
octets.inject(0) { |i, s|
|
654
712
|
(n = s.to_i) < 256 or raise InvalidAddressError, "invalid address: #{@addr}"
|
655
|
-
s.
|
713
|
+
(s != '0') && s.start_with?('0') and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}"
|
656
714
|
i << 8 | n
|
657
715
|
}
|
658
716
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ipaddr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Akinori MUSHA
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-10-19 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: |
|
15
15
|
IPAddr provides a set of methods to manipulate an IP address.
|
@@ -45,7 +45,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '0'
|
47
47
|
requirements: []
|
48
|
-
rubygems_version: 3.
|
48
|
+
rubygems_version: 3.5.21
|
49
49
|
signing_key:
|
50
50
|
specification_version: 4
|
51
51
|
summary: A class to manipulate an IP address in ruby
|