ipaddr 1.2.6 → 1.2.7

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.
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