ip 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/ip.rb +232 -0
  2. metadata +39 -0
@@ -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: []