blackwinter-ipaddress 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,269 @@
1
+ class IPAddress
2
+
3
+ #
4
+ # =NAME
5
+ #
6
+ # IPAddress::Prefix
7
+ #
8
+ # =SYNOPSIS
9
+ #
10
+ # Parent class for Prefix32 and Prefix128
11
+ #
12
+ # =DESCRIPTION
13
+ #
14
+ # IPAddress::Prefix is the parent class for IPAddress::Prefix32
15
+ # and IPAddress::Prefix128, defining some modules in common for
16
+ # both the subclasses.
17
+ #
18
+ # IPAddress::Prefix shouldn't be accesses directly, unless
19
+ # for particular needs.
20
+ #
21
+ class Prefix
22
+
23
+ include Comparable
24
+
25
+ include Conversions
26
+ extend Conversions
27
+
28
+ include Lazy
29
+
30
+ #
31
+ # Creates a new prefix object for 32 bits IPv4 addresses /
32
+ # 128 bits IPv6 addresses.
33
+ #
34
+ # prefix = IPAddress::Prefix32.new(24)
35
+ # #=> 24
36
+ #
37
+ # prefix6 = IPAddress::Prefix128.new(64)
38
+ # #=> 64
39
+ #
40
+ def initialize(num = nil)
41
+ validate_prefix(@prefix = case num
42
+ when self.class then num.prefix
43
+ when nil then max
44
+ else num.to_i
45
+ end)
46
+ end
47
+
48
+ attr_reader :prefix
49
+
50
+ #
51
+ # Returns a string with the prefix
52
+ #
53
+ def to_s
54
+ prefix.to_s
55
+ end
56
+
57
+ def inspect
58
+ "#{self.class}@#{to_s}"
59
+ end
60
+
61
+ #
62
+ # Transforms the prefix into a string of bits
63
+ # representing the netmask
64
+ #
65
+ # prefix32 = IPAddress::Prefix32.new(24)
66
+ #
67
+ # prefix32.bits
68
+ # #=> "11111111111111111111111100000000"
69
+ #
70
+ # prefix128 = IPAddress::Prefix128.new(64)
71
+ #
72
+ # prefix128.bits
73
+ # #=> "1111111111111111111111111111111111111111111111111111111111111111"
74
+ # "0000000000000000000000000000000000000000000000000000000000000000"
75
+ #
76
+ def bits
77
+ lazy(:bits) { '1' * prefix << '0' * host_prefix }
78
+ end
79
+
80
+ #
81
+ # Unsigned 32/128 bits decimal number representing
82
+ # the prefix
83
+ #
84
+ # prefix = IPAddress::Prefix32.new(24)
85
+ #
86
+ # prefix.to_u32
87
+ # #=> 4294967040
88
+ #
89
+ # prefix6 = IPAddress::Prefix128.new(64)
90
+ #
91
+ # prefix6.to_u128
92
+ # #=> 340282366920938463444927863358058659840
93
+ #
94
+ def to_i
95
+ lazy(:int) { bits.to_i(2) }
96
+ end
97
+
98
+ #
99
+ # Compare the prefix
100
+ #
101
+ def <=>(other)
102
+ prefix <=> other.prefix
103
+ end
104
+
105
+ def hash
106
+ prefix.hash
107
+ end
108
+
109
+ alias_method :eql?, :==
110
+
111
+ #
112
+ # Sums two prefixes or a prefix to a
113
+ # number, returns a Fixnum
114
+ #
115
+ def +(other)
116
+ prefix + (other.is_a?(self.class) ? other.prefix : other)
117
+ end
118
+
119
+ #
120
+ # Returns the difference between two
121
+ # prefixes, or a prefix and a number,
122
+ # as a Fixnum
123
+ #
124
+ def -(other)
125
+ (prefix - (other.is_a?(self.class) ? other.prefix : other)).abs
126
+ end
127
+
128
+ #
129
+ # Returns the length of the host portion
130
+ # of a netmask.
131
+ #
132
+ # prefix32 = Prefix32.new(24)
133
+ #
134
+ # prefix32.host_prefix
135
+ # #=> 8
136
+ #
137
+ # prefix128 = Prefix128.new(96)
138
+ #
139
+ # prefix128.host_prefix
140
+ # #=> 32
141
+ #
142
+ def host_prefix
143
+ lazy(:host_prefix) { max - prefix }
144
+ end
145
+
146
+ def max
147
+ lazy(:max) { self.class::MAX }
148
+ end
149
+
150
+ def max?
151
+ lazy(:max_p) { prefix == max }
152
+ end
153
+
154
+ def prev
155
+ lazy(:prev) { prefix - 1 }
156
+ end
157
+
158
+ def next
159
+ lazy(:next) { prefix + 1 unless max? }
160
+ end
161
+
162
+ def superprefix(num)
163
+ validate_prefix(num = [0, num].max, nil, prev)
164
+ num
165
+ end
166
+
167
+ def subprefix(num)
168
+ validate_prefix(num, prefix)
169
+ [2 ** (max - num), 2 ** (num - prefix)]
170
+ end
171
+
172
+ def validate_prefix(num, first = nil, last = nil)
173
+ unless (range = (first || 0)..(last || max)).include?(num)
174
+ raise ArgumentError, "Prefix must be in range #{range}, got: #{num}"
175
+ end
176
+ end
177
+
178
+ end
179
+
180
+ class Prefix32 < Prefix
181
+
182
+ MAX = 32
183
+
184
+ class << self
185
+
186
+ #
187
+ # Creates a new prefix by parsing a netmask in
188
+ # dotted decimal form
189
+ #
190
+ # prefix = IPAddress::Prefix32.parse_netmask("255.255.255.0")
191
+ # #=> 24
192
+ #
193
+ def parse_netmask(netmask)
194
+ octets = addr2ary(netmask)
195
+ new(data2bits(octets.pack("C#{octets.size}")).count('1'))
196
+ end
197
+
198
+ end
199
+
200
+ alias_method :to_u32, :to_i
201
+
202
+ #
203
+ # Gives the prefix in IPv4 dotted decimal format,
204
+ # i.e. the canonical netmask we're all used to
205
+ #
206
+ # prefix = IPAddress::Prefix32.new(24)
207
+ #
208
+ # prefix.to_ip
209
+ # #=> "255.255.255.0"
210
+ #
211
+ def to_ip
212
+ lazy(:ip) { bits2addr(bits) }
213
+ end
214
+
215
+ #
216
+ # An array of octets of the IPv4 dotted decimal
217
+ # format
218
+ #
219
+ # prefix = IPAddress::Prefix32.new(24)
220
+ #
221
+ # prefix.octets
222
+ # #=> [255, 255, 255, 0]
223
+ #
224
+ def octets
225
+ lazy(:octets) { addr2ary(to_ip) }
226
+ end
227
+
228
+ #
229
+ # Shortcut for the octecs in the dotted decimal
230
+ # representation
231
+ #
232
+ # prefix = IPAddress::Prefix32.new(24)
233
+ #
234
+ # prefix[2]
235
+ # #=> 255
236
+ #
237
+ def [](index)
238
+ octets[index]
239
+ end
240
+
241
+ alias_method :octet, :[]
242
+
243
+ #
244
+ # The hostmask is the contrary of the subnet mask,
245
+ # as it shows the bits that can change within the
246
+ # hosts
247
+ #
248
+ # prefix = IPAddress::Prefix32.new(24)
249
+ #
250
+ # prefix.hostmask
251
+ # #=> "0.0.0.255"
252
+ #
253
+ def hostmask
254
+ lazy(:hostmask) { int2addr(~to_i) }
255
+ end
256
+
257
+ end
258
+
259
+ class Prefix128 < Prefix
260
+
261
+ MAX = 128
262
+
263
+ alias_method :to_u128, :to_i
264
+
265
+ end
266
+
267
+ MAX_PREFIX = Prefix128::MAX
268
+
269
+ end