better_ipaddr 0.1.2
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 +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +12 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +675 -0
- data/README.md +118 -0
- data/Rakefile +10 -0
- data/better_ipaddr.gemspec +25 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/better_ipaddr.rb +2 -0
- data/lib/better_ipaddr/classes.rb +72 -0
- data/lib/better_ipaddr/core_extension.rb +11 -0
- data/lib/better_ipaddr/methods.rb +332 -0
- data/lib/better_ipaddr/space.rb +142 -0
- data/lib/better_ipaddr/version.rb +3 -0
- metadata +103 -0
data/README.md
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# BetterIpaddr
|
2
|
+
|
3
|
+
[](https://rubygems.org/gems/better_ipaddr)
|
4
|
+
[](https://travis-ci.org/bjmllr/better_ipaddr)
|
5
|
+
|
6
|
+
The `IPAddr` class that network engineers always wanted.
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
require "better_ipaddr"
|
10
|
+
addr = IPAddr::V4[some_source] # shortcut for .new, because your test suite
|
11
|
+
# contains a zillion IP addresses and you're
|
12
|
+
# tired of typing Socket::AF_INET
|
13
|
+
addr.host? # is it a host address?
|
14
|
+
addr.network? # or a network address?
|
15
|
+
addr.cidr # what is the CIDR representation?
|
16
|
+
addr.grow(1) # what is the next larger enclosing network?
|
17
|
+
addr + 1 # what address comes after this one?
|
18
|
+
addr.size # how many host addresses fit in this network?
|
19
|
+
addr.mask_addr # what's the netmask (as an integer)?
|
20
|
+
addr.prefix_length # what's the prefix length (as an integer)?
|
21
|
+
addr == other_addr # are these the same network?
|
22
|
+
addr.cover?(other_addr) # does this network contain that one?
|
23
|
+
addr.overlap?(other_addr) # do these networks share any hosts?
|
24
|
+
addr.each { ... } # do something with each host in this network
|
25
|
+
addr.first # what's the network address?
|
26
|
+
addr.last # what's the broadcast address?
|
27
|
+
addr.wildcard # what's the wildcard mask for this network?
|
28
|
+
addr.summarize_with(other) # can these networks be summarized?
|
29
|
+
```
|
30
|
+
|
31
|
+
Bonus: comes with an IP space finder.
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
require "better_ipaddr/space"
|
35
|
+
space = BetterIpaddr::Space.new(some_array_of_ipaddrs,
|
36
|
+
space: IPAddr::V4["10.0.0.0/8"])
|
37
|
+
|
38
|
+
space.find_by_minimum_prefix_length(26) # => a subnet with at least 64 addresses
|
39
|
+
space.find_by_minimum_size(256) # => a /24 or larger
|
40
|
+
space.gaps # => all your free subnets
|
41
|
+
```
|
42
|
+
|
43
|
+
Coming soon: MAC addresses and their various notations.
|
44
|
+
|
45
|
+
## Installation
|
46
|
+
|
47
|
+
Ruby 2.0 or later is required. There are no other dependencies.
|
48
|
+
|
49
|
+
Add this line to your application's Gemfile:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
gem 'better_ipaddr'
|
53
|
+
```
|
54
|
+
|
55
|
+
And then execute:
|
56
|
+
|
57
|
+
$ bundle
|
58
|
+
|
59
|
+
Or install it yourself as:
|
60
|
+
|
61
|
+
$ gem install better_ipaddr
|
62
|
+
|
63
|
+
## Usage
|
64
|
+
|
65
|
+
There are multiple ways to load this gem.
|
66
|
+
|
67
|
+
The quick and dirty way is to `require
|
68
|
+
"better_ipaddr/core_extension"`, which adds all the additional methods
|
69
|
+
directly to `IPAddr`. This is "monkey patching", so there may be
|
70
|
+
unintended consequences. If you use this approach in another library
|
71
|
+
or framework, be very clear about it with your users.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
require "better_ipaddr/core_extension"
|
75
|
+
addr = IPAddr["1.0.0.1"]
|
76
|
+
class_c = addr << 8 # => IPAddr::V4["1.0.0.0/24"]
|
77
|
+
IPAddr.new("1.0.0.0/24").summarize_with(IPAddr["1.0.1.0/24"]) # => IPAddr::V4["1.0.0.0/23"]
|
78
|
+
```
|
79
|
+
|
80
|
+
The recommended way is to `require "better_ipaddr"` and use
|
81
|
+
the `IPAddr` subclasses explicitly.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
require "better_ipaddr"
|
85
|
+
addr = IPAddr::V4["1.0.0.1"]
|
86
|
+
class_c = addr << 8 # => IPAddr::V4["1.0.0.0/24"]
|
87
|
+
```
|
88
|
+
|
89
|
+
Another way is to `require "better_ipaddr/methods"` and mix
|
90
|
+
`BetterIpaddr::InstanceMethods` into your own class which implements
|
91
|
+
the rest of the `IPAddr` API, or into individual `IPAddr` objects.
|
92
|
+
|
93
|
+
`BetterIpaddr::Space`, a collection class for dealing with sets of network addresses, is also available but not loaded by default.
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
require "better_ipaddr/space"
|
97
|
+
space = BetterIpaddr::Space.new([IPAddr::V4["10.0.0.0/24"],
|
98
|
+
IPAddr::V4["10.0.2.0/24"]])
|
99
|
+
space.gaps # => BetterIpaddr::Space.new([IPAddr::V4["10.0.1.0/24"]])
|
100
|
+
```
|
101
|
+
|
102
|
+
The available methods are described in the [API docs](http://www.rubydoc.info/gems/better_ipaddr).
|
103
|
+
|
104
|
+
## Development
|
105
|
+
|
106
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
107
|
+
|
108
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
109
|
+
|
110
|
+
## Contributing
|
111
|
+
|
112
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/bjmllr/better_ipaddr. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
113
|
+
|
114
|
+
## Copyright and License
|
115
|
+
|
116
|
+
Copyright (C) 2016 Ben Miller
|
117
|
+
|
118
|
+
The gem is available as free software under the terms of the [GNU General Public License, Version 3](http://www.gnu.org/licenses/gpl-3.0.html).
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'better_ipaddr/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "better_ipaddr"
|
8
|
+
spec.version = BetterIpaddr::VERSION
|
9
|
+
spec.authors = ["Ben Miller"]
|
10
|
+
spec.email = ["bmiller@rackspace.com"]
|
11
|
+
|
12
|
+
spec.summary = "IPAddr enhancements for network management."
|
13
|
+
spec.homepage = "https://github.com/bjmllr/better_ipaddr"
|
14
|
+
spec.license = "GPL-3.0"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
.reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r(^exe/)) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.0"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
25
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "better_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
|
data/bin/setup
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require "better_ipaddr/methods"
|
2
|
+
|
3
|
+
class IPAddr
|
4
|
+
class Base < IPAddr
|
5
|
+
include BetterIpaddr::Constants
|
6
|
+
include BetterIpaddr::InstanceMethods
|
7
|
+
include Comparable
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
def inherited(cls)
|
11
|
+
cls.extend BetterIpaddr::ClassMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.[](address, mask = nil, family: self::FAMILY)
|
15
|
+
if mask
|
16
|
+
new(address, family).mask(new(mask, family).to_s)
|
17
|
+
else
|
18
|
+
new(address, family)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return the given address as an instance of a class specific to
|
23
|
+
# its address family.
|
24
|
+
#
|
25
|
+
# @param address [IPAddr] the address to convert
|
26
|
+
# @return [IPAddr::V4, IPAddr::V6, IPAddr::EUI48]
|
27
|
+
def self.specialize(address)
|
28
|
+
return address unless address.class == IPAddr
|
29
|
+
case address.family
|
30
|
+
when Family::IPV4
|
31
|
+
IPAddr::V4[address.to_i, address.instance_variable_get(:@mask_addr)]
|
32
|
+
when Family::IPV6
|
33
|
+
IPAddr::V6[address.to_i, address.instance_variable_get(:@mask_addr)]
|
34
|
+
when Family::EUI48
|
35
|
+
IPAddr::MAC[address.to_i, address.instance_variable_get(:@mask_addr)]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.specialize_constants(family)
|
40
|
+
const_set(:FAMILY, family)
|
41
|
+
const_set(:BIT_LENGTH, FAMILY_TO_BIT_LENGTH.fetch(self::FAMILY))
|
42
|
+
const_set(:NETMASK_TO_PREFIX_LENGTH,
|
43
|
+
NETMASK_TO_PREFIX_LENGTH.fetch(self::FAMILY))
|
44
|
+
const_set(:PREFIX_LENGTH_TO_NETMASK,
|
45
|
+
PREFIX_LENGTH_TO_NETMASK.fetch(self::FAMILY))
|
46
|
+
end
|
47
|
+
|
48
|
+
def address_family_bit_length
|
49
|
+
self.class::BIT_LENGTH
|
50
|
+
end
|
51
|
+
|
52
|
+
def network?
|
53
|
+
prefix_length < self.class::BIT_LENGTH
|
54
|
+
end
|
55
|
+
|
56
|
+
def prefix_length
|
57
|
+
self.class::NETMASK_TO_PREFIX_LENGTH[mask_addr]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class V4 < Base
|
62
|
+
specialize_constants Family::IPV4
|
63
|
+
end
|
64
|
+
|
65
|
+
class V6 < Base
|
66
|
+
specialize_constants Family::IPV6
|
67
|
+
end
|
68
|
+
|
69
|
+
class MAC < Base
|
70
|
+
specialize_constants Family::EUI48
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "ipaddr"
|
2
|
+
require "better_ipaddr/methods"
|
3
|
+
require "better_ipaddr/classes"
|
4
|
+
|
5
|
+
class IPAddr
|
6
|
+
include BetterIpaddr::Constants
|
7
|
+
extend BetterIpaddr::ClassMethods
|
8
|
+
prepend BetterIpaddr::InstanceMethods
|
9
|
+
include Comparable
|
10
|
+
include Enumerable
|
11
|
+
end
|
@@ -0,0 +1,332 @@
|
|
1
|
+
require "ipaddr"
|
2
|
+
require "socket"
|
3
|
+
|
4
|
+
module BetterIpaddr
|
5
|
+
module Constants
|
6
|
+
# Integer codes representing supported address clases.
|
7
|
+
# Reuse values from Socket namespace where possible.
|
8
|
+
module Family
|
9
|
+
IPV4 = Socket::AF_INET
|
10
|
+
IPV6 = Socket::AF_INET6
|
11
|
+
EUI48 = 48
|
12
|
+
EUI64 = 64
|
13
|
+
end
|
14
|
+
|
15
|
+
# Map well known address family names to constants.
|
16
|
+
SYMBOL_TO_FAMILY = {
|
17
|
+
ipv4: Family::IPV4,
|
18
|
+
ipv6: Family::IPV6,
|
19
|
+
eui48: Family::EUI48,
|
20
|
+
eui64: Family::EUI64,
|
21
|
+
mac: Family::EUI48
|
22
|
+
}
|
23
|
+
|
24
|
+
# Map each address family to the size of its address space, in bits.
|
25
|
+
FAMILY_TO_BIT_LENGTH = {
|
26
|
+
Family::IPV4 => 32,
|
27
|
+
Family::IPV6 => 128,
|
28
|
+
Family::EUI48 => 48,
|
29
|
+
Family::EUI64 => 64
|
30
|
+
}
|
31
|
+
|
32
|
+
# Map all possible prefix lengths to the corresponding netmasks.
|
33
|
+
PREFIX_LENGTH_TO_NETMASK = {}
|
34
|
+
FAMILY_TO_BIT_LENGTH.each_pair do |family, size|
|
35
|
+
netmasks = []
|
36
|
+
(0..size).each do |prefix_length|
|
37
|
+
netmasks[prefix_length] = 2**size - 2**(size - prefix_length)
|
38
|
+
end
|
39
|
+
PREFIX_LENGTH_TO_NETMASK[family] = netmasks
|
40
|
+
end
|
41
|
+
|
42
|
+
# Map all possible netmasks to the corresponding prefix lengths.
|
43
|
+
NETMASK_TO_PREFIX_LENGTH = {}
|
44
|
+
PREFIX_LENGTH_TO_NETMASK.each_pair do |family, hash|
|
45
|
+
NETMASK_TO_PREFIX_LENGTH[family] =
|
46
|
+
Hash[hash.map.with_index { |e, i| [e, i] }]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module ClassMethods
|
51
|
+
include Constants
|
52
|
+
|
53
|
+
# @overload [](address, family)
|
54
|
+
# @param address [Integer] the integer representation of the address
|
55
|
+
# @param family [Symbol] a symbol named for the address's
|
56
|
+
# address family, one of +:ipv4+, +:ipv6+, or +:mac+.
|
57
|
+
# @return [IPAddr]
|
58
|
+
# Wrapper for IPAddr.new that accepts a symbolic family name and
|
59
|
+
# returns a specialized IPAddr subclass.
|
60
|
+
#
|
61
|
+
# @overload [](address, family)
|
62
|
+
# @param address [Integer] the integer representation of the address
|
63
|
+
# @param family [Integer] the magic number representing the address's
|
64
|
+
# address family.
|
65
|
+
# @return [IPAddr]
|
66
|
+
# Wrapper for IPAddr.new that accepts a symbolic family name and
|
67
|
+
# returns a specialized IPAddr subclass.
|
68
|
+
#
|
69
|
+
# @overload [](address)
|
70
|
+
# @param address [String] the string representation of the address
|
71
|
+
# @return [IPAddr]
|
72
|
+
# Wrapper for IPAddr.new that accepts the string representation
|
73
|
+
# of an address returns a specialized IPAddr subclass.
|
74
|
+
|
75
|
+
def [](address, family = nil)
|
76
|
+
instance = case family
|
77
|
+
when Symbol
|
78
|
+
self[address, SYMBOL_TO_FAMILY.fetch(family)]
|
79
|
+
when IPAddr
|
80
|
+
address
|
81
|
+
when nil
|
82
|
+
new(address)
|
83
|
+
else
|
84
|
+
new(address, family)
|
85
|
+
end
|
86
|
+
IPAddr::Base.specialize(instance)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
module InstanceMethods
|
91
|
+
include Constants
|
92
|
+
|
93
|
+
# Return the magic number representing the address family.
|
94
|
+
# @return [Integer]
|
95
|
+
attr_reader :family
|
96
|
+
|
97
|
+
# Return the integer representation of the netmask.
|
98
|
+
# @return [Integer]
|
99
|
+
attr_reader :mask_addr
|
100
|
+
alias_method :netmask, :mask_addr
|
101
|
+
|
102
|
+
# Return the address greater than the original address by the
|
103
|
+
# given offset.
|
104
|
+
# @param offset [Integer] the difference between the original
|
105
|
+
# address and the returned address
|
106
|
+
# @return [IPAddr]
|
107
|
+
|
108
|
+
def +(offset)
|
109
|
+
self.class.new(@addr + offset, family)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Return the address less than the original address by the given
|
113
|
+
# offset.
|
114
|
+
# @param offset [Integer] the difference between the original
|
115
|
+
# address and the returned address
|
116
|
+
# @return [IPAddr]
|
117
|
+
|
118
|
+
def -(offset)
|
119
|
+
self + (-offset)
|
120
|
+
end
|
121
|
+
|
122
|
+
# @overload <=>(other)
|
123
|
+
# Compare this address with another address of the same address
|
124
|
+
# family.
|
125
|
+
# @param [IPAddr] other
|
126
|
+
# @return [Integer]
|
127
|
+
|
128
|
+
# @overload <=>(other)
|
129
|
+
# Compare this address with the integer representation of another
|
130
|
+
# address of the same address family.
|
131
|
+
# @param [Integer] other
|
132
|
+
# @return [Integer]
|
133
|
+
|
134
|
+
def <=>(other)
|
135
|
+
if other.is_a?(IPAddr)
|
136
|
+
family_difference = family <=> other.family
|
137
|
+
return family_difference unless family_difference == 0
|
138
|
+
elsif !other.is_a?(Integer)
|
139
|
+
fail ArgumentError, "Can't compare #{self.class} with #{other.class}"
|
140
|
+
end
|
141
|
+
|
142
|
+
address_difference = to_i <=> other.to_i
|
143
|
+
|
144
|
+
if address_difference != 0 || !other.is_a?(IPAddr)
|
145
|
+
return address_difference
|
146
|
+
end
|
147
|
+
|
148
|
+
other.instance_variable_get(:@mask_addr) <=> @mask_addr
|
149
|
+
end
|
150
|
+
|
151
|
+
# Test the equality of two IP addresses, or an IP address an
|
152
|
+
# integer representing an address in the same address family.
|
153
|
+
# @param other [IPAddr, Integer] the address to compare with
|
154
|
+
# @return [Boolean]
|
155
|
+
|
156
|
+
def ==(other)
|
157
|
+
return false if other.nil?
|
158
|
+
(self <=> other) == 0
|
159
|
+
end
|
160
|
+
|
161
|
+
# The address at the given offset relative to the network address
|
162
|
+
# of the network. A negative offset will be used to count
|
163
|
+
# backwards from the highest addresses within the network.
|
164
|
+
# @param offset [Integer] the index within the network of the
|
165
|
+
# desired address
|
166
|
+
# @return [IPAddr] the address at the given index
|
167
|
+
|
168
|
+
def [](offset)
|
169
|
+
offset2 = offset >= 0 ? offset : size + offset
|
170
|
+
self.class[to_i + offset2, family: family]
|
171
|
+
end
|
172
|
+
|
173
|
+
# Returns the number of bits allowed by the address family.
|
174
|
+
# A more efficient form of this method is available to the
|
175
|
+
# specialized IPAddr child classes.
|
176
|
+
#
|
177
|
+
# @return [Integer]
|
178
|
+
|
179
|
+
def address_family_bit_length
|
180
|
+
FAMILY_TO_BIT_LENGTH.fetch(family)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Returns a string representation of the address without a prefix length.
|
184
|
+
#
|
185
|
+
# @return [String]
|
186
|
+
|
187
|
+
def base
|
188
|
+
_to_string(@addr)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Return a string containing the CIDR representation of the address.
|
192
|
+
#
|
193
|
+
# @return [String]
|
194
|
+
|
195
|
+
def cidr
|
196
|
+
return _to_string(@addr) unless ipv4? || ipv6?
|
197
|
+
"#{_to_string(@addr)}/#{prefixlen}"
|
198
|
+
end
|
199
|
+
|
200
|
+
# Test whether or not this address completely encloses the other address.
|
201
|
+
|
202
|
+
def cover?(other)
|
203
|
+
first <= other.first && other.last <= last
|
204
|
+
end
|
205
|
+
|
206
|
+
# @overload each
|
207
|
+
# Yield each host address contained within the network. A host
|
208
|
+
# address, such as +1.1.1.1/32+, will yield only itself. Returns
|
209
|
+
# the original object.
|
210
|
+
# @yield [IPAddr]
|
211
|
+
# @return [IPAddr]
|
212
|
+
|
213
|
+
# @overload each
|
214
|
+
# Return an enumerator with the behavior described above.
|
215
|
+
# @return [Enumerator]
|
216
|
+
|
217
|
+
def each
|
218
|
+
if block_given?
|
219
|
+
(0...size).each do |offset|
|
220
|
+
yield self[offset]
|
221
|
+
end
|
222
|
+
self
|
223
|
+
else
|
224
|
+
enum_for(:each)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# The first host address in the network.
|
229
|
+
# @return [IPAddr]
|
230
|
+
|
231
|
+
def first
|
232
|
+
self[0]
|
233
|
+
end
|
234
|
+
|
235
|
+
# Return a new address with the prefix length reduced by the given
|
236
|
+
# amount. The new address will cover the original address.
|
237
|
+
# @param shift [Integer] the decrease in the prefix length
|
238
|
+
# @return [IPAddr]
|
239
|
+
|
240
|
+
def grow(shift)
|
241
|
+
mask(prefix_length - shift)
|
242
|
+
end
|
243
|
+
|
244
|
+
# Return true if the address represents a host (i.e., only one address).
|
245
|
+
|
246
|
+
def host?
|
247
|
+
prefix_length >= address_family_bit_length
|
248
|
+
end
|
249
|
+
|
250
|
+
# Return the last address in the network, which by convention is
|
251
|
+
# the broadcast address in IP networks.
|
252
|
+
# @return [IPAddr]
|
253
|
+
|
254
|
+
def last
|
255
|
+
self[-1]
|
256
|
+
end
|
257
|
+
|
258
|
+
alias_method :broadcast, :last
|
259
|
+
|
260
|
+
# Test whether or not two networks have any addresses in common
|
261
|
+
# (i.e., if either entirely encloses the other).
|
262
|
+
|
263
|
+
def overlap?(other)
|
264
|
+
cover?(other) || other.cover?(self)
|
265
|
+
end
|
266
|
+
|
267
|
+
# Return the prefix length.
|
268
|
+
# A more efficient form of this method is available to the
|
269
|
+
# specialized +IPAddr+ child classes.
|
270
|
+
# @return [Integer]
|
271
|
+
|
272
|
+
def prefix_length
|
273
|
+
NETMASK_TO_PREFIX_LENGTH[family][mask_addr]
|
274
|
+
end
|
275
|
+
|
276
|
+
alias_method :prefixlen, :prefix_length
|
277
|
+
|
278
|
+
# Return a new address with the prefix length increased by the
|
279
|
+
# given amount. The old address will cover the new address.
|
280
|
+
# @param shift [Integer] the increase in the prefix length
|
281
|
+
# @return [Boolean]
|
282
|
+
|
283
|
+
def shrink(shift)
|
284
|
+
mask(prefix_length + shift)
|
285
|
+
end
|
286
|
+
|
287
|
+
# Return the number of host addresses representable by the network
|
288
|
+
# given its size.
|
289
|
+
# @return [Integer]
|
290
|
+
|
291
|
+
def size
|
292
|
+
2**(address_family_bit_length - prefix_length)
|
293
|
+
end
|
294
|
+
|
295
|
+
# Returns a summary address if the two networks can be combined
|
296
|
+
# into a single network without covering any other networks.
|
297
|
+
# Returns +nil+ if the two networks can't be combined this way.
|
298
|
+
# @return [IPAddr?]
|
299
|
+
|
300
|
+
def summarize_with(other)
|
301
|
+
if other.nil?
|
302
|
+
nil
|
303
|
+
elsif cover?(other)
|
304
|
+
self
|
305
|
+
elsif other.cover?(self)
|
306
|
+
other
|
307
|
+
elsif other.grow(1) == grow(1)
|
308
|
+
grow(1)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
# Return a range representing the network. A block can be given to
|
313
|
+
# specify a conversion procedure, for example to convert the first
|
314
|
+
# and last addresses to integers before building the range.
|
315
|
+
# @return [Range(IPAddr)]
|
316
|
+
|
317
|
+
def to_range
|
318
|
+
if block_given?
|
319
|
+
(yield first)..(yield last)
|
320
|
+
else
|
321
|
+
first..last
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# Return a wildcard mask representing the network.
|
326
|
+
# @return [IPAddr]
|
327
|
+
|
328
|
+
def wildcard
|
329
|
+
_to_string(@mask_addr.to_i ^ (2**address_family_bit_length - 1))
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|