useful_utilities 5.4.6 → 5.5.0
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/lib/useful_utilities/ip.rb +222 -0
- data/lib/useful_utilities/version.rb +1 -1
- data/lib/useful_utilities.rb +1 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 070776adf9c916abe22c6c83c0bc51af55ce327b
|
4
|
+
data.tar.gz: 14abcd387fe88bcc23027e7375070543dd966470
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 815b9225aba50b2c7062b75740daa87bc9e78054d622d8915a8511c6f0df7d3e9319d304ed06b0dcf8fc09937d2a88e8781e94ca6f1428c6f9a8e919a7de5477
|
7
|
+
data.tar.gz: b164e91be3ab638bded3a1bc0f9dfd1a7d3f8b80ad78e697012fc944113714a5c2f019cf07e3a6f1b00eaf8136590fa5f2e26d8c42e4622712446c6bd18859c2
|
@@ -0,0 +1,222 @@
|
|
1
|
+
require 'ipaddr'
|
2
|
+
|
3
|
+
module UsefulUtilities
|
4
|
+
# Provides a bunch of convinient methods to deal with ip addresses
|
5
|
+
# The module rely on stdlib ipaddr
|
6
|
+
module IP
|
7
|
+
IPV4 = 4
|
8
|
+
IPV6 = 6
|
9
|
+
IPVERSIONS = [IPV4, IPV6].freeze
|
10
|
+
MAX_NET_MASK_IPV4 = 32
|
11
|
+
MAX_NET_MASK_IPV6 = 128
|
12
|
+
MIN_NET_MASK = 0
|
13
|
+
ZERO_IP_INTEGER = 0
|
14
|
+
|
15
|
+
# integer representing ip '10.0.0.0', start of '10.0.0.0/8'
|
16
|
+
PRIVATE_RANGE_10_START = 167772160
|
17
|
+
# integer representing ip '10.255.255.255', end of '10.0.0.0/8'
|
18
|
+
PRIVATE_RANGE_10_END = 184549375
|
19
|
+
|
20
|
+
# integer representing ip '172.16.0.0', start of '172.16.0.0/12'
|
21
|
+
PRIVATE_RANGE_172_START = 2886729728
|
22
|
+
# integer representing ip '172.31.255.255', end of '172.16.0.0/12'
|
23
|
+
PRIVATE_RANGE_172_END = 2887778303
|
24
|
+
|
25
|
+
# integer representing ip '192.168.0.0', start of '192.168.0.0/16'
|
26
|
+
PRIVATE_RANGE_192_START = 3232235520
|
27
|
+
# integer representing ip '192.168.255.255', end of '192.168.0.0/16'
|
28
|
+
PRIVATE_RANGE_192_END = 3232301055
|
29
|
+
|
30
|
+
# integer representing ip 'fc00::', start of 'fc00::/7'
|
31
|
+
PRIVATE_RANGE_FC_START = 334965454937798799971759379190646833152
|
32
|
+
# integer representing ip 'fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
|
33
|
+
# end of 'fc00::/7'
|
34
|
+
PRIVATE_RANGE_FC_END = 337623910929368631717566993311207522303
|
35
|
+
|
36
|
+
private_constant :IPV4,
|
37
|
+
:IPV6,
|
38
|
+
:IPVERSIONS,
|
39
|
+
:MAX_NET_MASK_IPV4,
|
40
|
+
:MAX_NET_MASK_IPV6,
|
41
|
+
:MIN_NET_MASK,
|
42
|
+
:ZERO_IP_INTEGER,
|
43
|
+
:PRIVATE_RANGE_10_START,
|
44
|
+
:PRIVATE_RANGE_10_END,
|
45
|
+
:PRIVATE_RANGE_172_START,
|
46
|
+
:PRIVATE_RANGE_172_END,
|
47
|
+
:PRIVATE_RANGE_192_START,
|
48
|
+
:PRIVATE_RANGE_192_END,
|
49
|
+
:PRIVATE_RANGE_FC_START,
|
50
|
+
:PRIVATE_RANGE_FC_END
|
51
|
+
|
52
|
+
extend self
|
53
|
+
|
54
|
+
# @param ip_string [String]
|
55
|
+
# @return [Boolean] true if supplied string is parsable ip address string
|
56
|
+
# and false otherwise
|
57
|
+
# @example
|
58
|
+
# UsefulUtilities::IP.valid_ip('10.10.0.1') #=> true
|
59
|
+
# UsefulUtilities::IP.valid_ip('non-parsable-ip') #=> false
|
60
|
+
def valid_ip?(ip_string)
|
61
|
+
IPAddr.new(ip_string)
|
62
|
+
true
|
63
|
+
rescue IPAddr::InvalidAddressError, IPAddr::AddressFamilyError
|
64
|
+
false
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param ip_string [String]
|
68
|
+
# @return [Boolean] true if ip_string represent private ip address.
|
69
|
+
# If ip_sting is non-parsable ip address ArgumentError raises.
|
70
|
+
# It is a wrapper on the private? method of IPAddr class instance.
|
71
|
+
# IPv4 addresses in 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16 as defined
|
72
|
+
# in RFC 1918 and IPv6 Unique Local Addresses in fc00::/7 as defined in
|
73
|
+
# RFC 4193 are considered private.
|
74
|
+
# @example
|
75
|
+
# UsefulUtilities::IP.private_ip?('10.10.10.10') #=> true
|
76
|
+
# UsefulUtilities::IP.private_ip?('8.10.10.10') #=> false
|
77
|
+
def private_ip?(ip_string)
|
78
|
+
ip = IPAddr.new(ip_string)
|
79
|
+
|
80
|
+
# starting from ruby 2.5.0 an IPAddr instance has built-in private? method
|
81
|
+
# use the built-in method if exists
|
82
|
+
return ip.private? if ip.respond_to?(:private?)
|
83
|
+
|
84
|
+
check_private_ip(ip)
|
85
|
+
rescue IPAddr::InvalidAddressError, IPAddr::AddressFamilyError
|
86
|
+
raise ArgumentError, 'Invalid ip address string supplied!'
|
87
|
+
end
|
88
|
+
|
89
|
+
# @param address [Integer]
|
90
|
+
# @param version. If version is not equal 4 or 6 ArgumentError raises.
|
91
|
+
# If supplied address can not be converted into ip address string
|
92
|
+
# then ArgumentError raises.
|
93
|
+
# @return string as human readable ip address.
|
94
|
+
# @example
|
95
|
+
# UsefulUtilities::IP.integer_to_ip_string(1,version: 4) #=> '0.0.0.1'
|
96
|
+
# UsefulUtilities::IP.integer_to_ip_string(1,version: 6) #=> '::1'
|
97
|
+
def integer_to_ip_string(address, version:)
|
98
|
+
unless address.is_a? Integer
|
99
|
+
raise ArgumentError, 'Supplied address is not integer!'
|
100
|
+
end
|
101
|
+
|
102
|
+
IPAddr.new(address, ip_address_family(version)).to_s
|
103
|
+
rescue IPAddr::InvalidAddressError, IPAddr::AddressFamilyError
|
104
|
+
raise ArgumentError, 'Invalid address!'
|
105
|
+
end
|
106
|
+
|
107
|
+
# @param ip_string [String]
|
108
|
+
# @return integer representation of supplied ip string.
|
109
|
+
# ArgumentError raises if ip string can not be parsed as ip address.
|
110
|
+
# @example
|
111
|
+
# UsefulUtilities::IP.ip_string_to_integer('0.0.0.2') #=> 2
|
112
|
+
# UsefulUtilities::IP.ip_string_to_integer('::2') #=> 2
|
113
|
+
def ip_string_to_integer(ip_string)
|
114
|
+
IPAddr.new(ip_string).to_i
|
115
|
+
rescue IPAddr::InvalidAddressError, IPAddr::AddressFamilyError
|
116
|
+
raise ArgumentError, 'Invalid ip address string supplied!'
|
117
|
+
end
|
118
|
+
|
119
|
+
# @param ip_string [String]
|
120
|
+
# @return array of 2 elements,
|
121
|
+
# the first: integer representation of supplied ip string,
|
122
|
+
# the second: version of ip protocol 4 or 6.
|
123
|
+
# ArgumentError raises if ip string can not be parsed as ip address.
|
124
|
+
# @example
|
125
|
+
# UsefulUtilities::IP.ip_string_to_integer_with_version('0.0.0.1') #=> [1, 4]
|
126
|
+
# UsefulUtilities::IP.ip_string_to_integer_with_version('::1') #=> [1, 6]
|
127
|
+
def ip_string_to_integer_with_version(ip_string)
|
128
|
+
ip = IPAddr.new(ip_string)
|
129
|
+
version = IPV4 if ip.ipv4?
|
130
|
+
version = IPV6 if ip.ipv6?
|
131
|
+
|
132
|
+
[ip.to_i, version]
|
133
|
+
rescue IPAddr::InvalidAddressError, IPAddr::AddressFamilyError
|
134
|
+
raise ArgumentError, 'Invalid ip address string supplied!'
|
135
|
+
end
|
136
|
+
|
137
|
+
# @param ip_string [String]
|
138
|
+
# @param network_mask [Integer]
|
139
|
+
# @return [String] value representing network address derived from supplied
|
140
|
+
# ip address and it's network mask
|
141
|
+
# @example
|
142
|
+
# UsefulUtilities::IP.network_address('10.10.15.33', 24) #=> "10.10.15.0"
|
143
|
+
def network_address(ip_string, network_mask)
|
144
|
+
ip = IPAddr.new(ip_string)
|
145
|
+
|
146
|
+
version = if ip.ipv4?
|
147
|
+
IPV4
|
148
|
+
elsif ip.ipv6?
|
149
|
+
IPV6
|
150
|
+
else
|
151
|
+
raise ArgumentError, 'Unsupported ip address version!'
|
152
|
+
end
|
153
|
+
|
154
|
+
unless acceptable_network_mask?(network_mask, version: version)
|
155
|
+
raise ArgumentError,
|
156
|
+
"Invalid network mask: '#{network_mask}' for address: '#{ip_string}'"
|
157
|
+
end
|
158
|
+
|
159
|
+
ip_network_address =
|
160
|
+
IPAddr.new(ZERO_IP_INTEGER, ip_address_family(version))
|
161
|
+
.~
|
162
|
+
.<<(max_network_mask(version) - network_mask)
|
163
|
+
.&(ip)
|
164
|
+
|
165
|
+
ip_network_address.to_s
|
166
|
+
rescue IPAddr::InvalidAddressError, IPAddr::AddressFamilyError
|
167
|
+
raise ArgumentError, 'Invalid ip address string supplied!'
|
168
|
+
end
|
169
|
+
|
170
|
+
# @param network_mask [Integer]
|
171
|
+
# @param version [Integer]
|
172
|
+
# @return [Boolean]
|
173
|
+
# ArgumentError raises if version is not equal 4 or 6.
|
174
|
+
# @example
|
175
|
+
# UsefulUtilities::IP.acceptable_network_mask?('not int', version: 4) #=> false
|
176
|
+
# UsefulUtilities::IP.acceptable_network_mask?(24, version: 4) #=> true
|
177
|
+
def acceptable_network_mask?(network_mask, version:)
|
178
|
+
return false unless network_mask.is_a? Integer
|
179
|
+
|
180
|
+
network_mask >= MIN_NET_MASK && network_mask <= max_network_mask(version)
|
181
|
+
end
|
182
|
+
|
183
|
+
private
|
184
|
+
|
185
|
+
def ip_address_family(ip_version)
|
186
|
+
return Socket::AF_INET if ip_version == IPV4
|
187
|
+
return Socket::AF_INET6 if ip_version == IPV6
|
188
|
+
|
189
|
+
raise ArgumentError,
|
190
|
+
'Unsupported ip address version! '\
|
191
|
+
"Supported argument values: #{IPV4} or #{IPV6}."
|
192
|
+
end
|
193
|
+
|
194
|
+
def max_network_mask(ip_version)
|
195
|
+
return MAX_NET_MASK_IPV4 if ip_version == IPV4
|
196
|
+
return MAX_NET_MASK_IPV6 if ip_version == IPV6
|
197
|
+
|
198
|
+
raise ArgumentError,
|
199
|
+
'Unsupported version supplied! '\
|
200
|
+
"Supported version values: #{IPV4} or #{IPV6}."
|
201
|
+
end
|
202
|
+
|
203
|
+
def check_private_ip(ip)
|
204
|
+
return true if ip.ipv4? && in_private_ipv4?(ip.to_i)
|
205
|
+
return true if ip.ipv6? && in_private_ipv6?(ip.to_i)
|
206
|
+
|
207
|
+
false
|
208
|
+
end
|
209
|
+
|
210
|
+
def in_private_ipv4?(integer_ip)
|
211
|
+
[
|
212
|
+
(PRIVATE_RANGE_10_START..PRIVATE_RANGE_10_END),
|
213
|
+
(PRIVATE_RANGE_172_START..PRIVATE_RANGE_172_END),
|
214
|
+
(PRIVATE_RANGE_192_START..PRIVATE_RANGE_192_END)
|
215
|
+
].any? { |range| range.include?(integer_ip) }
|
216
|
+
end
|
217
|
+
|
218
|
+
def in_private_ipv6?(integer_ip)
|
219
|
+
(PRIVATE_RANGE_FC_START..PRIVATE_RANGE_FC_END).include?(integer_ip)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
data/lib/useful_utilities.rb
CHANGED
@@ -8,6 +8,7 @@ module UsefulUtilities
|
|
8
8
|
require_relative 'useful_utilities/size'
|
9
9
|
require_relative 'useful_utilities/api'
|
10
10
|
require_relative 'useful_utilities/i18n'
|
11
|
+
require_relative 'useful_utilities/ip'
|
11
12
|
require_relative 'useful_utilities/hash'
|
12
13
|
require_relative 'useful_utilities/yaml'
|
13
14
|
require_relative 'useful_utilities/redhat_release'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: useful_utilities
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OnApp Ltd.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -94,8 +94,7 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
-
description:
|
98
|
-
A bunch of useful modules to work with time/size constants/hashes
|
97
|
+
description: " A bunch of useful modules to work with time/size constants/hashes\n"
|
99
98
|
email: onapp@onapp.com
|
100
99
|
executables: []
|
101
100
|
extensions: []
|
@@ -108,6 +107,7 @@ files:
|
|
108
107
|
- lib/useful_utilities/centos_version.rb
|
109
108
|
- lib/useful_utilities/hash.rb
|
110
109
|
- lib/useful_utilities/i18n.rb
|
110
|
+
- lib/useful_utilities/ip.rb
|
111
111
|
- lib/useful_utilities/numeric.rb
|
112
112
|
- lib/useful_utilities/redhat_release.rb
|
113
113
|
- lib/useful_utilities/size.rb
|
@@ -141,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
141
|
version: '0'
|
142
142
|
requirements: []
|
143
143
|
rubyforge_project:
|
144
|
-
rubygems_version: 2.
|
144
|
+
rubygems_version: 2.6.11
|
145
145
|
signing_key:
|
146
146
|
specification_version: 4
|
147
147
|
summary: Helpful methods for time, sizes, hashes etc.
|