ipaddr 1.2.9 → 1.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 +4 -4
- data/README.md +1 -1
- data/lib/ipaddr.rb +128 -29
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b3a45f67694de980f29fe97b4b20675bf93b95d8250b26dfcc0549816129394a
|
|
4
|
+
data.tar.gz: 37d8f96d02031b7847bd8c32b22776cdf0e9596a416defc64769899d5e89c6d3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3da16382856d2668a53ca3f270b708e0ec8d3d109e6c103aa9be482aac4b84697d12a9b928b13516a522ae355ab8c47e79299d4c18e356c6944add55a6033613
|
|
7
|
+
data.tar.gz: 60ec70c14d1715254f564070d8f3b7bbac87a7a07af194f99604fbf222d7cea15f08fc858497b8f9a342ea94dbccd1706f1d14b5b686792a800fce2c9cec9206
|
data/README.md
CHANGED
data/lib/ipaddr.rb
CHANGED
|
@@ -41,7 +41,7 @@ require 'socket'
|
|
|
41
41
|
|
|
42
42
|
class IPAddr
|
|
43
43
|
# The version string
|
|
44
|
-
VERSION = "1.
|
|
44
|
+
VERSION = "1.3.1"
|
|
45
45
|
|
|
46
46
|
# 32 bit mask for IPv4
|
|
47
47
|
IN4MASK = 0xffffffff
|
|
@@ -205,9 +205,51 @@ class IPAddr
|
|
|
205
205
|
return @addr
|
|
206
206
|
end
|
|
207
207
|
|
|
208
|
+
# Returns a string containing the binary representation of the
|
|
209
|
+
# IP address value, right adjusted to the address size (32 bits
|
|
210
|
+
# for IPv4, 128 bits for IPv6), regardless of the prefix length.
|
|
211
|
+
#
|
|
212
|
+
# e.g.:
|
|
213
|
+
# require 'ipaddr'
|
|
214
|
+
# p IPAddr.new("192.168.1.1").to_bits
|
|
215
|
+
# #=> "11000000101010000000000100000001"
|
|
216
|
+
# p IPAddr.new("3ffe:505:2::1").to_bits
|
|
217
|
+
# #=> "00111111111111100000010100000101" \
|
|
218
|
+
# # "00000000000000100000000000000000" \
|
|
219
|
+
# # "00000000000000000000000000000000" \
|
|
220
|
+
# # "00000000000000000000000000000001"
|
|
221
|
+
def to_bits
|
|
222
|
+
case @family
|
|
223
|
+
when Socket::AF_INET
|
|
224
|
+
@addr.to_s(2).rjust(32, '0')
|
|
225
|
+
when Socket::AF_INET6
|
|
226
|
+
@addr.to_s(2).rjust(128, '0')
|
|
227
|
+
else
|
|
228
|
+
raise AddressFamilyError, "unsupported address family"
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Returns a string containing the hexadecimal representation of the
|
|
233
|
+
# IP address value, right adjusted to the address size.
|
|
234
|
+
#
|
|
235
|
+
# e.g.:
|
|
236
|
+
# require 'ipaddr'
|
|
237
|
+
# p IPAddr.new("192.168.1.1").to_hex #=> "c0a80101"
|
|
238
|
+
# p IPAddr.new("3ffe:505:2::1").to_hex #=> "3ffe0505000200000000000000000001"
|
|
239
|
+
def to_hex
|
|
240
|
+
case @family
|
|
241
|
+
when Socket::AF_INET
|
|
242
|
+
@addr.to_s(16).rjust(8, '0')
|
|
243
|
+
when Socket::AF_INET6
|
|
244
|
+
@addr.to_s(16).rjust(32, '0')
|
|
245
|
+
else
|
|
246
|
+
raise AddressFamilyError, "unsupported address family"
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
208
250
|
# Returns a string containing the IP address representation.
|
|
209
251
|
def to_s
|
|
210
|
-
str =
|
|
252
|
+
str = _to_string(@addr)
|
|
211
253
|
return str if ipv4?
|
|
212
254
|
|
|
213
255
|
str.gsub!(/\b0{1,3}([\da-f]+)\b/i, '\1')
|
|
@@ -227,6 +269,7 @@ class IPAddr
|
|
|
227
269
|
str = sprintf('::%s%d.%d.%d.%d', $1, $2.hex / 256, $2.hex % 256, $3.hex / 256, $3.hex % 256)
|
|
228
270
|
end
|
|
229
271
|
|
|
272
|
+
str << @zone_id if @zone_id
|
|
230
273
|
str
|
|
231
274
|
end
|
|
232
275
|
|
|
@@ -267,12 +310,9 @@ class IPAddr
|
|
|
267
310
|
# Returns a network byte ordered string form of the IP address.
|
|
268
311
|
def hton
|
|
269
312
|
case @family
|
|
270
|
-
when Socket::AF_INET
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
return (0..7).map { |i|
|
|
274
|
-
(@addr >> (112 - 16 * i)) & 0xffff
|
|
275
|
-
}.pack('n8')
|
|
313
|
+
when Socket::AF_INET, Socket::AF_INET6
|
|
314
|
+
value = to_hex
|
|
315
|
+
return [value].pack("H#{value.length}")
|
|
276
316
|
else
|
|
277
317
|
raise AddressFamilyError, "unsupported address family"
|
|
278
318
|
end
|
|
@@ -294,11 +334,11 @@ class IPAddr
|
|
|
294
334
|
def loopback?
|
|
295
335
|
case @family
|
|
296
336
|
when Socket::AF_INET
|
|
297
|
-
@addr & 0xff000000 == 0x7f000000 # 127.0.0.1/8
|
|
337
|
+
(@addr & 0xff000000 == 0x7f000000) && prefix >= 8 # 127.0.0.1/8
|
|
298
338
|
when Socket::AF_INET6
|
|
299
339
|
@addr == 1 || # ::1
|
|
300
340
|
(@addr >> 32 == 0xffff && (
|
|
301
|
-
@addr & 0xff000000 == 0x7f000000 # ::ffff:127.0.0.1/8
|
|
341
|
+
(@addr & 0xff000000 == 0x7f000000) && prefix >= 104 # ::ffff:127.0.0.0/104 (127.0.0.1/8)
|
|
302
342
|
))
|
|
303
343
|
else
|
|
304
344
|
raise AddressFamilyError, "unsupported address family"
|
|
@@ -313,22 +353,22 @@ class IPAddr
|
|
|
313
353
|
def private?
|
|
314
354
|
case @family
|
|
315
355
|
when Socket::AF_INET
|
|
316
|
-
@addr & 0xff000000 == 0x0a000000 || # 10.0.0.0/8
|
|
317
|
-
@addr & 0xfff00000 == 0xac100000 ||
|
|
318
|
-
@addr & 0xffff0000 == 0xc0a80000
|
|
356
|
+
(@addr & 0xff000000 == 0x0a000000) && prefix >= 8 || # 10.0.0.0/8
|
|
357
|
+
(@addr & 0xfff00000 == 0xac100000) && prefix >= 12 || # 172.16.0.0/12
|
|
358
|
+
(@addr & 0xffff0000 == 0xc0a80000) && prefix >= 16 # 192.168.0.0/16
|
|
319
359
|
when Socket::AF_INET6
|
|
320
|
-
@addr & 0xfe00_0000_0000_0000_0000_0000_0000_0000 == 0xfc00_0000_0000_0000_0000_0000_0000_0000 ||
|
|
360
|
+
(@addr & 0xfe00_0000_0000_0000_0000_0000_0000_0000 == 0xfc00_0000_0000_0000_0000_0000_0000_0000) && prefix >= 7 || # fc00::/7
|
|
321
361
|
(@addr >> 32 == 0xffff && (
|
|
322
|
-
@addr & 0xff000000 == 0x0a000000 ||
|
|
323
|
-
@addr & 0xfff00000 == 0xac100000 ||
|
|
324
|
-
@addr & 0xffff0000 == 0xc0a80000
|
|
362
|
+
(@addr & 0xff000000 == 0x0a000000) && prefix >= 104 || # ::ffff:10.0.0.0/104 (10.0.0.0/8)
|
|
363
|
+
(@addr & 0xfff00000 == 0xac100000) && prefix >= 108 || # ::ffff:172.16.0.0/108 (172.16.0.0/12)
|
|
364
|
+
(@addr & 0xffff0000 == 0xc0a80000) && prefix >= 112 # ::ffff:192.168.0.0/112 (192.168.0.0/16)
|
|
325
365
|
))
|
|
326
366
|
else
|
|
327
367
|
raise AddressFamilyError, "unsupported address family"
|
|
328
368
|
end
|
|
329
369
|
end
|
|
330
370
|
|
|
331
|
-
# Returns true if the ipaddr is a link-local address. IPv4
|
|
371
|
+
# Returns true if the ipaddr is a link-local unicast address. IPv4
|
|
332
372
|
# addresses in 169.254.0.0/16 reserved by RFC 3927 and link-local
|
|
333
373
|
# IPv6 Unicast Addresses in fe80::/10 reserved by RFC 4291 are
|
|
334
374
|
# considered link-local. Link-local IPv4 addresses in the
|
|
@@ -336,11 +376,65 @@ class IPAddr
|
|
|
336
376
|
def link_local?
|
|
337
377
|
case @family
|
|
338
378
|
when Socket::AF_INET
|
|
339
|
-
@addr & 0xffff0000 == 0xa9fe0000 # 169.254.0.0/16
|
|
379
|
+
(@addr & 0xffff0000 == 0xa9fe0000) && prefix >= 16 # 169.254.0.0/16
|
|
340
380
|
when Socket::AF_INET6
|
|
341
|
-
@addr & 0xffc0_0000_0000_0000_0000_0000_0000_0000 == 0xfe80_0000_0000_0000_0000_0000_0000_0000 || # fe80::/10
|
|
381
|
+
(@addr & 0xffc0_0000_0000_0000_0000_0000_0000_0000 == 0xfe80_0000_0000_0000_0000_0000_0000_0000) && prefix >= 10 || # fe80::/10
|
|
342
382
|
(@addr >> 32 == 0xffff && (
|
|
343
|
-
@addr & 0xffff0000 == 0xa9fe0000 # ::ffff:169.254.0.0/16
|
|
383
|
+
(@addr & 0xffff0000 == 0xa9fe0000) && prefix >= 112 # ::ffff:169.254.0.0/112 (169.254.0.0/16)
|
|
384
|
+
))
|
|
385
|
+
else
|
|
386
|
+
raise AddressFamilyError, "unsupported address family"
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
alias link_local_unicast? link_local?
|
|
391
|
+
|
|
392
|
+
# Returns true if the ipaddr is an unspecified address. The IPv4
|
|
393
|
+
# address 0.0.0.0 and the IPv6 address :: are unspecified. Unspecified
|
|
394
|
+
# IPv4 addresses in the IPv4-mapped IPv6 address range are also
|
|
395
|
+
# considered unspecified.
|
|
396
|
+
def unspecified?
|
|
397
|
+
case @family
|
|
398
|
+
when Socket::AF_INET
|
|
399
|
+
@addr == 0 && prefix == 32 # 0.0.0.0
|
|
400
|
+
when Socket::AF_INET6
|
|
401
|
+
@addr == 0 && prefix == 128 || # ::
|
|
402
|
+
(@addr >> 32 == 0xffff && (@addr & IN4MASK) == 0) && prefix == 128 # ::ffff:0.0.0.0
|
|
403
|
+
else
|
|
404
|
+
raise AddressFamilyError, "unsupported address family"
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# Returns true if the ipaddr is a multicast address. IPv4
|
|
409
|
+
# addresses in 224.0.0.0/4 and IPv6 multicast addresses
|
|
410
|
+
# in ff00::/8 are considered multicast. Multicast IPv4 addresses in the
|
|
411
|
+
# IPv4-mapped IPv6 address range are also considered multicast.
|
|
412
|
+
def multicast?
|
|
413
|
+
case @family
|
|
414
|
+
when Socket::AF_INET
|
|
415
|
+
(@addr & 0xf0000000 == 0xe0000000) && prefix >= 4 # 224.0.0.0/4
|
|
416
|
+
when Socket::AF_INET6
|
|
417
|
+
(@addr & 0xff00_0000_0000_0000_0000_0000_0000_0000 == 0xff00_0000_0000_0000_0000_0000_0000_0000) && prefix >= 8 || # ff00::/8
|
|
418
|
+
(@addr >> 32 == 0xffff &&
|
|
419
|
+
(@addr & 0xf0000000 == 0xe0000000) && prefix >= 100 # ::ffff:224.0.0.0/100 (224.0.0.0/4)
|
|
420
|
+
)
|
|
421
|
+
else
|
|
422
|
+
raise AddressFamilyError, "unsupported address family"
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
# Returns true if the ipaddr is a link-local multicast address. IPv4
|
|
427
|
+
# addresses in 224.0.0.0/24 and link-local IPv6 Multicast Addresses in ff02::/16
|
|
428
|
+
# are considered link-local multicast. Link-local multicast IPv4 addresses in the
|
|
429
|
+
# IPv4-mapped IPv6 address range are also considered link-local multicast.
|
|
430
|
+
def link_local_multicast?
|
|
431
|
+
case @family
|
|
432
|
+
when Socket::AF_INET
|
|
433
|
+
(@addr & 0xffffff00 == 0xe0000000) && prefix >= 24 # 224.0.0.0/24 Local Network Control Block
|
|
434
|
+
when Socket::AF_INET6
|
|
435
|
+
(@addr & 0xffff_0000_0000_0000_0000_0000_0000_0000 == 0xff02_0000_0000_0000_0000_0000_0000_0000) && prefix >= 16 || # ff02::/16
|
|
436
|
+
(@addr >> 32 == 0xffff && (
|
|
437
|
+
(@addr & 0xffffff00 == 0xe0000000) && prefix >= 120 # ::ffff:224.0.0.0/120 (224.0.0.0/24)
|
|
344
438
|
))
|
|
345
439
|
else
|
|
346
440
|
raise AddressFamilyError, "unsupported address family"
|
|
@@ -539,7 +633,7 @@ class IPAddr
|
|
|
539
633
|
def zone_id=(zid)
|
|
540
634
|
if @family == Socket::AF_INET6
|
|
541
635
|
case zid
|
|
542
|
-
when nil, /\A%
|
|
636
|
+
when nil, /\A%[-0-9A-Za-z._~]+\z/
|
|
543
637
|
@zone_id = zid
|
|
544
638
|
else
|
|
545
639
|
raise InvalidAddressError, "invalid zone identifier for address"
|
|
@@ -673,12 +767,14 @@ class IPAddr
|
|
|
673
767
|
raise AddressFamilyError, "unsupported address family: #{family}"
|
|
674
768
|
end
|
|
675
769
|
end
|
|
770
|
+
requested_family = family
|
|
676
771
|
prefix, prefixlen = addr.split('/', 2)
|
|
677
772
|
if prefix =~ /\A\[(.*)\]\z/i
|
|
678
773
|
prefix = $1
|
|
679
774
|
family = Socket::AF_INET6
|
|
775
|
+
bracketed = true
|
|
680
776
|
end
|
|
681
|
-
if prefix =~ /\A(.*)(
|
|
777
|
+
if prefix =~ /\A(.*)(%[-0-9A-Za-z._~]+)\z/
|
|
682
778
|
prefix = $1
|
|
683
779
|
zone_id = $2
|
|
684
780
|
family = Socket::AF_INET6
|
|
@@ -698,11 +794,17 @@ class IPAddr
|
|
|
698
794
|
@family = Socket::AF_INET6
|
|
699
795
|
end
|
|
700
796
|
@zone_id = zone_id
|
|
701
|
-
if
|
|
797
|
+
if requested_family != Socket::AF_UNSPEC && @family != requested_family
|
|
702
798
|
raise AddressFamilyError, "address family mismatch"
|
|
703
799
|
end
|
|
704
800
|
if prefixlen
|
|
705
801
|
mask!(prefixlen)
|
|
802
|
+
|
|
803
|
+
if bracketed
|
|
804
|
+
warn "bracketed IPv6 address with a prefix length is an invalid address " \
|
|
805
|
+
"and will raise IPAddr::InvalidAddressError in a future version: #{addr}",
|
|
806
|
+
uplevel: 1
|
|
807
|
+
end
|
|
706
808
|
else
|
|
707
809
|
@mask_addr = (@family == Socket::AF_INET) ? IN4MASK : IN6MASK
|
|
708
810
|
end
|
|
@@ -747,7 +849,7 @@ class IPAddr
|
|
|
747
849
|
right = ''
|
|
748
850
|
when RE_IPV6ADDRLIKE_COMPRESSED
|
|
749
851
|
if $4
|
|
750
|
-
left.count(':') <= 6 or raise InvalidAddressError, "invalid address: #{left}"
|
|
852
|
+
left.count(':') <= ($1.empty? ? 7 : 6) or raise InvalidAddressError, "invalid address: #{left}"
|
|
751
853
|
addr = in_addr($~[4,4])
|
|
752
854
|
left = $1
|
|
753
855
|
right = $3 + '0:0'
|
|
@@ -764,9 +866,6 @@ class IPAddr
|
|
|
764
866
|
l = left.split(':')
|
|
765
867
|
r = right.split(':')
|
|
766
868
|
rest = 8 - l.size - r.size
|
|
767
|
-
if rest < 0
|
|
768
|
-
return nil
|
|
769
|
-
end
|
|
770
869
|
(l + Array.new(rest, '0') + r).inject(0) { |i, s|
|
|
771
870
|
i << 16 | s.hex
|
|
772
871
|
} | addr
|
|
@@ -790,7 +889,7 @@ class IPAddr
|
|
|
790
889
|
(@addr >> (8 * i)) & 0xff
|
|
791
890
|
}.join('.')
|
|
792
891
|
when Socket::AF_INET6
|
|
793
|
-
return
|
|
892
|
+
return to_hex.reverse.chars.join('.')
|
|
794
893
|
else
|
|
795
894
|
raise AddressFamilyError, "unsupported address family"
|
|
796
895
|
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.
|
|
4
|
+
version: 1.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Akinori MUSHA
|
|
@@ -42,7 +42,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
43
|
version: '0'
|
|
44
44
|
requirements: []
|
|
45
|
-
rubygems_version:
|
|
45
|
+
rubygems_version: 3.6.9
|
|
46
46
|
specification_version: 4
|
|
47
47
|
summary: A class to manipulate an IP address in ruby
|
|
48
48
|
test_files: []
|