wikk_ipv4 0.0.1 → 0.0.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 +4 -4
- data/History.txt +10 -0
- data/lib/wikk_ipv4.rb +194 -31
- data/version +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45e4407cf771cc48e192398fae57b65900e66aa1cee3b05ec67921bfb1e93389
|
4
|
+
data.tar.gz: ecf43d3987463028f34e86a77618b9edcd72e0617200b68f5259a5d7a5e5335c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fc0da6d2a34617489427f20986f0cf17df5344560f1f647c58c659bc597d8e35b2353ee2784dd915e80516355238ada2a544159a01e1d1a75f69d6fd2e2d6a7
|
7
|
+
data.tar.gz: 635d50f75017ed60324a376e230d619826c5fdecef9584ac8df5abbc64e91a84570c3249a5254f8ade08a8590e845d136a82b99dd4eab383e18d911d93a3524e
|
data/History.txt
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
robertburrowes Fri Jun 24 18:27:50 2022 +1200
|
2
|
+
bump version
|
3
|
+
robertburrowes Fri Jun 24 18:27:27 2022 +1200
|
4
|
+
added methods last_host and first_host to return IPv4 address Modified network and broadcast to either return the IPv4 or calculate these with a different mask applied. Tidied up the revptr and revnet Fixed the issubnet? test
|
5
|
+
robertburrowes Fri Jun 24 18:24:32 2022 +1200
|
6
|
+
created tests
|
7
|
+
robertburrowes Fri Jun 24 16:31:08 2022 +1200
|
8
|
+
merge in the other copy from 2018
|
9
|
+
robertburrowes Fri Jun 24 12:53:27 2022 +1200
|
10
|
+
chmod
|
1
11
|
robertburrowes Mon Jun 13 13:52:07 2022 +1200
|
2
12
|
rubocop
|
3
13
|
robertburrowes Mon Jun 13 13:45:19 2022 +1200
|
data/lib/wikk_ipv4.rb
CHANGED
@@ -2,87 +2,250 @@
|
|
2
2
|
module WIKK
|
3
3
|
# Some utility IPv4 calles
|
4
4
|
class IPv4
|
5
|
-
VERSION = '0.0.
|
5
|
+
VERSION = '0.0.2'
|
6
6
|
|
7
|
-
attr_reader :
|
7
|
+
attr_reader :host # [Integer] IPv4 Address
|
8
|
+
attr_reader :mask # [Integer] IPv4 Mask
|
9
|
+
attr_reader :mask_bytes # [Array] Integer values, for each byte
|
10
|
+
attr_reader :mask_length # [Integer] mask length i.e. 24 for /24
|
8
11
|
|
9
|
-
def initialize(
|
10
|
-
@mask = mask
|
11
|
-
if
|
12
|
-
ip =
|
12
|
+
def initialize(host, mask = 32)
|
13
|
+
@mask, @mask_length, @mask_bytes = process_mask(mask)
|
14
|
+
if host.instance_of?(String)
|
15
|
+
ip = host.split(/\./)
|
13
16
|
(0..3).each { |i| ip[i] = '0' if ip[i].nil? }
|
14
|
-
@
|
15
|
-
elsif
|
16
|
-
@
|
17
|
+
@host = ((ip[0].to_i << 24) | (ip[1].to_i << 16) | (ip[2].to_i << 8) | ip[3].to_i)
|
18
|
+
elsif host.instance_of?(Integer)
|
19
|
+
@host = host
|
20
|
+
else
|
21
|
+
@host = nil
|
22
|
+
return
|
23
|
+
end
|
24
|
+
@network = @host & @mask
|
25
|
+
@broadcast = (~@network & ~@mask & 0xFFFFFFFF) | @network
|
26
|
+
@first_host = @network + 1
|
27
|
+
@last_host = @broadcast - 1
|
28
|
+
end
|
29
|
+
|
30
|
+
def process_mask(mask)
|
31
|
+
if mask.instance_of?(String)
|
32
|
+
return process_string_mask(mask)
|
33
|
+
elsif mask.instance_of?(Integer)
|
34
|
+
return process_int_mask(mask)
|
17
35
|
else
|
18
|
-
|
36
|
+
raise "Unknown Mask type #{mask.class}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Takes an Integer mask, and returns the length in bits
|
41
|
+
# @param [Integer] Integer Mask (0xFF000000)
|
42
|
+
# @return [Integer] Mask length in bits (8)
|
43
|
+
def calc_mask_length(mask)
|
44
|
+
mask_length = 0
|
45
|
+
(1..32).each do |_i|
|
46
|
+
mask_length += 1 if (mask & 0x1) == 1
|
47
|
+
mask = mask >> 1
|
19
48
|
end
|
49
|
+
return mask_length
|
50
|
+
end
|
51
|
+
|
52
|
+
def length
|
53
|
+
broadcast.to_i - network.to_i + 1
|
20
54
|
end
|
21
55
|
|
22
|
-
|
56
|
+
# Turns mask string into an Integer mask, mask length and Integer array
|
57
|
+
# @param mask [String] Mask of the form '255.0.0.0'
|
58
|
+
# @return [Array] Integer Mask (0xFF000000), Mask Length (8), Mask Integer Array ([0xFF,0,0,0])
|
59
|
+
def process_string_mask(mask)
|
60
|
+
return nil, nil, nil if mask.class != String
|
61
|
+
|
62
|
+
mask_bytes = mask.split('.') # Make into a byte array
|
63
|
+
mask_bytes.collect!(& :to_i) # Convert the string bytes into integers
|
64
|
+
# Turn the byte array into a single integer.
|
65
|
+
mask = (mask_bytes[0] << 24) + (mask_bytes[1] << 16) + (mask_bytes[2] << 8) + mask_bytes[3]
|
66
|
+
mask_length = calc_mask_length(mask)
|
67
|
+
|
68
|
+
return mask, mask_length, mask_bytes
|
69
|
+
end
|
70
|
+
|
71
|
+
# Turns mask into an Integer mask, mask length and Integer array
|
72
|
+
# @param mask [Integer] Either an Integer mask (0xFF000000), or the mask length (8) as an Integer
|
73
|
+
# @return [Array] Integer Mask (0xFF000000), Mask Length (8), Mask Integer Array ([0xFF, 0,0,0])
|
74
|
+
def process_int_mask(mask)
|
75
|
+
return nil, nil, nil unless mask.instance_of?(Integer)
|
76
|
+
|
77
|
+
if (mask & 0x800000) == 0 # Assume it is the mask length
|
78
|
+
mask_length = mask
|
79
|
+
mask = 0xFFFFFFFF << (32 - mask_length)
|
80
|
+
else # Assume it is a full mask
|
81
|
+
mask_length = calc_mask_length(mask)
|
82
|
+
end
|
83
|
+
|
84
|
+
mask_bytes = []
|
85
|
+
mask_bytes[3] = mask & 255
|
86
|
+
mask_bytes[2] = (mask >> 8) & 255
|
87
|
+
mask_bytes[1] = (mask >> 16) & 255
|
88
|
+
mask_bytes[0] = (mask >> 24) & 255
|
89
|
+
|
90
|
+
return mask, mask_length, mask_bytes
|
91
|
+
end
|
92
|
+
|
93
|
+
# Store IP address in @host
|
94
|
+
# @param value [String|Integer] Accepts "x.x.x.x" or a network order Integer IP address
|
95
|
+
def host=(value)
|
23
96
|
if value.instance_of?(String)
|
24
97
|
ip = s.split(/\./)
|
25
98
|
(0..3).each { |i| ip[i] = '0' if ip[i].nil? }
|
26
|
-
@
|
99
|
+
@host = ((ip[0].to_i << 24) | (ip[1].to_i << 16) | (ip[2].to_i << 8) | ip[3].to_i) & mask
|
27
100
|
else
|
28
|
-
@
|
101
|
+
@host = value
|
29
102
|
end
|
30
103
|
end
|
31
104
|
|
32
|
-
|
33
|
-
|
34
|
-
|
105
|
+
alias ipaddress= host=
|
106
|
+
alias ipaddress host
|
107
|
+
|
108
|
+
# @return [String] the host address
|
109
|
+
def to_s(mask = 32) # 32 being a host ip address. Can also be a String, or Integer Mask
|
110
|
+
mask, _mask_length, _mask_bytes = process_mask(mask)
|
111
|
+
if @host
|
112
|
+
ip = (@host & mask)
|
35
113
|
"#{(ip >> 24) & 255}.#{(ip >> 16) & 255}.#{(ip >> 8) & 255}.#{ip & 255}"
|
36
114
|
else
|
37
115
|
''
|
38
116
|
end
|
39
117
|
end
|
40
118
|
|
41
|
-
|
42
|
-
|
119
|
+
# @return [IPv4] the host address
|
120
|
+
def network(mask = nil)
|
121
|
+
if mask.nil?
|
122
|
+
self.class.new(@network, @mask)
|
123
|
+
else
|
124
|
+
mask, _mask_length, _mask_bytes = process_mask(mask)
|
125
|
+
self.class.new(@host & mask, mask)
|
126
|
+
end
|
43
127
|
end
|
44
128
|
|
45
|
-
|
46
|
-
|
129
|
+
# @return [IPv4] The broadcast address
|
130
|
+
def broadcast(mask = nil)
|
131
|
+
if mask.nil?
|
132
|
+
self.class.new(@broadcast, @mask)
|
133
|
+
else
|
134
|
+
self.class.new((~@host & ~mask & 0xFFFFFFFF) | @network, mask)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# @return [IPv4] First host IPv4 Address for this mask
|
139
|
+
def first_host
|
140
|
+
self.class.new(@first_host, @mask)
|
141
|
+
end
|
142
|
+
|
143
|
+
# @return [IPv4] Second to last IPv4 Address for this mask
|
144
|
+
def last_host
|
145
|
+
self.class.new(@last_host, @mask)
|
47
146
|
end
|
48
147
|
|
148
|
+
# @return [Integer] the IPv4 address as an integer
|
49
149
|
def to_i
|
50
|
-
@
|
150
|
+
@host
|
51
151
|
end
|
52
152
|
|
153
|
+
# @return [Integer] IPv4 mask from a string to an Int
|
53
154
|
def self.mask_to_i(s)
|
54
155
|
ip = s.split(/\./)
|
55
156
|
((ip[0].to_i << 24) | (ip[1].to_i << 16) | (ip[2].to_i << 8) | ip[3].to_i)
|
56
157
|
end
|
57
158
|
|
159
|
+
# @return [Integer] mask for number of bits in mask
|
58
160
|
def self.maskbits_to_i(n)
|
59
161
|
0xffffffff >> (32 - n) << (32 - n)
|
60
162
|
end
|
61
163
|
|
164
|
+
# @return [IPv4] add two addresses
|
62
165
|
def +(other)
|
63
|
-
self.class.new(@
|
166
|
+
self.class.new(@host + other)
|
64
167
|
end
|
65
168
|
|
66
|
-
|
67
|
-
|
68
|
-
|
169
|
+
# @return [IPv4] Difference between two addresses
|
170
|
+
def -(other)
|
171
|
+
self.class.new(@host - other)
|
69
172
|
end
|
70
173
|
|
71
|
-
|
72
|
-
|
73
|
-
|
174
|
+
# @return [String] host part of IPv4 as DNS reverse string
|
175
|
+
def revptr(bytes = nil, mask = nil)
|
176
|
+
if mask.nil?
|
177
|
+
mask = @mask
|
178
|
+
else
|
179
|
+
mask, _mask_length, _mask_bytes = process_mask(mask)
|
180
|
+
end
|
181
|
+
addr = (@host & ~mask)
|
182
|
+
bytes ||= 4 - ((@mask_length - 1) / 8 + 1)
|
183
|
+
rip = [ "#{addr & 255}", "#{(addr >> 8) & 255}", "#{(addr >> 16) & 255}", "#{(addr >> 24) & 255}" ]
|
184
|
+
rip[0..bytes].join('.')
|
185
|
+
end
|
186
|
+
|
187
|
+
# @return [String] host part of IPv4 as DNS reverse string
|
188
|
+
def revnet(bytes = nil, mask = nil)
|
189
|
+
if mask.nil?
|
190
|
+
mask = @mask
|
191
|
+
else
|
192
|
+
mask, _mask_length, _mask_bytes = process_mask(mask)
|
193
|
+
end
|
194
|
+
addr = (@host & mask)
|
195
|
+
bytes ||= ((@mask_length - 1) / 8 + 1) - 4
|
196
|
+
rip = [ "#{addr & 255}", "#{(addr >> 8) & 255}", "#{(addr >> 16) & 255}", "#{(addr >> 24) & 255}" ]
|
197
|
+
rip[bytes..-1].join('.')
|
74
198
|
end
|
75
199
|
|
200
|
+
# Test if IP addresses are the same
|
201
|
+
# @param i [IPV4] address to check against local ip address
|
202
|
+
# @return [Boolean]
|
76
203
|
def ==(other)
|
77
|
-
@
|
204
|
+
@host == other.host
|
78
205
|
end
|
79
206
|
|
207
|
+
# @return [Boolean] the IP address is not nil
|
80
208
|
def notnil?
|
81
|
-
@
|
209
|
+
@host != nil
|
82
210
|
end
|
83
211
|
|
212
|
+
# Test to see if one network is a subnet of another
|
213
|
+
# @param net [IPV4] Net we want to check is a subnet of this net
|
214
|
+
# @return [Boolean]
|
84
215
|
def issubnet?(net)
|
85
|
-
(@
|
216
|
+
(@network == (net.host & @mask)) && @mask_length <= net.mask_length
|
217
|
+
end
|
218
|
+
|
219
|
+
# @return [Array] Split IPv4 address (integer) into 4 bytes
|
220
|
+
def to_bytes(address)
|
221
|
+
bytes = []
|
222
|
+
bytes[3] = address & 255
|
223
|
+
bytes[2] = (address >> 8) & 255
|
224
|
+
bytes[1] = (address >> 16) & 255
|
225
|
+
bytes[0] = (address >> 24) & 255
|
226
|
+
return bytes
|
227
|
+
end
|
228
|
+
|
229
|
+
# @return [String] IPv4 address
|
230
|
+
def ip_to_s(address)
|
231
|
+
bytes = to_bytes(address)
|
232
|
+
"#{bytes[0]}.#{bytes[1]}.#{bytes[2]}.#{bytes[3]}"
|
233
|
+
end
|
234
|
+
|
235
|
+
# Iterate over a network's IP addresses
|
236
|
+
# @yield [IPv4] addresses
|
237
|
+
def each_ip
|
238
|
+
((@network + 1)..@last_host).each { |ip| yield ip_to_s(ip) }
|
239
|
+
end
|
240
|
+
|
241
|
+
# Compare two IPv4 addresses
|
242
|
+
def <=>(other)
|
243
|
+
@host.to_i <=> other.to_i
|
244
|
+
end
|
245
|
+
|
246
|
+
# @return [IPv4] the next IPv4 address
|
247
|
+
def succ
|
248
|
+
self.class.new(@host + 1)
|
86
249
|
end
|
87
250
|
end
|
88
251
|
end
|
data/version
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
PROJECT="wikk_ipv4"
|
2
|
-
VERSION="0.0.
|
2
|
+
VERSION="0.0.2"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wikk_ipv4
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob Burrowes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-06-
|
11
|
+
date: 2022-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hoe-yard
|