ipaddr 1.2.6 → 1.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/ipaddr.rb +68 -18
  4. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f58727d4b57c7d063e7f6671b34b03f93de0b0b38f035528f9e3b6ef77842512
4
- data.tar.gz: 71c172f3e9506cfaacd857ad27099ca01f7862737590c3fd6ac4ca01952f96c1
3
+ metadata.gz: 566f76e26928f5a6014a11f985f08d1299dd06e7cb273cbc90b2553182b90006
4
+ data.tar.gz: f966e0490212bdb9194d05e6ee1d7e8df85ce622ed3692c46b2539c648e0315f
5
5
  SHA512:
6
- metadata.gz: f97223995de559e291ba8058014e3ba23606f36670c2cf8360aa1f35c2dfa716fc0956cda1ceead863715ecd5065457c295f8c8653e999e63757f88c2d937a11
7
- data.tar.gz: 20d8934e68d7f4be367267661c398c452f65d066b8a623e0e6fc2d17569fca3e82381606001eb0a56294132cd438e98ba5e7a34faf18098093bb71ea3aee9e86
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
- [![Build Status](https://travis-ci.org/ruby/ipaddr.svg?branch=master)](https://travis-ci.org/ruby/ipaddr)
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.6"
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
- (\d+) \. (\d+) \. (\d+) \. (\d+)
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
- case addr.size
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
@@ -222,6 +227,28 @@ class IPAddr
222
227
  return str
223
228
  end
224
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
+
225
252
  # Returns a network byte ordered string form of the IP address.
226
253
  def hton
227
254
  case @family
@@ -247,12 +274,17 @@ class IPAddr
247
274
  end
248
275
 
249
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.
250
279
  def loopback?
251
280
  case @family
252
281
  when Socket::AF_INET
253
- @addr & 0xff000000 == 0x7f000000
282
+ @addr & 0xff000000 == 0x7f000000 # 127.0.0.1/8
254
283
  when Socket::AF_INET6
255
- @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
+ ))
256
288
  else
257
289
  raise AddressFamilyError, "unsupported address family"
258
290
  end
@@ -282,15 +314,19 @@ class IPAddr
282
314
  end
283
315
 
284
316
  # Returns true if the ipaddr is a link-local address. IPv4
285
- # addresses in 169.254.0.0/16 reserved by RFC 3927 and Link-Local
317
+ # addresses in 169.254.0.0/16 reserved by RFC 3927 and link-local
286
318
  # IPv6 Unicast Addresses in fe80::/10 reserved by RFC 4291 are
287
- # considered link-local.
319
+ # considered link-local. Link-local IPv4 addresses in the
320
+ # IPv4-mapped IPv6 address range are also considered link-local.
288
321
  def link_local?
289
322
  case @family
290
323
  when Socket::AF_INET
291
324
  @addr & 0xffff0000 == 0xa9fe0000 # 169.254.0.0/16
292
325
  when Socket::AF_INET6
293
- @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
+ ))
294
330
  else
295
331
  raise AddressFamilyError, "unsupported address family"
296
332
  end
@@ -432,7 +468,7 @@ class IPAddr
432
468
  when Integer
433
469
  mask!(prefix)
434
470
  else
435
- raise InvalidPrefixError, "prefix must be an integer: #{@addr}"
471
+ raise InvalidPrefixError, "prefix must be an integer"
436
472
  end
437
473
  end
438
474
 
@@ -457,6 +493,20 @@ class IPAddr
457
493
  _to_string(@mask_addr)
458
494
  end
459
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
+
460
510
  # Returns the IPv6 zone identifier, if present.
461
511
  # Raises InvalidAddressError if not an IPv6 address.
462
512
  def zone_id
@@ -506,11 +556,11 @@ class IPAddr
506
556
  case family[0] ? family[0] : @family
507
557
  when Socket::AF_INET
508
558
  if addr < 0 || addr > IN4MASK
509
- raise InvalidAddressError, "invalid address: #{@addr}"
559
+ raise InvalidAddressError, "invalid address: #{addr}"
510
560
  end
511
561
  when Socket::AF_INET6
512
562
  if addr < 0 || addr > IN6MASK
513
- raise InvalidAddressError, "invalid address: #{@addr}"
563
+ raise InvalidAddressError, "invalid address: #{addr}"
514
564
  end
515
565
  else
516
566
  raise AddressFamilyError, "unsupported address family"
@@ -537,12 +587,12 @@ class IPAddr
537
587
  else
538
588
  m = IPAddr.new(mask)
539
589
  if m.family != @family
540
- raise InvalidPrefixError, "address family is not same: #{@addr}"
590
+ raise InvalidPrefixError, "address family is not same"
541
591
  end
542
592
  @mask_addr = m.to_i
543
593
  n = @mask_addr ^ m.instance_variable_get(:@mask_addr)
544
594
  unless ((n + 1) & n).zero?
545
- raise InvalidPrefixError, "invalid mask #{mask}: #{@addr}"
595
+ raise InvalidPrefixError, "invalid mask #{mask}"
546
596
  end
547
597
  @addr &= @mask_addr
548
598
  return self
@@ -553,13 +603,13 @@ class IPAddr
553
603
  case @family
554
604
  when Socket::AF_INET
555
605
  if prefixlen < 0 || prefixlen > 32
556
- raise InvalidPrefixError, "invalid length: #{@addr}"
606
+ raise InvalidPrefixError, "invalid length"
557
607
  end
558
608
  masklen = 32 - prefixlen
559
609
  @mask_addr = ((IN4MASK >> masklen) << masklen)
560
610
  when Socket::AF_INET6
561
611
  if prefixlen < 0 || prefixlen > 128
562
- raise InvalidPrefixError, "invalid length: #{@addr}"
612
+ raise InvalidPrefixError, "invalid length"
563
613
  end
564
614
  masklen = 128 - prefixlen
565
615
  @mask_addr = ((IN6MASK >> masklen) << masklen)
@@ -655,12 +705,12 @@ class IPAddr
655
705
  when Array
656
706
  octets = addr
657
707
  else
658
- m = RE_IPV4ADDRLIKE.match(addr) or return nil
659
- octets = m.captures
708
+ RE_IPV4ADDRLIKE.match?(addr) or return nil
709
+ octets = addr.split('.')
660
710
  end
661
711
  octets.inject(0) { |i, s|
662
712
  (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address: #{@addr}"
663
- s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}"
713
+ (s != '0') && s.start_with?('0') and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}"
664
714
  i << 8 | n
665
715
  }
666
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.6
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: 2023-12-16 00:00:00.000000000 Z
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.5.0.dev
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