ip 0.0.1
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.
- data/lib/ip.rb +232 -0
- metadata +39 -0
data/lib/ip.rb
ADDED
@@ -0,0 +1,232 @@
|
|
1
|
+
#
|
2
|
+
# IP - Collection of Tools to work with IP addresses
|
3
|
+
#
|
4
|
+
# Version:: 0.0.1
|
5
|
+
# Author:: Erik Hollensbe
|
6
|
+
# License:: BSD
|
7
|
+
# Contact:: erik@hollensbe.org
|
8
|
+
#
|
9
|
+
# IP is, as mentioned above, a collection of tools to work
|
10
|
+
# with IP addresses. There are three major classes included
|
11
|
+
# in the IP namespace, IP::Address, which works with standard
|
12
|
+
# dotted-quad IP addresses, IP::Range, which can calculate and return
|
13
|
+
# a range of IP::Address objects, and IP::CIDR, which can work with
|
14
|
+
# Classless Inter-Domain Routing address formats.
|
15
|
+
#
|
16
|
+
# The IP module uses long integers and bit-flipping per <netinet/in.h>
|
17
|
+
# to achieve fairly efficient performance, as opposed to a purely
|
18
|
+
# iterative approach. This is most true when calculating ranges and
|
19
|
+
# netmasks.
|
20
|
+
#
|
21
|
+
# Please see the documentation for each of these classes for usage
|
22
|
+
# information.
|
23
|
+
#
|
24
|
+
# Note: there is no IPv6 support as of current, but this is planned in
|
25
|
+
# perhaps a distant, future release. Any patches that can correct this
|
26
|
+
# issue are most welcome.
|
27
|
+
#
|
28
|
+
|
29
|
+
class IP
|
30
|
+
|
31
|
+
#
|
32
|
+
# A IP::AddressException is thrown when an IP address cannot be
|
33
|
+
# parsed.
|
34
|
+
#
|
35
|
+
|
36
|
+
class AddressException < Exception
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# A IP::BoundaryException is thrown when an index is being used out of
|
41
|
+
# it's pre-defined boundary. This is most relevant when using the []
|
42
|
+
# method in IP::Address.
|
43
|
+
#
|
44
|
+
|
45
|
+
class BoundaryException < Exception
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# IP::Range - Calculates a range of IP addresses, and returns an
|
50
|
+
# Array of IP::Address objects.
|
51
|
+
#
|
52
|
+
# Usage::
|
53
|
+
#
|
54
|
+
# IP::Range['10.0.0.1', '10.0.0.2'] => IP::Address objects between
|
55
|
+
# 10.0.0.1 and 10.0.0.2 (inclusive)
|
56
|
+
#
|
57
|
+
# IP::Range can also take two IP::Address objects.
|
58
|
+
#
|
59
|
+
# Will throw a IP::AddressException if for some reason addresses
|
60
|
+
# cannot be parsed.
|
61
|
+
#
|
62
|
+
|
63
|
+
class Range
|
64
|
+
|
65
|
+
#
|
66
|
+
# See the documentation for IP::Range for more information on this
|
67
|
+
# method.
|
68
|
+
#
|
69
|
+
|
70
|
+
def Range.[](addr1, addr2)
|
71
|
+
raw1, raw2 = [nil, nil]
|
72
|
+
|
73
|
+
if addr1.kind_of? String
|
74
|
+
raw1 = IP::Address.pack(IP::Address.new(addr1))
|
75
|
+
elsif addr1.kind_of? IP::Address
|
76
|
+
raw1 = IP::Address.pack(addr1)
|
77
|
+
else
|
78
|
+
raise IP::AddressException("IP Address is not type String or IP::Address")
|
79
|
+
end
|
80
|
+
|
81
|
+
if addr2.kind_of? String
|
82
|
+
raw2 = IP::Address.pack(IP::Address.new(addr2))
|
83
|
+
elsif addr2.kind_of? IP::Address
|
84
|
+
raw2 = IP::Address.pack(addr2)
|
85
|
+
else
|
86
|
+
raise IP::AddressException("IP Address is not type String or IP::Address")
|
87
|
+
end
|
88
|
+
|
89
|
+
range = []
|
90
|
+
|
91
|
+
(raw1..raw2).each { |x| range.push(IP::Address.unpack(x)) }
|
92
|
+
|
93
|
+
return range
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# IP::CIDR - Works with Classless Inter-Domain Routing formats, such
|
99
|
+
# as 10.0.0.1/32.
|
100
|
+
#
|
101
|
+
# Note: this class does not work with expanded RHS
|
102
|
+
# netmasks, such as 10.0.0.1/255.255.255.255. This is to be
|
103
|
+
# corrected in a later release.
|
104
|
+
#
|
105
|
+
|
106
|
+
class CIDR
|
107
|
+
#
|
108
|
+
# Contains the original CIDR you fed it, returned as a string.
|
109
|
+
#
|
110
|
+
attr_reader :cidr
|
111
|
+
#
|
112
|
+
# Contains the IP address (LHS) only. Returned as an IP::Address
|
113
|
+
# object.
|
114
|
+
#
|
115
|
+
attr_reader :ip
|
116
|
+
#
|
117
|
+
# Contains the integer-based netmask (RHS) only. Returned as an
|
118
|
+
# integer.
|
119
|
+
#
|
120
|
+
attr_reader :mask
|
121
|
+
|
122
|
+
#
|
123
|
+
# Given a string of format X.X.X.X/X, in standard CIDR notation,
|
124
|
+
# this will construct a IP::CIDR object.
|
125
|
+
#
|
126
|
+
def initialize(cidr)
|
127
|
+
if !cidr.kind_of? String
|
128
|
+
raise IP::AddressException("CIDR value is not of type String")
|
129
|
+
end
|
130
|
+
|
131
|
+
@cidr = cidr
|
132
|
+
@ip, @mask = cidr.split(/\//)
|
133
|
+
|
134
|
+
if @mask.length == 0 or @mask.length > 2 or /\D/.match @mask
|
135
|
+
raise IP::AddressException("CIDR RHS is not valid - #{@mask}")
|
136
|
+
end
|
137
|
+
|
138
|
+
@ip = IP::Address.new(@ip)
|
139
|
+
@mask = @mask.to_i
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
# This produces the netmask of the CIDR in an IP::Address object.
|
144
|
+
#
|
145
|
+
def netmask
|
146
|
+
raw = 0xFFFFFFFF << (32 - @mask)
|
147
|
+
return IP::Address.unpack(raw)
|
148
|
+
end
|
149
|
+
|
150
|
+
#
|
151
|
+
# This produces a range ala IP::Range, but only for the subnet
|
152
|
+
# defined by the CIDR object.
|
153
|
+
#
|
154
|
+
def range
|
155
|
+
rawip = IP::Address.pack(@ip)
|
156
|
+
rawnm = 0xFFFFFFFF << (32 - @mask)
|
157
|
+
upper = rawip | ~rawnm
|
158
|
+
return IP::Range[IP::Address.unpack(rawip), IP::Address.unpack(upper)]
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
#
|
164
|
+
# IP::Address - utility class to work with dotted-quad IP addresses.
|
165
|
+
#
|
166
|
+
class Address
|
167
|
+
#
|
168
|
+
# This original IP Address you passed it, returned as a string.
|
169
|
+
#
|
170
|
+
attr_reader :ip_address
|
171
|
+
#
|
172
|
+
# This returns an Array of Integer which contains the octets of
|
173
|
+
# the IP, in descending order.
|
174
|
+
#
|
175
|
+
attr_reader :octets
|
176
|
+
|
177
|
+
#
|
178
|
+
# When given a string, constructs an IP::Address object.
|
179
|
+
#
|
180
|
+
def initialize(ip_address)
|
181
|
+
if ! ip_address.kind_of? String
|
182
|
+
raise IP::AddressException("Fed IP address is not String")
|
183
|
+
end
|
184
|
+
@ip_address = ip_address
|
185
|
+
@octets = ip_address.split(/\./).collect { |x| x.to_i }
|
186
|
+
|
187
|
+
# I made a design decision to allow 0.0.0.0 here.
|
188
|
+
if @octets.length != 4 or @octets.find_all { |x| x > 255 }.length > 0
|
189
|
+
raise IP::AddressException.new("IP address is improperly formed")
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
#
|
194
|
+
# Returns an octet given the proper index. The octets returned are
|
195
|
+
# Integer types.
|
196
|
+
#
|
197
|
+
def [](num)
|
198
|
+
if num > 3
|
199
|
+
raise IP::BoundaryException.new("Max octet number is 3")
|
200
|
+
end
|
201
|
+
return @octets[num]
|
202
|
+
end
|
203
|
+
|
204
|
+
#
|
205
|
+
# See [].
|
206
|
+
#
|
207
|
+
alias_method :octet, :[]
|
208
|
+
|
209
|
+
#
|
210
|
+
# Class method to pack an IP::Address object into a long integer
|
211
|
+
# used for calculation. Returns a 'FixNum' type.
|
212
|
+
#
|
213
|
+
def Address.pack(ip)
|
214
|
+
ret = 0
|
215
|
+
myip = ip.octets.reverse
|
216
|
+
4.times { |x| ret = ret | (myip[x] & 0xFF) << 8*x }
|
217
|
+
return ret
|
218
|
+
end
|
219
|
+
|
220
|
+
#
|
221
|
+
# Class method to take a 'FixNum' type and return an IP::Address
|
222
|
+
# object.
|
223
|
+
#
|
224
|
+
def Address.unpack(ip)
|
225
|
+
ret = []
|
226
|
+
4.times { |x| ret.push((ip >> 8*x) & 0xFF) }
|
227
|
+
return IP::Address.new(ret.reverse.join("."))
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
metadata
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: ip
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2005-10-17 00:00:00 -07:00
|
8
|
+
summary: "Ruby classes to work with IP address, ranges, and netmasks"
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: erik@hollensbe.org
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: ip
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
29
|
+
authors:
|
30
|
+
- Erik Hollensbe
|
31
|
+
files:
|
32
|
+
- lib/ip.rb
|
33
|
+
test_files: []
|
34
|
+
rdoc_options: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
executables: []
|
37
|
+
extensions: []
|
38
|
+
requirements: []
|
39
|
+
dependencies: []
|