ipaddr 1.2.2 → 1.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 78c5854e872965800e79a6508cb7d8ff3cb3ea73
4
- data.tar.gz: 0b6b8d515a8718a852beb923e7f5c24c9f65353d
2
+ SHA256:
3
+ metadata.gz: d2856d459b11572a7c59a6ad57ec0462b5e851a5c2a012cb6d106a8be15e3739
4
+ data.tar.gz: e8bf2d309cd922ad6c10af07f359034264be462b926718b4d8524e068084fa5f
5
5
  SHA512:
6
- metadata.gz: e3089db198e90b6c0860b09483f052fa1eb24cfb034d1473db3817e46e06b00d52afec9d5f43abaf09e01bf603324473ed9ed0de770e5bdf6de308f4e57cd556
7
- data.tar.gz: ed8a0801bc5aa5df9ddcbcb7d8134e521ab1e77af14c19a38b0e625c1ac77bf0e48f271ef54b517a805585d4d3611a2bed848f997d0b8166cccf25747fcdee35
6
+ metadata.gz: 372737acde9b6852b407d6b38df6392ea2240589eda19798e14fd01184594f0a9ef7d3a30d7f3ce5d178d314ff535a92fb1400f9895863c49047229175e1e350
7
+ data.tar.gz: 46aaa06ed661f88c99b63f844855ec91e9b17639799d5d3d980a77f7db236306511671d6f38b562d08fcdd35150b5bea1adccef2b182c7c8e5563a6439b374d7
data/README.md CHANGED
@@ -3,6 +3,8 @@
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)
7
+
6
8
  ## Installation
7
9
 
8
10
  This library is part of the standard ruby distribution as default gem
data/ipaddr.gemspec CHANGED
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "ipaddr"
8
- spec.version = "1.2.2"
8
+ spec.version = "1.2.3"
9
9
  spec.authors = ["Akinori MUSHA", "Hajimu UMEMOTO"]
10
10
  spec.email = ["knu@idaemons.org", "ume@mahoroba.org"]
11
11
 
@@ -15,14 +15,10 @@ IPAddr provides a set of methods to manipulate an IP address.
15
15
  Both IPv4 and IPv6 are supported.
16
16
  DESCRIPTION
17
17
  spec.homepage = "https://github.com/ruby/ipaddr"
18
- spec.license = "BSD-2-Clause"
18
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
19
19
 
20
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "ipaddr.gemspec", "lib/ipaddr.rb"]
21
- spec.bindir = "exe"
22
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.files = ["LICENSE.txt", "README.md", "ipaddr.gemspec", "lib/ipaddr.rb"]
23
21
  spec.require_paths = ["lib"]
24
22
 
25
- spec.add_development_dependency "bundler", "~> 1.15"
26
- spec.add_development_dependency "rake", "~> 10.0"
27
- spec.add_development_dependency "test-unit"
23
+ spec.required_ruby_version = ">= 2.3"
28
24
  end
data/lib/ipaddr.rb CHANGED
@@ -112,13 +112,12 @@ class IPAddr
112
112
  def self.ntop(addr)
113
113
  case addr.size
114
114
  when 4
115
- s = addr.unpack('C4').join('.')
115
+ addr.unpack('C4').join('.')
116
116
  when 16
117
- s = IN6FORMAT % addr.unpack('n8')
117
+ IN6FORMAT % addr.unpack('n8')
118
118
  else
119
119
  raise AddressFamilyError, "unsupported address family"
120
120
  end
121
- return s
122
121
  end
123
122
 
124
123
  # Returns a new ipaddr built by bitwise AND.
@@ -168,34 +167,17 @@ class IPAddr
168
167
  # net1 = IPAddr.new("192.168.2.0/24")
169
168
  # net2 = IPAddr.new("192.168.2.100")
170
169
  # net3 = IPAddr.new("192.168.3.0")
170
+ # net4 = IPAddr.new("192.168.2.0/16")
171
171
  # p net1.include?(net2) #=> true
172
172
  # p net1.include?(net3) #=> false
173
+ # p net1.include?(net4) #=> false
174
+ # p net4.include?(net1) #=> true
173
175
  def include?(other)
174
176
  other = coerce_other(other)
175
- if ipv4_mapped?
176
- if (@mask_addr >> 32) != 0xffffffffffffffffffffffff
177
- return false
178
- end
179
- mask_addr = (@mask_addr & IN4MASK)
180
- addr = (@addr & IN4MASK)
181
- family = Socket::AF_INET
182
- else
183
- mask_addr = @mask_addr
184
- addr = @addr
185
- family = @family
186
- end
187
- if other.ipv4_mapped?
188
- other_addr = (other.to_i & IN4MASK)
189
- other_family = Socket::AF_INET
190
- else
191
- other_addr = other.to_i
192
- other_family = other.family
193
- end
194
-
195
- if family != other_family
196
- return false
197
- end
198
- return ((addr & mask_addr) == (other_addr & mask_addr))
177
+ return false unless other.family == family
178
+ range = to_range
179
+ other = other.to_range
180
+ range.begin <= other.begin && range.end >= other.end
199
181
  end
200
182
  alias === include?
201
183
 
@@ -232,7 +214,13 @@ class IPAddr
232
214
  # Returns a string containing the IP address representation in
233
215
  # canonical form.
234
216
  def to_string
235
- return _to_string(@addr)
217
+ str = _to_string(@addr)
218
+
219
+ if @family == Socket::AF_INET6
220
+ str << zone_id.to_s
221
+ end
222
+
223
+ return str
236
224
  end
237
225
 
238
226
  # Returns a network byte ordered string form of the IP address.
@@ -328,9 +316,11 @@ class IPAddr
328
316
  # into an IPv4-mapped IPv6 address.
329
317
  def ipv4_mapped
330
318
  if !ipv4?
331
- raise InvalidAddressError, "not an IPv4 address"
319
+ raise InvalidAddressError, "not an IPv4 address: #{@addr}"
332
320
  end
333
- return self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6)
321
+ clone = self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6)
322
+ clone.instance_variable_set(:@mask_addr, @mask_addr | 0xffffffffffffffffffffffff00000000)
323
+ clone
334
324
  end
335
325
 
336
326
  # Returns a new ipaddr built by converting the native IPv4 address
@@ -338,7 +328,7 @@ class IPAddr
338
328
  def ipv4_compat
339
329
  warn "IPAddr\##{__callee__} is obsolete", uplevel: 1 if $VERBOSE
340
330
  if !ipv4?
341
- raise InvalidAddressError, "not an IPv4 address"
331
+ raise InvalidAddressError, "not an IPv4 address: #{@addr}"
342
332
  end
343
333
  return self.clone.set(@addr, Socket::AF_INET6)
344
334
  end
@@ -369,7 +359,7 @@ class IPAddr
369
359
  # Returns a string for DNS reverse lookup compatible with RFC3172.
370
360
  def ip6_arpa
371
361
  if !ipv6?
372
- raise InvalidAddressError, "not an IPv6 address"
362
+ raise InvalidAddressError, "not an IPv6 address: #{@addr}"
373
363
  end
374
364
  return _reverse + ".ip6.arpa"
375
365
  end
@@ -377,7 +367,7 @@ class IPAddr
377
367
  # Returns a string for DNS reverse lookup compatible with RFC1886.
378
368
  def ip6_int
379
369
  if !ipv6?
380
- raise InvalidAddressError, "not an IPv6 address"
370
+ raise InvalidAddressError, "not an IPv6 address: #{@addr}"
381
371
  end
382
372
  return _reverse + ".ip6.int"
383
373
  end
@@ -404,7 +394,7 @@ class IPAddr
404
394
 
405
395
  # Returns a hash value used by Hash, Set, and Array classes
406
396
  def hash
407
- return ([@addr, @mask_addr].hash << 1) | (ipv4? ? 0 : 1)
397
+ return ([@addr, @mask_addr, @zone_id].hash << 1) | (ipv4? ? 0 : 1)
408
398
  end
409
399
 
410
400
  # Creates a Range object for the network address.
@@ -448,7 +438,7 @@ class IPAddr
448
438
  when Integer
449
439
  mask!(prefix)
450
440
  else
451
- raise InvalidPrefixError, "prefix must be an integer"
441
+ raise InvalidPrefixError, "prefix must be an integer: #{@addr}"
452
442
  end
453
443
  end
454
444
 
@@ -460,11 +450,42 @@ class IPAddr
460
450
  af = "IPv4"
461
451
  when Socket::AF_INET6
462
452
  af = "IPv6"
453
+ zone_id = @zone_id.to_s
463
454
  else
464
455
  raise AddressFamilyError, "unsupported address family"
465
456
  end
466
- return sprintf("#<%s: %s:%s/%s>", self.class.name,
467
- af, _to_string(@addr), _to_string(@mask_addr))
457
+ return sprintf("#<%s: %s:%s%s/%s>", self.class.name,
458
+ af, _to_string(@addr), zone_id, _to_string(@mask_addr))
459
+ end
460
+
461
+ # Returns the netmask in string format e.g. 255.255.0.0
462
+ def netmask
463
+ _to_string(@mask_addr)
464
+ end
465
+
466
+ # Returns the IPv6 zone identifier, if present.
467
+ # Raises InvalidAddressError if not an IPv6 address.
468
+ def zone_id
469
+ if @family == Socket::AF_INET6
470
+ @zone_id
471
+ else
472
+ raise InvalidAddressError, "not an IPv6 address"
473
+ end
474
+ end
475
+
476
+ # Returns the IPv6 zone identifier, if present.
477
+ # Raises InvalidAddressError if not an IPv6 address.
478
+ def zone_id=(zid)
479
+ if @family == Socket::AF_INET6
480
+ case zid
481
+ when nil, /\A%(\w+)\z/
482
+ @zone_id = zid
483
+ else
484
+ raise InvalidAddressError, "invalid zone identifier for address"
485
+ end
486
+ else
487
+ raise InvalidAddressError, "not an IPv6 address"
488
+ end
468
489
  end
469
490
 
470
491
  protected
@@ -476,11 +497,11 @@ class IPAddr
476
497
  case family[0] ? family[0] : @family
477
498
  when Socket::AF_INET
478
499
  if addr < 0 || addr > IN4MASK
479
- raise InvalidAddressError, "invalid address"
500
+ raise InvalidAddressError, "invalid address: #{@addr}"
480
501
  end
481
502
  when Socket::AF_INET6
482
503
  if addr < 0 || addr > IN6MASK
483
- raise InvalidAddressError, "invalid address"
504
+ raise InvalidAddressError, "invalid address: #{@addr}"
484
505
  end
485
506
  else
486
507
  raise AddressFamilyError, "unsupported address family"
@@ -496,17 +517,20 @@ class IPAddr
496
517
  def mask!(mask)
497
518
  case mask
498
519
  when String
499
- if mask =~ /\A\d+\z/
520
+ case mask
521
+ when /\A(0|[1-9]+\d*)\z/
500
522
  prefixlen = mask.to_i
523
+ when /\A\d+\z/
524
+ raise InvalidPrefixError, "leading zeros in prefix"
501
525
  else
502
526
  m = IPAddr.new(mask)
503
527
  if m.family != @family
504
- raise InvalidPrefixError, "address family is not same"
528
+ raise InvalidPrefixError, "address family is not same: #{@addr}"
505
529
  end
506
530
  @mask_addr = m.to_i
507
531
  n = @mask_addr ^ m.instance_variable_get(:@mask_addr)
508
532
  unless ((n + 1) & n).zero?
509
- raise InvalidPrefixError, "invalid mask #{mask}"
533
+ raise InvalidPrefixError, "invalid mask #{mask}: #{@addr}"
510
534
  end
511
535
  @addr &= @mask_addr
512
536
  return self
@@ -517,13 +541,13 @@ class IPAddr
517
541
  case @family
518
542
  when Socket::AF_INET
519
543
  if prefixlen < 0 || prefixlen > 32
520
- raise InvalidPrefixError, "invalid length"
544
+ raise InvalidPrefixError, "invalid length: #{@addr}"
521
545
  end
522
546
  masklen = 32 - prefixlen
523
547
  @mask_addr = ((IN4MASK >> masklen) << masklen)
524
548
  when Socket::AF_INET6
525
549
  if prefixlen < 0 || prefixlen > 128
526
- raise InvalidPrefixError, "invalid length"
550
+ raise InvalidPrefixError, "invalid length: #{@addr}"
527
551
  end
528
552
  masklen = 128 - prefixlen
529
553
  @mask_addr = ((IN6MASK >> masklen) << masklen)
@@ -567,11 +591,16 @@ class IPAddr
567
591
  raise AddressFamilyError, "unsupported address family: #{family}"
568
592
  end
569
593
  end
570
- prefix, prefixlen = addr.split('/')
594
+ prefix, prefixlen = addr.split('/', 2)
571
595
  if prefix =~ /\A\[(.*)\]\z/i
572
596
  prefix = $1
573
597
  family = Socket::AF_INET6
574
598
  end
599
+ if prefix =~ /\A(.*)(%\w+)\z/
600
+ prefix = $1
601
+ zone_id = $2
602
+ family = Socket::AF_INET6
603
+ end
575
604
  # It seems AI_NUMERICHOST doesn't do the job.
576
605
  #Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil,
577
606
  # Socket::AI_NUMERICHOST)
@@ -586,6 +615,7 @@ class IPAddr
586
615
  @addr = in6_addr(prefix)
587
616
  @family = Socket::AF_INET6
588
617
  end
618
+ @zone_id = zone_id
589
619
  if family != Socket::AF_UNSPEC && @family != family
590
620
  raise AddressFamilyError, "address family mismatch"
591
621
  end
@@ -594,8 +624,6 @@ class IPAddr
594
624
  else
595
625
  @mask_addr = (@family == Socket::AF_INET) ? IN4MASK : IN6MASK
596
626
  end
597
- rescue InvalidAddressError => e
598
- raise e.class, "#{e.message}: #{addr}"
599
627
  end
600
628
 
601
629
  def coerce_other(other)
@@ -618,8 +646,8 @@ class IPAddr
618
646
  octets = m.captures
619
647
  end
620
648
  octets.inject(0) { |i, s|
621
- (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address"
622
- s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous"
649
+ (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address: #{@addr}"
650
+ s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}"
623
651
  i << 8 | n
624
652
  }
625
653
  end
@@ -636,19 +664,19 @@ class IPAddr
636
664
  right = ''
637
665
  when RE_IPV6ADDRLIKE_COMPRESSED
638
666
  if $4
639
- left.count(':') <= 6 or raise InvalidAddressError, "invalid address"
667
+ left.count(':') <= 6 or raise InvalidAddressError, "invalid address: #{@addr}"
640
668
  addr = in_addr($~[4,4])
641
669
  left = $1
642
670
  right = $3 + '0:0'
643
671
  else
644
672
  left.count(':') <= ($1.empty? || $2.empty? ? 8 : 7) or
645
- raise InvalidAddressError, "invalid address"
673
+ raise InvalidAddressError, "invalid address: #{@addr}"
646
674
  left = $1
647
675
  right = $2
648
676
  addr = 0
649
677
  end
650
678
  else
651
- raise InvalidAddressError, "invalid address"
679
+ raise InvalidAddressError, "invalid address: #{@addr}"
652
680
  end
653
681
  l = left.split(':')
654
682
  r = right.split(':')
metadata CHANGED
@@ -1,58 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ipaddr
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akinori MUSHA
8
8
  - Hajimu UMEMOTO
9
- autorequire:
10
- bindir: exe
9
+ autorequire:
10
+ bindir: bin
11
11
  cert_chain: []
12
- date: 2018-12-18 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: bundler
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - "~>"
19
- - !ruby/object:Gem::Version
20
- version: '1.15'
21
- type: :development
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - "~>"
26
- - !ruby/object:Gem::Version
27
- version: '1.15'
28
- - !ruby/object:Gem::Dependency
29
- name: rake
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - "~>"
33
- - !ruby/object:Gem::Version
34
- version: '10.0'
35
- type: :development
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - "~>"
40
- - !ruby/object:Gem::Version
41
- version: '10.0'
42
- - !ruby/object:Gem::Dependency
43
- name: test-unit
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - ">="
47
- - !ruby/object:Gem::Version
48
- version: '0'
49
- type: :development
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: '0'
12
+ date: 2021-10-25 00:00:00.000000000 Z
13
+ dependencies: []
56
14
  description: |
57
15
  IPAddr provides a set of methods to manipulate an IP address.
58
16
  Both IPv4 and IPv6 are supported.
@@ -63,21 +21,16 @@ executables: []
63
21
  extensions: []
64
22
  extra_rdoc_files: []
65
23
  files:
66
- - ".gitignore"
67
- - ".travis.yml"
68
- - Gemfile
69
24
  - LICENSE.txt
70
25
  - README.md
71
- - Rakefile
72
- - bin/console
73
- - bin/setup
74
26
  - ipaddr.gemspec
75
27
  - lib/ipaddr.rb
76
28
  homepage: https://github.com/ruby/ipaddr
77
29
  licenses:
30
+ - Ruby
78
31
  - BSD-2-Clause
79
32
  metadata: {}
80
- post_install_message:
33
+ post_install_message:
81
34
  rdoc_options: []
82
35
  require_paths:
83
36
  - lib
@@ -85,16 +38,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
38
  requirements:
86
39
  - - ">="
87
40
  - !ruby/object:Gem::Version
88
- version: '0'
41
+ version: '2.3'
89
42
  required_rubygems_version: !ruby/object:Gem::Requirement
90
43
  requirements:
91
44
  - - ">="
92
45
  - !ruby/object:Gem::Version
93
46
  version: '0'
94
47
  requirements: []
95
- rubyforge_project:
96
- rubygems_version: 2.6.14.1
97
- signing_key:
48
+ rubygems_version: 3.2.22
49
+ signing_key:
98
50
  specification_version: 4
99
51
  summary: A class to manipulate an IP address in ruby
100
52
  test_files: []
data/.gitignore DELETED
@@ -1,9 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
data/.travis.yml DELETED
@@ -1,21 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.3
5
- - 2.4
6
- - 2.5.0
7
- - ruby-head
8
- matrix:
9
- include:
10
- - rvm: jruby-9.1.13.0
11
- jdk: openjdk8
12
- - rvm: jruby-9.1.13.0
13
- jdk: oraclejdk8
14
- - rvm: jruby-head
15
- jdk: openjdk8
16
- - rvm: jruby-head
17
- jdk: oraclejdk8
18
- allow_failures:
19
- - rvm: ruby-head
20
- - rvm: jruby-head
21
- before_install: gem install bundler
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Specify your gem's dependencies in ipaddr.gemspec
4
- gemspec
data/Rakefile DELETED
@@ -1,10 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/test_*.rb"]
8
- end
9
-
10
- task :default => :test
data/bin/console DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "ipaddr"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here