ipadmin 0.1.1 → 0.1.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.
data/README CHANGED
@@ -15,106 +15,140 @@
15
15
  =Examples:
16
16
 
17
17
 
18
+ #!/usr/bin/ruby
19
+
18
20
  require 'rubygems'
19
21
  require_gem 'ipadmin'
20
-
21
-
22
+
22
23
  #============================================================================#
23
24
  # IPAdmin::IPAddr
24
25
  #============================================================================#
25
26
  puts "IPAdmin::IPAddr"
26
-
27
- begin
28
- ip4 = IPAdmin::IPAddr.new(:IPAddr => '192.168.1.1/24')
29
- ip4 = IPAdmin::IPAddr.new(:IPAddr => '192.168.1.1',
30
- :Netmask => '255.255.255.0',
31
- :Tag => {'test' => 'ip4 tag'})
32
- ip6 = IPAdmin::IPAddr.new(:IPAddr => 'fec0::1/64')
33
- rescue Exception
34
- puts 'oops'
35
- exit
36
- end
37
-
27
+
28
+ # new
29
+ ip4 = IPAdmin::IPAddr.new(:IPAddr => '192.168.1.1/24')
30
+ ip4 = IPAdmin::IPAddr.new(:IPAddr => '192.168.1.1',
31
+ :Netmask => '255.255.255.0',
32
+ :Tag => {'test' => 'ip4 tag'})
33
+ ip6 = IPAdmin::IPAddr.new(:IPAddr => 'fec0::1/64')
34
+
35
+ # reader/writer
38
36
  puts ip4.tag['test']
39
37
  ip4.tag['test'] = 'modified ip4 tag'
40
38
  puts ip4.tag['test']
41
-
42
- puts "base addr #{ip4.base()}"
43
- puts "base addr #{ip6.base()}"
44
39
 
45
- puts "bcast addr #{ip4.broadcast()}"
40
+ # base
41
+ puts "ip4 base addr #{ip4.base()}"
42
+ puts "ip6 base addr #{ip6.base()}"
46
43
 
47
- puts "description #{ip4.desc()}"
48
- puts "description #{ip6.desc()}"
44
+ # broadcast
45
+ puts "ip4 bcast addr #{ip4.broadcast()}"
49
46
 
50
- puts "extended hostmask #{ip4.hostmask_ext()}"
51
- puts "extended netmask #{ip4.netmask_ext()}"
47
+ # desc
48
+ puts "ip4 description #{ip4.desc()}"
49
+ puts "ip6 description #{ip6.desc()}"
52
50
 
53
- puts "ip addr #{ip4.ip()}"
54
- puts "ip addr #{ip6.ip()}"
51
+ # extended masks
52
+ puts "ip4 extended hostmask #{ip4.hostmask_ext()}"
53
+ puts "ip6 extended netmask #{ip4.netmask_ext()}"
55
54
 
56
- puts "netmask in bits #{ip4.netmask()}"
57
- puts "netmask in bits #{ip6.netmask()}"
55
+ # ip
56
+ puts "ip4 ip addr #{ip4.ip()}"
57
+ puts "ip6 ip addr #{ip6.ip()}"
58
+
59
+ # netmask
60
+ puts "ip4 netmask in CIDR format #{ip4.netmask()}"
61
+ puts "ip6 netmask in CIDR format #{ip6.netmask()}"
62
+
63
+ # bits
64
+ puts "ip4 netmask in bits #{ip4.bits()}"
65
+ puts "ip6 netmask in bits #{ip6.bits()}"
58
66
 
59
67
  print "\n\n\n"
60
68
  #=====================================#
61
- #
69
+ #
62
70
  #=====================================#
63
71
 
64
-
65
72
  #============================================================================#
66
73
  # IPAdmin::CIDR
67
74
  #============================================================================#
68
75
  puts "IPAdmin::CIDR"
69
76
 
70
- begin
71
- cidr4 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0/24')
72
- cidr4 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0',
73
- :Netmask => '255.255.255.0',
74
- :Tag => {'test' => 'cidr4 tag'})
75
- cidr6 = IPAdmin::CIDR.new(:CIDR => 'fec0::0/64')
76
- rescue Exception
77
- puts 'oops'
78
- exit
79
- end
80
-
77
+ # new
78
+ cidr4 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0/24')
79
+ cidr4 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0',
80
+ :Netmask => '255.255.255.0',
81
+ :Tag => {'test' => 'cidr4 tag'})
82
+ cidr6 = IPAdmin::CIDR.new(:CIDR => 'fec0::0/64')
83
+
84
+ # attr reader/writer
81
85
  puts cidr4.tag['test']
82
86
  cidr4.tag['test'] = 'modified cidr4 tag'
83
87
  puts cidr4.tag['test']
84
88
 
85
- puts "cidr4 contains ip4" if ( cidr4.contains(ip4) )
86
- puts "cidr6 contains ip6" if ( cidr6.contains(ip6) )
87
-
88
- puts "description #{cidr4.desc()}"
89
- puts "description #{cidr6.desc()}"
90
-
91
- puts "extended hostmask #{cidr4.hostmask_ext()}"
92
- puts "extended netmask #{cidr4.netmask_ext()}"
93
-
94
- puts "netmask in bits #{cidr4.netmask()}"
95
- puts "netmask in bits #{cidr6.netmask()}"
96
-
97
- puts "network address #{cidr4.network()}"
98
- puts "network address #{cidr6.network()}"
99
-
100
- puts "1st ip is #{cidr4.nth(:Index => 1)}"
101
- puts "1st ip is #{(cidr6.nth(:Index => 1, :Objectify => 1)).desc}"
89
+ # contains
90
+ puts "#{cidr4.desc} contains #{ip4.desc}" if ( cidr4.contains(ip4) )
91
+ puts "#{cidr6.desc} contains #{ip6.desc}" if ( cidr6.contains(ip6) )
92
+
93
+ # desc
94
+ puts "cidr4 description #{cidr4.desc()}"
95
+ puts "cidr6 description #{cidr6.desc()}"
96
+
97
+ # extended masks
98
+ puts "cidr4 extended hostmask #{cidr4.hostmask_ext()}"
99
+ puts "cidr4 extended netmask #{cidr4.netmask_ext()}"
100
+
101
+ # netmask
102
+ puts "cidr4 netmask in CIDR format #{cidr4.netmask()}"
103
+ puts "cidr6 netmask in CIDR format #{cidr6.netmask()}"
102
104
 
105
+ # bits
106
+ puts "cidr4 netmask in bits #{cidr4.bits()}"
107
+ puts "cidr6 netmask in bits #{cidr6.bits()}"
108
+
109
+ # network
110
+ puts "cidr4 network address #{cidr4.network()}"
111
+ puts "cidr6 network address #{cidr6.network()}"
112
+
113
+ # nth
114
+ puts "cidr4 1st ip is #{cidr4.nth(:Index => 1)}"
115
+ puts "cidr6 1st ip is #{(cidr6.nth(:Index => 1, :Objectify => 1)).desc}"
116
+
117
+ # size
103
118
  puts "cidr4 size is #{cidr4.size()}"
104
119
  puts "cidr6 size is #{cidr6.size()}"
120
+
121
+ # enumerate
122
+ puts "first 4 cidr4 addresses (bitstep 32)"
123
+ list4 = cidr4.enumerate(:Limit => 4, :Bitstep => 32)
124
+ list4.each do |addr|
125
+ puts " #{addr}"
126
+ end
105
127
 
106
- cidr4.enumerate(:Limit => 4, :Bitstep => 32) {|addr| puts addr}
107
- cidr6.enumerate(:Limit => 4, :Bitstep => 32, :Objectify => 1) {|addr| puts addr.desc()}
128
+ puts "first 4 cidr6 addresses (bitstep 32)"
129
+ list6 = cidr6.enumerate(:Limit => 4, :Bitstep => 32, :Objectify => 1)
130
+ list6.each do |addr|
131
+ puts " #{addr.desc}"
132
+ end
108
133
 
109
- cidr4.subnet(:Subnet => 28, :MinCount => 3) {|cidr| puts cidr.desc()}
110
- cidr6.subnet(:Subnet => 66, :MinCount => 4) {|cidr| puts cidr.desc()}
134
+ # subnet
135
+ puts "cidr4 subnetted into at least 3 /28 ranges"
136
+ sn4 = cidr4.subnet(:Subnet => 28, :MinCount => 3)
137
+ sn4.each do |cidr|
138
+ puts " #{cidr.desc()}"
139
+ end
111
140
 
112
- print "\n\n\n"
141
+ puts "cidr6 subnetted into at least 4 /66 ranges"
142
+ sn6 = cidr6.subnet(:Subnet => 66, :MinCount => 4)
143
+ sn6.each do |cidr|
144
+ puts " #{cidr.desc()}"
145
+ end
146
+
147
+ print "\n\n\n"
113
148
  #=====================================#
114
- #
149
+ #
115
150
  #=====================================#
116
151
 
117
-
118
152
  #============================================================================#
119
153
  # IPAdmin::CIDRTable
120
154
  #============================================================================#
@@ -127,20 +161,17 @@
127
161
  cidr4_5 = IPAdmin::CIDR.new(:CIDR => '192.168.1.64/26')
128
162
  cidr4_6 = IPAdmin::CIDR.new(:CIDR => '192.168.1.128/26')
129
163
  cidr4_7 = IPAdmin::CIDR.new(:CIDR => '192.168.1.192/26')
130
-
164
+
131
165
  cidr6_1 = IPAdmin::CIDR.new(:CIDR => 'fec0::/10')
132
166
  cidr6_2 = IPAdmin::CIDR.new(:CIDR => 'fe80::/10')
133
167
  cidr6_3 = IPAdmin::CIDR.new(:CIDR => 'fec0::/64')
134
168
  cidr6_4 =IPAdmin::CIDR.new(:CIDR => 'fec0::/126')
135
-
136
- begin
137
- table4 = IPAdmin::CIDRTable.new(4)
138
- table6 = IPAdmin::CIDRTable.new(6)
139
- rescue Exception
140
- puts 'oops'
141
- exit
142
- end
143
-
169
+
170
+ # new
171
+ table4 = IPAdmin::CIDRTable.new(4)
172
+ table6 = IPAdmin::CIDRTable.new(6)
173
+
174
+ # add_cidr
144
175
  table4.add_cidr(cidr4_1)
145
176
  table4.add_cidr(cidr4_2)
146
177
  table4.add_cidr(cidr4_3)
@@ -148,92 +179,105 @@
148
179
  table4.add_cidr(cidr4_5)
149
180
  table4.add_cidr(cidr4_6)
150
181
  table4.add_cidr(cidr4_7)
151
-
182
+
152
183
  table6.add_cidr(cidr6_1)
153
184
  table6.add_cidr(cidr6_2)
154
185
  table6.add_cidr(cidr6_3)
155
186
  table6.add_cidr(cidr6_4)
156
187
 
157
- puts "ip4 belongs in #{table4.find_ip(ip4).desc}"
158
- puts "ip6 belongs in #{table6.find_ip(ip6).desc}"
159
-
188
+ # find_ip
189
+ puts "#{ip4.desc} belongs in #{table4.find_ip(ip4).desc}"
190
+ puts "#{ip6.desc} belongs in #{table6.find_ip(ip6).desc}"
191
+
192
+ # find_space
160
193
  puts "all blocks that can hold a /27"
161
194
  list4 = table4.find_space(:Size => 27)
162
195
  list4.each do |cidr|
163
196
  puts " #{cidr.desc()}"
164
197
  end
165
-
198
+
166
199
  puts "first block that can hold a /64"
167
200
  list6 = table6.find_space(:Size => 64, :Limit => 1)
168
201
  list6.each do |cidr|
169
202
  puts " #{cidr.desc()}"
170
203
  end
171
-
172
-
204
+
205
+ # dump
173
206
  puts 'dump table4...'
174
- dump4 = table4.dump
207
+ dump4 = table4.dump
175
208
  dump4.each do |cidr|
176
209
  puts " #{cidr.desc}"
177
210
  end
178
211
  puts 'dump table6...'
179
- dump6 = table6.dump
212
+ dump6 = table6.dump
180
213
  dump6.each do |cidr|
181
214
  puts " #{cidr.desc}"
182
215
  end
216
+
217
+ puts "remove 192.168.1.0/26 from table4"
218
+ table4.rem_cidr(cidr4_3)
219
+ dump4 = table4.dump
220
+ dump4.each do |cidr|
221
+ puts " #{cidr.desc}"
222
+ end
183
223
 
184
224
  print "\n\n\n"
185
225
  #=====================================#
186
- #
226
+ #
187
227
  #=====================================#
188
228
 
189
-
190
229
  #============================================================================#
191
- # IPAdmin Misc Methods
230
+ # IPAdmin Methods
192
231
  #============================================================================#
193
- puts "Misc Methods"
232
+ puts "IPAdmin Methods"
194
233
 
234
+ # validate ip
195
235
  puts "192.168.1.0 is valid" if ( IPAdmin.validate_ipv4_addr('192.168.1.0') )
196
236
  puts "192.168.1.0 is valid" if ( IPAdmin.validate_ipv6_addr('fec0::0') )
197
-
237
+
238
+ # validate netmask
198
239
  puts "255.255.255.0 is valid" if (IPAdmin.validate_ipv4_netmask('255.255.255.0') )
199
240
  puts "/24 is valid" if ( IPAdmin.validate_ipv4_netmask(24) )
200
241
  puts "/64 is valid" if ( IPAdmin.validate_ipv6_netmask(64) )
201
-
242
+
202
243
  cidr4_1 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0/24')
203
244
  cidr4_2 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0/25')
204
245
  cidr6_1 = IPAdmin::CIDR.new(:CIDR => 'fec0::0/10')
205
246
  cidr6_2 = IPAdmin::CIDR.new(:CIDR => 'fec0::0/64')
206
-
247
+
248
+ # compare_cidr
207
249
  comp1 = IPAdmin.compare_cidr(cidr4_1,cidr4_2)
208
250
  comp2 = IPAdmin.compare_cidr(cidr6_1,cidr6_2)
209
251
  puts "#{(comp1[0]).desc} is the supernet of #{(comp1[1]).desc}"
210
252
  puts "#{(comp2[0]).desc} is the supernet of #{(comp2[1]).desc}"
211
-
253
+
212
254
  cidr4_1 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0/24')
213
255
  cidr4_2 = IPAdmin::CIDR.new(:CIDR => '192.168.0.0/24')
214
256
  cidr6_1 = IPAdmin::CIDR.new(:CIDR => 'fec0::0/128')
215
257
  cidr6_2 = IPAdmin::CIDR.new(:CIDR => 'fec0::1/128')
216
-
258
+
259
+ # merge_cidr
217
260
  puts "192.168.1.0/24 and 192.168.0.0/24 merge into #{IPAdmin.merge_cidr([cidr4_1,cidr4_2]).desc}"
218
261
  puts "fec0::0/128 and fec0::1/128 merge into #{IPAdmin.merge_cidr([cidr6_1,cidr6_2]).desc}"
219
262
 
220
263
  ip1 = IPAdmin::IPAddr.new(:IPAddr => '192.168.1.0')
221
264
  ip2 = IPAdmin::IPAddr.new(:IPAddr => '192.168.1.50')
222
265
 
223
-
266
+ # range
224
267
  list = IPAdmin.range(:Boundaries => [ip1,ip2], :Bitstep => 20 )
225
- puts "ip's between #{ip1.desc} and #{ip2.desc}"
268
+ puts "ip's between #{ip1.desc} and #{ip2.desc} (bitstep of 20)"
226
269
  list.each do |x|
227
270
  puts " #{x}"
228
271
  end
229
272
 
273
+ # make_arpa
274
+ puts "arpa for #{cidr4_1.desc()} is #{IPAdmin.make_arpa(cidr4_1)}"
275
+ puts "arpa for #{cidr6_1.desc()} is #{IPAdmin.make_arpa(cidr6_1)}"
230
276
 
277
+ # v6_short
278
+ puts "shorthand notation for #{cidr6_1.network()} is #{IPAdmin.v6_short(cidr6_1.network)}"
279
+
231
280
  print "\n\n\n"
232
281
  #=====================================#
233
- #
282
+ #
234
283
  #=====================================#
235
-
236
-
237
-
238
-
239
-
@@ -9,18 +9,23 @@ module IPAdmin
9
9
  # Compare cidr addresses of two IPAdmin::CIDR objects.
10
10
  # - Arguments:
11
11
  # * Two IPAdmin::CIDR objects
12
- #
12
+ #
13
13
  # - Returns:
14
14
  # * if one object is a subnet of another, then return an array in order of
15
15
  # [supernet,subnet]
16
16
  # * if both are equal, return 1
17
17
  # * if neither is a subnet of the other, return nil
18
18
  #
19
+ # Example:
20
+ # supernet,subnet = IPAdmin.compare_cidr(cidr1,cidr2)
21
+ # puts "#{supernet.desc} is the supernet of #{subnet.desc}"
22
+ #
23
+
19
24
  def compare_cidr(cidr1,cidr2)
20
25
 
21
26
  # we only accept CIDR objects
22
27
  unless ( (cidr1.kind_of? IPAdmin::CIDR)&&(cidr2.kind_of? IPAdmin::CIDR) )
23
- raise "Expected IPAdmin::CIDR, but #{options.class} provided."
28
+ raise ArgumentError, "Arguments shouldbe of type IPAdmin::CIDR."
24
29
  end
25
30
 
26
31
  # make sure both are same version
@@ -74,6 +79,84 @@ module_function :compare_cidr
74
79
 
75
80
 
76
81
 
82
+ #============================================================================#
83
+ # make_arpa()
84
+ #============================================================================#
85
+
86
+ # Given the address in the provided IPAdmin::IPAddr or IPAdmin::CIDR object,
87
+ # return either an in-addr.arpa. or ip6.arpa string. If an IPAdmin::CIDR
88
+ # object is provided, then its netmask will be used to determine the length
89
+ # of the returned arpa string.
90
+ #
91
+ # - Arguments:
92
+ # * IPAdmin::CIDR or IPAdmin::IPAddr object
93
+ #
94
+ # - Returns:
95
+ # * IP/CIDR address in in-addr.arpa or ip6.arpa format
96
+ #
97
+ # Example:
98
+ # arpa = IPAdmin.make_arpa(cidr)
99
+ #
100
+ def make_arpa(object)
101
+
102
+ if (object.kind_of? IPAdmin::CIDR)
103
+ base = object.network()
104
+ netmask = object.bits()
105
+
106
+ elsif (object.kind_of? IPAdmin::IPAddr)
107
+ base = object.ip()
108
+
109
+ else
110
+ raise ArgumentError, "Expected IPAdmin::CIDR or IPAdmin::IPAddr object, " +
111
+ "but #{object.class} provided."
112
+ end
113
+
114
+
115
+ if (object.version == 4)
116
+ net = base.split('.')
117
+
118
+ if (netmask)
119
+ while (netmask < 32)
120
+ net.pop
121
+ netmask = netmask + 8
122
+ end
123
+ end
124
+
125
+ arpa = net.reverse.join('.')
126
+ arpa << ".in-addr.arpa."
127
+
128
+ else
129
+ fields = base.split(':')
130
+ net = []
131
+ fields.each do |field|
132
+ (field.split("")).each do |x|
133
+ net.push(x)
134
+ end
135
+ end
136
+
137
+ if (netmask)
138
+ while (netmask < 128)
139
+ net.pop
140
+ netmask = netmask + 4
141
+ end
142
+ end
143
+
144
+ arpa = net.reverse.join('.')
145
+ arpa << ".ip6.arpa."
146
+
147
+ end
148
+
149
+ return(arpa)
150
+
151
+ end
152
+ module_function :make_arpa
153
+
154
+ #=====================================#
155
+ #
156
+ #=====================================#
157
+
158
+
159
+
77
160
  #============================================================================#
78
161
  # merge_cidr()
79
162
  #============================================================================#
@@ -87,11 +170,14 @@ module_function :compare_cidr
87
170
  # - Returns:
88
171
  # * IPAdmin::CIDR object
89
172
  #
173
+ # Example:
174
+ # merged = IPAdmin.merge_cidr([cidr1,cidr2])
175
+ #
90
176
  def merge_cidr(cidr_list)
91
177
 
92
178
  # make sure we have an array with at least 2 objects
93
179
  unless ( (cidr_list.kind_of? Array) && (cidr_list.length > 1) )
94
- raise "Array of at least two IPAdmin::CIDR objects required."
180
+ raise ArgumentError, "Array of at least two IPAdmin::CIDR objects required."
95
181
  end
96
182
 
97
183
 
@@ -99,7 +185,7 @@ def merge_cidr(cidr_list)
99
185
  version = {}
100
186
  cidr_list.each do |cidr|
101
187
  unless (cidr.kind_of? IPAdmin::CIDR)
102
- raise "Expected IPAdmin::CIDR, but #{options.class} provided."
188
+ raise ArgumentError, "Expected IPAdmin::CIDR, but #{cidr.class} provided."
103
189
  end
104
190
  version[cidr.version] = 1
105
191
  end
@@ -193,12 +279,15 @@ module_function :merge_cidr
193
279
  #
194
280
  # - Returns:
195
281
  # * packed IPv4 address or exception on error.
282
+ #
283
+ # Example:
284
+ # packed = IPAdmin.pack_ipv4_addr('192.168.1.1')
196
285
  #
197
286
  def pack_ipv4_addr(ip)
198
287
 
199
288
  # is this a string?
200
289
  unless (ip.kind_of? String)
201
- raise "Expected String, but #{ip.class} provided."
290
+ raise ArgumentError, "Expected String, but #{ip.class} provided."
202
291
  end
203
292
 
204
293
  # pack our ip
@@ -227,7 +316,7 @@ module_function :pack_ipv4_addr
227
316
  # pack_ipv4_netmask()
228
317
  #============================================================================#
229
318
 
230
- # Pack IPv4 netmask into a single byte field. No attempt at validation
319
+ # Pack IPv4 netmask into a single byte field. Only very basic validation
231
320
  # is performed.
232
321
  # - Arguments:
233
322
  # * IPv4 netmask in cidr or extended notation
@@ -235,6 +324,10 @@ module_function :pack_ipv4_addr
235
324
  # - Returns:
236
325
  # * packed IPv4 netmask or exception on error.
237
326
  #
327
+ # Example:
328
+ # packed = IPAdmin.pack_ipv4_netmask('255.255.255.0')
329
+ # packed = IPAdmin.pack_ipv4_netmask('24')
330
+ #
238
331
  def pack_ipv4_netmask(netmask)
239
332
 
240
333
  all_f = 2**32-1
@@ -247,10 +340,21 @@ def pack_ipv4_netmask(netmask)
247
340
  packed_netmask = pack_ipv4_addr(netmask)
248
341
  packed_hostmask = packed_netmask ^ all_f
249
342
  rescue Exception
250
- raise "#{netmask} is invalid."
343
+ raise "#{netmask} is not a valid IPv4 netmask."
251
344
  end
252
345
 
253
- elsif (netmask !~ /\D/)
346
+ else
347
+ # remove '/' if present
348
+ if (netmask =~ /^\// )
349
+ netmask[0] = " "
350
+ netmask.lstrip!
351
+ end
352
+
353
+ # check if we have any non numeric characters
354
+ if (netmask =~ /\D/)
355
+ raise "#{netmask} is not a valid IPv4 netmask."
356
+ end
357
+
254
358
  if (netmask.kind_of? String)
255
359
  netmask = netmask.to_i
256
360
  end
@@ -258,9 +362,6 @@ def pack_ipv4_netmask(netmask)
258
362
  packed_hostmask = all_f >> netmask
259
363
  packed_netmask = all_f ^ packed_hostmask
260
364
 
261
- else
262
- raise "#{netmask} is unrecognized."
263
-
264
365
  end
265
366
 
266
367
  ret_vals = [packed_netmask,packed_hostmask]
@@ -287,11 +388,14 @@ module_function :pack_ipv4_netmask
287
388
  # - Returns:
288
389
  # * packed IPv6 address or exception on error.
289
390
  #
391
+ # Example:
392
+ # packed = IPAdmin.pack_ipv4_netmask('fec0::0001')
393
+ #
290
394
  def pack_ipv6_addr(ip)
291
395
 
292
396
  # is this a string?
293
397
  unless (ip.kind_of? String)
294
- raise "Expected String, but #{ip.class} provided."
398
+ raise ArgumentError, "Expected String, but #{ip.class} provided."
295
399
  end
296
400
 
297
401
 
@@ -351,7 +455,7 @@ module_function :pack_ipv6_addr
351
455
  # pack_ipv6_netmask()
352
456
  #============================================================================#
353
457
 
354
- # Pack IPv6 netmask into a single byte field. No attempt at validation
458
+ # Pack IPv6 netmask into a single byte field. Only very basic validation
355
459
  # is performed.
356
460
  # - Arguments:
357
461
  # * IPv6 netmask in cidr notation
@@ -359,10 +463,18 @@ module_function :pack_ipv6_addr
359
463
  # - Returns:
360
464
  # * packed IPv6 netmask or exception on error.
361
465
  #
466
+ # Example:
467
+ # packed = IPAdmin.pack_ipv4_netmask('64')
468
+ #
362
469
  def pack_ipv6_netmask(netmask)
363
470
 
364
471
  all_f = 2**128-1
365
472
 
473
+ # remove '/' if present
474
+ if (netmask =~ /^\// )
475
+ netmask[0] = " "
476
+ netmask.lstrip!
477
+ end
366
478
 
367
479
  if (netmask !~ /\D/)
368
480
  # pack
@@ -374,7 +486,7 @@ def pack_ipv6_netmask(netmask)
374
486
  packed_netmask = all_f ^ packed_hostmask
375
487
 
376
488
  else
377
- raise "#{netmask} is unrecognized."
489
+ raise "#{netmask} is not a valid IPv6 netmask."
378
490
 
379
491
  end
380
492
 
@@ -401,14 +513,17 @@ module_function :pack_ipv6_netmask
401
513
  #
402
514
  # - Arguments:
403
515
  # * Hash with the following fields
404
- # - :Bitstep -- enumerate in X sized steps
405
- # - :Boundaries -- array of (2) IPAdmin::IPAddr objects
406
- # - :Limit -- limit returned list to X number of items
407
- # - :Objectify -- return IPAdmin::IPAddr objects
516
+ # - :Bitstep -- enumerate in X sized steps
517
+ # - :Boundaries -- array of (2) IPAdmin::IPAddr objects
518
+ # - :Limit -- limit returned list to X number of items
519
+ # - :Objectify -- return IPAdmin::IPAddr objects
408
520
  #
409
521
  # - Returns:
410
522
  # * array of IP addresses or IPAdmin::IPAddr objects
411
523
  #
524
+ # Example:
525
+ # list = IPAdmin.range(:Boundaries => [ip1,ip2])
526
+ #
412
527
  def range(options)
413
528
  list = []
414
529
  bitstep = 1
@@ -537,6 +652,9 @@ module_function :range
537
652
  # - Returns:
538
653
  # * IPv4 address.
539
654
  #
655
+ # Example:
656
+ # unpacked = IPAdmin.unpack_ipv4_addr(packed)
657
+ #
540
658
  def unpack_ipv4_addr(packed_ip)
541
659
 
542
660
  octets = []
@@ -571,6 +689,9 @@ module_function :unpack_ipv4_addr
571
689
  # - Returns:
572
690
  # * IPv4 netmask as number of bits (cidr format).
573
691
  #
692
+ # Example:
693
+ # unpacked = IPAdmin.unpack_ipv4_netmask(packed)
694
+ #
574
695
  def unpack_ipv4_netmask(packed_mask)
575
696
 
576
697
  mask = 32
@@ -604,6 +725,9 @@ module_function :unpack_ipv4_netmask
604
725
  # - Returns:
605
726
  # * IPv6 address.
606
727
  #
728
+ # Example:
729
+ # unpacked = IPAdmin.unpack_ipv6_addr(packed)
730
+ #
607
731
  def unpack_ipv6_addr(packed_ip)
608
732
  hex_fields = []
609
733
  (0..7).each do |x|
@@ -642,6 +766,9 @@ module_function :unpack_ipv6_addr
642
766
  # - Returns:
643
767
  # * IPv6 netmask as number of bits (cidr format).
644
768
  #
769
+ # Example:
770
+ # unpacked = IPAdmin.unpack_ipv6_netmask(packed)
771
+ #
645
772
  def unpack_ipv6_netmask(packed_mask)
646
773
 
647
774
  mask = 128
@@ -663,22 +790,104 @@ module_function :unpack_ipv6_netmask
663
790
 
664
791
 
665
792
 
793
+ #============================================================================#
794
+ # v6_short()
795
+ #============================================================================#
796
+
797
+ # Take a standard IPv6 address, and format it in short-hand notation.
798
+ # Address should not contain a netmask.
799
+ # - Arguments:
800
+ # * IPv6 address
801
+ #
802
+ # - Returns:
803
+ # * IPv6 short-hand address.
804
+ #
805
+ # Example:
806
+ # short = IPAdmin.v6_short('fec0:0000:0000:0000:0000:0000:0000:0001')
807
+ #
808
+ def v6_short(addr)
809
+
810
+ # is this a string?
811
+ unless (addr.kind_of? String)
812
+ raise ArgumentError, "Expected String, but #{addr.class} provided."
813
+ end
814
+
815
+ validate_ipv6_addr(addr)
816
+
817
+ # make sure this isnt already shorthand
818
+ if (addr =~ /::/)
819
+ raise "#{addr} already appears to be in IPv6 shorthand notation."
820
+ end
821
+
822
+
823
+ # look for most 0 fields
824
+ found_zero = nil
825
+ pattern = ""
826
+ zero_fields = []
827
+ fields = addr.split(":")
828
+
829
+ (0..(fields.length-1)).each do |x|
830
+ fields[x] = fields[x].to_i(16)
831
+
832
+ if (fields[x] == 0)
833
+ if (!found_zero)
834
+ found_zero = 1
835
+ end
836
+ pattern << ":0"
837
+ else
838
+ if (found_zero)
839
+ found_zero = nil
840
+ pattern << ":"
841
+ zero_fields.push(pattern)
842
+ pattern = ""
843
+ end
844
+ end
845
+
846
+ fields[x] = fields[x].to_s(16)
847
+ end
848
+
849
+
850
+ # pattern should be the longest set of 0's in a row
851
+ zero_fields.push(pattern) if (pattern != "")
852
+ pattern = ""
853
+ zero_fields.each do |x|
854
+ pattern = x if (x.length > pattern.length)
855
+ end
856
+
857
+
858
+
859
+ short = fields.join(":")
860
+ short.sub!(pattern,"::")
861
+
862
+ return(short)
863
+ end
864
+ module_function :v6_short
865
+
866
+ #=====================================#
867
+ #
868
+ #=====================================#
869
+
870
+
871
+
666
872
  #============================================================================#
667
873
  # validate_ipv4_addr()
668
874
  #============================================================================#
669
875
 
670
- # Validate IPv4 addresses.
876
+ # Validate IPv4 addresses. Address should not contain a netmask.
671
877
  # - Arguments:
672
878
  # * IPv4 address
673
879
  #
674
880
  # - Returns:
675
881
  # * 1 on valid IP or exception on error.
676
882
  #
883
+ # Example:
884
+ # IPAdmin.validate_ipv4_addr('192.168.1.1')
885
+ #
677
886
  def validate_ipv4_addr(ip)
678
887
 
679
888
  # is this a string?
680
889
  unless (ip.kind_of? String)
681
- raise "Expected String, but #{ip.class} provided."
890
+ raise ArgumentError, "Expected String, but #{ip.class} provided."
682
891
  end
683
892
  octets = ip.split( /\./ )
684
893
 
@@ -686,14 +895,14 @@ def validate_ipv4_addr(ip)
686
895
 
687
896
  # check validity of characters in the addr
688
897
  if ( (ip =~ /\.{2,}?/ ) || (ip =~ /[^0-9\.]/) )
689
- raise "#{ip} is invalid."
898
+ raise "#{ip} is not a valid IPv4 address."
690
899
  end
691
900
 
692
901
 
693
902
 
694
903
  # do we have 4 octets?
695
904
  if (octets.length != 4)
696
- raise "#{ip} is invalid."
905
+ raise "#{ip} is not a valid IPv4 address."
697
906
  end
698
907
 
699
908
 
@@ -702,14 +911,14 @@ def validate_ipv4_addr(ip)
702
911
  (0..3).each do |x|
703
912
  octets[x] = octets[x].to_i
704
913
  unless ( (octets[x] >= 0) && (octets[x] < 256 ) )
705
- raise "#{ip} is invalid."
914
+ raise "#{ip} is not a valid IPv4 address."
706
915
  end
707
916
  end
708
917
 
709
918
 
710
919
  # dont allow first octet to be 0
711
920
  if (octets[0] == 0)
712
- raise "#{ip} is invalid."
921
+ raise "#{ip} is not a valid IPv4 address."
713
922
  end
714
923
 
715
924
  return(1)
@@ -734,6 +943,12 @@ module_function :validate_ipv4_addr
734
943
  # - Returns:
735
944
  # * 1 on valid IP or exception on error.
736
945
  #
946
+ # Example:
947
+ # IPAdmin.validate_ipv4_netmask('255.255.255.0')
948
+ # IPAdmin.validate_ipv4_netmask('24')
949
+ # IPAdmin.validate_ipv4_netmask('/24')
950
+ # IPAdmin.validate_ipv4_netmask(24)
951
+ #
737
952
  def validate_ipv4_netmask(netmask)
738
953
 
739
954
  all_f = (2**32)-1
@@ -747,7 +962,7 @@ def validate_ipv4_netmask(netmask)
747
962
  packed_mask = pack_ipv4_addr(netmask)
748
963
 
749
964
  rescue Exception
750
- raise "#{netmask} is invalid."
965
+ raise "#{netmask} is not a valid IPv4 netmask."
751
966
  end
752
967
 
753
968
  # cycle through the bits of hostmask and compare
@@ -762,7 +977,7 @@ def validate_ipv4_netmask(netmask)
762
977
  if ( check != 0)
763
978
  hostmask = hostmask >> 1
764
979
  unless ( (packed_mask ^ hostmask) == all_f)
765
- raise "#{netmask} is invalid."
980
+ raise "#{netmask} is not a valid IPv4 netmask."
766
981
  end
767
982
  break
768
983
  else
@@ -773,9 +988,15 @@ def validate_ipv4_netmask(netmask)
773
988
 
774
989
  else
775
990
 
991
+ # remove '/' if present
992
+ if (netmask =~ /^\// )
993
+ netmask[0] = " "
994
+ netmask.lstrip!
995
+ end
996
+
776
997
  # check if we have any non numeric characters
777
998
  if (netmask =~ /\D/)
778
- raise "#{netmask} is invalid."
999
+ raise "#{netmask} is not a valid IPv4 netmask."
779
1000
  end
780
1001
 
781
1002
 
@@ -785,7 +1006,7 @@ def validate_ipv4_netmask(netmask)
785
1006
  end
786
1007
 
787
1008
  if ( (netmask > 32) || (netmask == 0) )
788
- raise "#{netmask} is invalid."
1009
+ raise "#{netmask} is not a valid IPv4 netmask."
789
1010
  end
790
1011
 
791
1012
  end
@@ -805,24 +1026,27 @@ module_function :validate_ipv4_netmask
805
1026
  # validate_ipv6_addr()
806
1027
  #============================================================================#
807
1028
 
808
- # Validate IPv6 addresses.
1029
+ # Validate IPv6 addresses. Address should not contain a netmask.
809
1030
  # - Arguments:
810
1031
  # * IPv6 address
811
1032
  #
812
1033
  # - Returns:
813
1034
  # * 1 on valid IP or exception on error.
814
1035
  #
1036
+ # Example:
1037
+ # IPAdmin.validate_ipv6_addr('fec0::')
1038
+ #
815
1039
  def validate_ipv6_addr(ip)
816
1040
  # is this a string?
817
1041
  unless (ip.kind_of? String)
818
- raise "Expected String, but #{ip.class} provided."
1042
+ raise ArgumentError, "Expected String, but #{ip.class} provided."
819
1043
  end
820
1044
 
821
1045
 
822
1046
 
823
1047
  # check validity of characters in the addr
824
1048
  if ( (ip =~ /:{3,}?/ ) || (ip =~ /[^0-9a-fA-F:]/) )
825
- raise "#{ip} is invalid."
1049
+ raise "#{ip} is not a valid IPv6 address."
826
1050
  end
827
1051
 
828
1052
 
@@ -833,7 +1057,7 @@ def validate_ipv6_addr(ip)
833
1057
  if (ip =~ /::/)
834
1058
  shrthnd = ip.split( /::/ )
835
1059
  unless ( (shrthnd.length > 0) && (shrthnd.length < 3) )
836
- raise "#{ip} is invalid."
1060
+ raise "#{ip} is not a valid IPv6 address."
837
1061
  end
838
1062
  end
839
1063
 
@@ -848,7 +1072,7 @@ def validate_ipv6_addr(ip)
848
1072
  elements.each {|x| hex_fields.push(x)}
849
1073
  end
850
1074
  if ( (hex_fields.length < 1) || (hex_fields.length > 7) )
851
- raise "#{ip} is invalid."
1075
+ raise "#{ip} is not a valid IPv6 address."
852
1076
  end
853
1077
 
854
1078
  else
@@ -856,7 +1080,7 @@ def validate_ipv6_addr(ip)
856
1080
  # have exactly 8 hex fields
857
1081
  hex_fields = ip.split( /:/ )
858
1082
  if (hex_fields.length != 8)
859
- raise "#{ip} is invalid."
1083
+ raise "#{ip} is not a valid IPv6 address."
860
1084
  end
861
1085
 
862
1086
  end
@@ -867,7 +1091,7 @@ def validate_ipv6_addr(ip)
867
1091
  # hex field
868
1092
  hex_fields.each do |x|
869
1093
  if (x.length > 4)
870
- raise "#{ip} is invalid."
1094
+ raise "#{ip} is not a valid IPv6 address."
871
1095
  end
872
1096
  end
873
1097
 
@@ -893,11 +1117,22 @@ module_function :validate_ipv6_addr
893
1117
  #
894
1118
  # - Returns:
895
1119
  # * 1 on valid IP or exception on error.
1120
+ #
1121
+ # Example:
1122
+ # IPAdmin.validate_ipv6_netmask('64')
1123
+ # IPAdmin.validate_ipv6_netmask('/64')
1124
+ # IPAdmin.validate_ipv6_netmask(64)
896
1125
  #
897
1126
  def validate_ipv6_netmask(netmask)
898
1127
 
1128
+ # remove '/' if present
1129
+ if (netmask =~ /^\// )
1130
+ netmask[0] = " "
1131
+ netmask.lstrip!
1132
+ end
1133
+
899
1134
  if (netmask =~ /\D/)
900
- raise "#{netmask} is invalid."
1135
+ raise "#{netmask} is not a valid IPv6 netmask."
901
1136
 
902
1137
  else
903
1138
  # are we between 1 and 128 inclusive
@@ -906,7 +1141,7 @@ def validate_ipv6_netmask(netmask)
906
1141
  end
907
1142
 
908
1143
  if ( (netmask > 128) || (netmask == 0) )
909
- raise "#{netmask} is invalid."
1144
+ raise "#{netmask} is not a valid IPv6 netmask."
910
1145
  end
911
1146
 
912
1147
  end
@@ -942,17 +1177,20 @@ class CIDR
942
1177
  #============================================================================#
943
1178
  # attr_reader/attr_writer
944
1179
  #============================================================================#
945
-
946
- # @network - packed cidr network
947
- # @netmask - packet cidr netmask
948
- # @hostmask - inverse packed netmask
949
1180
 
950
1181
  # ip version 4 or 6
951
1182
  attr_reader :version
952
1183
 
953
1184
  # hash of custom tags. should be in the format tag => value
954
1185
  attr_reader :tag
955
- attr_writer :tag
1186
+
1187
+ # attr_writer - hash of custom tags. should be in the format tag => value
1188
+ def tag=(new_tag)
1189
+ unless (new_tag.kind_of? Hash)
1190
+ raise ArgumentError, "Expected Hash, but #{new_tag.class} provided."
1191
+ end
1192
+ @tag = new_tag
1193
+ end
956
1194
 
957
1195
  #=====================================#
958
1196
  #
@@ -966,14 +1204,21 @@ class CIDR
966
1204
 
967
1205
  # - Arguments:
968
1206
  # * Hash with the following fields:
969
- # :CIDR -- IPv4 or IPv6 cidr block
970
- # :Netmask -- IPv4 netmask in extended format (if not provided in :CIDR)
971
- # :Tag -- Custom descriptor tag for object. Should be Hash (tag => value)
1207
+ # - :CIDR -- IPv4 or IPv6 cidr block
1208
+ # - :Netmask -- IPv4 netmask in extended format (if not provided in :CIDR)
1209
+ # - :Tag -- Custom descriptor tag for object. Should be Hash (tag => value)
1210
+ #
1211
+ # Example:
1212
+ # cidr4 = IPAdmin::CIDR.new(:CIDR => '192.168.1.0',
1213
+ # :Netmask => '255.255.255.0')
1214
+ # cidr6 = IPAdmin::CIDR.new(:CIDR => 'fec0::/64',
1215
+ # :Tag => {'interface' => 'g0/1'})
1216
+ #
972
1217
  #
973
1218
  def initialize(options)
974
1219
 
975
1220
  unless (options.kind_of? Hash)
976
- raise "Expected Hash, but #{options.class} provided."
1221
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
977
1222
  end
978
1223
 
979
1224
 
@@ -1051,8 +1296,11 @@ class CIDR
1051
1296
 
1052
1297
 
1053
1298
  # set tag if present
1054
- if ( options.has_key?(:Tag) )
1299
+ if ( options.has_key?(:Tag) )
1055
1300
  @tag = options[:Tag]
1301
+ unless (@tag.kind_of? Hash)
1302
+ raise "Expected Hash, but #{@tag.class} provided for option :Tag."
1303
+ end
1056
1304
  end
1057
1305
 
1058
1306
 
@@ -1064,6 +1312,37 @@ class CIDR
1064
1312
 
1065
1313
 
1066
1314
 
1315
+ #============================================================================#
1316
+ # bits()
1317
+ #============================================================================#
1318
+
1319
+ # Provide number of bits of Netmask.
1320
+ #
1321
+ # - Arguments:
1322
+ # * none
1323
+ #
1324
+ # - Returns:
1325
+ # * Number of bits of Netmask.
1326
+ #
1327
+ # Example:
1328
+ # bits = cidr.bits()
1329
+ #
1330
+ def bits()
1331
+ if (@version == 4)
1332
+ bits = IPAdmin.unpack_ipv4_netmask(@netmask)
1333
+ else
1334
+ bits = IPAdmin.unpack_ipv6_netmask(@netmask)
1335
+ end
1336
+
1337
+ return(bits)
1338
+ end
1339
+
1340
+ #=====================================#
1341
+ #
1342
+ #=====================================#
1343
+
1344
+
1345
+
1067
1346
  #============================================================================#
1068
1347
  # contains()
1069
1348
  #============================================================================#
@@ -1075,9 +1354,16 @@ class CIDR
1075
1354
  #
1076
1355
  # - Returns:
1077
1356
  # * 1 on true, nil on false
1357
+ #
1358
+ # Example:
1359
+ # contains = cidr.contains(ip)
1078
1360
  #
1079
1361
  def contains(ip_obj)
1080
1362
 
1363
+ unless (ip_obj.kind_of? IPAdmin::IPAddr)
1364
+ raise ArgumentError, "Expected IPAdmin::IPAddr object, but #{ip_obj.class} provided."
1365
+ end
1366
+
1081
1367
  if ( (ip_obj.version == 4) && (@version == 4) )
1082
1368
  v4_all_f = (2**32)-1
1083
1369
  hostmask = @netmask ^ v4_all_f
@@ -1117,6 +1403,9 @@ class CIDR
1117
1403
  #
1118
1404
  # - Returns:
1119
1405
  # * Description in network/netmask format
1406
+ #
1407
+ # Example:
1408
+ # desc = cidr.desc()
1120
1409
  #
1121
1410
  def desc()
1122
1411
 
@@ -1147,12 +1436,15 @@ class CIDR
1147
1436
  #
1148
1437
  # - Arguments:
1149
1438
  # * Hash with the following fields
1150
- # - :Bitstep -- enumerate in X sized steps
1151
- # - :Objectify -- return IPAdmin::IPAddr objects
1152
- # - :Limit -- limit returned list to X number of items
1439
+ # - :Bitstep -- enumerate in X sized steps
1440
+ # - :Objectify -- return IPAdmin::IPAddr objects
1441
+ # - :Limit -- limit returned list to X number of items
1153
1442
  #
1154
1443
  # - Returns:
1155
1444
  # * array of IP addresses or IPAdmin::IPAddr objects
1445
+ #
1446
+ # Example:
1447
+ # ip_list = cidr.enumerate(:Bitstep => 2)
1156
1448
  #
1157
1449
  def enumerate(options=nil)
1158
1450
  bitstep = 1
@@ -1265,6 +1557,9 @@ class CIDR
1265
1557
  #
1266
1558
  # - Returns:
1267
1559
  # * Hostmask in extended (y.y.y.y) format.
1560
+ #
1561
+ # Example:
1562
+ # hostmask = cidr.hostmask_ext()
1268
1563
  #
1269
1564
  def hostmask_ext()
1270
1565
  if (@version == 4)
@@ -1292,7 +1587,10 @@ class CIDR
1292
1587
  # * none
1293
1588
  #
1294
1589
  # - Returns:
1295
- # * Number of bits in the netmask.
1590
+ # * Netmask in CIDR format.
1591
+ #
1592
+ # Example:
1593
+ # netmask = cidr.netmask()
1296
1594
  #
1297
1595
  def netmask()
1298
1596
  if (@version == 4)
@@ -1301,7 +1599,7 @@ class CIDR
1301
1599
  bits = IPAdmin.unpack_ipv6_netmask(@netmask)
1302
1600
  end
1303
1601
 
1304
- return(bits)
1602
+ return("/#{bits}")
1305
1603
  end
1306
1604
 
1307
1605
  #=====================================#
@@ -1321,13 +1619,16 @@ class CIDR
1321
1619
  #
1322
1620
  # - Returns:
1323
1621
  # * Netmask in extended (y.y.y.y) format.
1622
+ #
1623
+ # Example:
1624
+ # netmask = cidr.netmask_ext()
1324
1625
  #
1325
1626
  def netmask_ext()
1326
1627
  if (@version == 4)
1327
1628
  netmask = IPAdmin.unpack_ipv4_addr(@netmask)
1328
1629
  else
1329
1630
  raise "IPv6 does not support extended netmask notation. " +
1330
- "Use bits() method instead."
1631
+ "Use netmask() method instead."
1331
1632
  end
1332
1633
 
1333
1634
  return(netmask)
@@ -1350,6 +1651,9 @@ class CIDR
1350
1651
  #
1351
1652
  # - Returns:
1352
1653
  # * Base network address.
1654
+ #
1655
+ # Example:
1656
+ # network = cidr.network()
1353
1657
  #
1354
1658
  def network()
1355
1659
  if (@version == 4)
@@ -1375,11 +1679,14 @@ class CIDR
1375
1679
  #
1376
1680
  # - Arguments:
1377
1681
  # * Hash with the following fields
1378
- # - :Index -- index of the address to return
1379
- # - :Objectify -- return IPAdmin::IPAddr objects
1682
+ # - :Index -- index number of the IP address to return
1683
+ # - :Objectify -- return IPAdmin::IPAddr objects
1380
1684
  #
1381
1685
  # - Returns:
1382
1686
  # * IP address or IPAdmin::IPAddr object.
1687
+ #
1688
+ # Example:
1689
+ # first_ip = cidr.nth(:Index => 1)
1383
1690
  #
1384
1691
  def nth(options)
1385
1692
  objectify = nil
@@ -1458,6 +1765,9 @@ class CIDR
1458
1765
  #
1459
1766
  # - Returns:
1460
1767
  # * Byte-packed Hostmask.
1768
+ #
1769
+ # Example:
1770
+ # packed = cidr.packed_hostmask()
1461
1771
  #
1462
1772
  def packed_hostmask()
1463
1773
  return(@hostmask)
@@ -1480,6 +1790,9 @@ class CIDR
1480
1790
  #
1481
1791
  # - Returns:
1482
1792
  # * Byte-packed Netmask.
1793
+ #
1794
+ # Example:
1795
+ # packed = cidr.packed_netmask()
1483
1796
  #
1484
1797
  def packed_netmask()
1485
1798
  return(@netmask)
@@ -1502,6 +1815,9 @@ class CIDR
1502
1815
  #
1503
1816
  # - Returns:
1504
1817
  # * Byte-packed Network Address.
1818
+ #
1819
+ # Example:
1820
+ # packed = cidr.packed_network()
1505
1821
  #
1506
1822
  def packed_network()
1507
1823
  return(@network)
@@ -1524,6 +1840,9 @@ class CIDR
1524
1840
  #
1525
1841
  # - Returns:
1526
1842
  # * Number of IP addresses in this CIDR block.
1843
+ #
1844
+ # Example:
1845
+ # num_ip = cidr.size()
1527
1846
  #
1528
1847
  def size()
1529
1848
  return(@hostmask + 1)
@@ -1544,16 +1863,19 @@ class CIDR
1544
1863
  #
1545
1864
  # - Arguments:
1546
1865
  # * Hash with the following fields:
1547
- # :Subnet -- number of bits of new subnet to create (24,26, etc...)
1548
- # :MinCount -- minimum number of subnets of size :Subnet to return
1866
+ # - :Subnet -- number of bits of new subnet to create (24,26, etc...)
1867
+ # - :MinCount -- minimum number of subnets of size :Subnet to return
1549
1868
  #
1550
1869
  # - Returns:
1551
1870
  # * array of IPAdmin::CIDR objects
1871
+ #
1872
+ # Example:
1873
+ # cidr_list = cidr4.subnet(:Subnet => 28, :MinCount => 3)
1552
1874
  #
1553
1875
  def subnet(options)
1554
1876
  subnet = options[:Subnet]
1555
1877
  min_count = options[:MinCount]
1556
- mymask = self.netmask
1878
+ mymask = self.bits
1557
1879
  num_avail = 2**(subnet - mymask)
1558
1880
  new_subnets = []
1559
1881
 
@@ -1698,12 +2020,15 @@ class CIDRTable
1698
2020
  #============================================================================#
1699
2021
 
1700
2022
  # - Arguments:
1701
- # * Table version (4 or 6)
2023
+ # * IP version (4 or 6)
2024
+ #
2025
+ # Example:
2026
+ # table = IPAdmin::CIDRTable.new(4)
1702
2027
  #
1703
2028
  def initialize(version)
1704
2029
 
1705
2030
  unless ( version.kind_of? Fixnum )
1706
- raise "Expected Fixnum, but #{version.class} provided."
2031
+ raise ArgumentError, "Expected Fixnum, but #{version.class} provided."
1707
2032
  end
1708
2033
 
1709
2034
  unless ( version == 4 || version == 6 )
@@ -1730,10 +2055,17 @@ class CIDRTable
1730
2055
  # * IPAdmin::CIDR object
1731
2056
  #
1732
2057
  # - Returns:
1733
- # * nil
2058
+ # * nothing
2059
+ #
2060
+ # Example:
2061
+ # table.add_cidr(cidr)
1734
2062
  #
1735
2063
  def add_cidr(new_cidr)
1736
2064
 
2065
+ unless (new_cidr.kind_of? IPAdmin::CIDR)
2066
+ raise ArgumentError, "Expected IPAdmin::CIDR, but #{new_cidr.class} provided."
2067
+ end
2068
+
1737
2069
  unless (new_cidr.version == @version )
1738
2070
  raise "CIDR version #{new_cidr.version} is incompatible with " +
1739
2071
  "CIDRTable version #{@version}."
@@ -1805,10 +2137,13 @@ class CIDRTable
1805
2137
  # Dump contents of this table
1806
2138
  #
1807
2139
  # - Arguments:
1808
- # * nil
2140
+ # * none
1809
2141
  #
1810
2142
  # - Returns:
1811
2143
  # * ordered array of IPAdmin::CIDR objects within this table
2144
+ #
2145
+ # Example:
2146
+ # cidr_list = table.dump()
1812
2147
  #
1813
2148
  def dump()
1814
2149
 
@@ -1855,15 +2190,18 @@ class CIDRTable
1855
2190
  #
1856
2191
  # - Returns:
1857
2192
  # * IPAdmin::CIDR object, or nil on no match
2193
+ #
2194
+ # Example:
2195
+ # cidr = table.find_ip(ip)
1858
2196
  #
1859
2197
  def find_ip(ip_obj)
1860
2198
 
1861
2199
  unless (ip_obj.kind_of? IPAdmin::IPAddr)
1862
- raise "Expected IPAdmin::IPAddr, but #{options.class} provided."
2200
+ raise ArgumentError, "Expected IPAdmin::IPAddr, but #{ip_obj.class} provided."
1863
2201
  end
1864
2202
 
1865
2203
  unless (ip_obj.version == @version )
1866
- raise "IPAddr version #{ip_addr.version} is incompatible with " +
2204
+ raise "IPAddr version #{ip_obj.version} is incompatible with " +
1867
2205
  "CIDRTable version #{@version}."
1868
2206
  end
1869
2207
 
@@ -1899,11 +2237,14 @@ class CIDRTable
1899
2237
  #
1900
2238
  # - Arguments:
1901
2239
  # * Hash with the following fields:
1902
- # :Size -- subnet size (number of bits)
1903
- # :Limit -- max entries to return
2240
+ # - :Size -- subnet size (number of bits)
2241
+ # - :Limit -- max entries to return
1904
2242
  #
1905
2243
  # - Returns:
1906
2244
  # * ordered array of IPAdmin::CIDR objects, or nil on no match
2245
+ #
2246
+ # Example:
2247
+ # cidr_list = table.find_space(:Size => 27)
1907
2248
  #
1908
2249
  def find_space(options)
1909
2250
  limit = nil
@@ -1915,11 +2256,11 @@ class CIDRTable
1915
2256
 
1916
2257
  # validate options
1917
2258
  unless (options.kind_of? Hash)
1918
- raise "Expected Hash, but #{options.class} provided."
2259
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
1919
2260
  end
1920
2261
 
1921
2262
  unless ( options.has_key?(:Size) )
1922
- raise "Missing argument :Size."
2263
+ raise ArgumentError, "Missing argument :Size."
1923
2264
  end
1924
2265
  subnet_size = options[:Size]
1925
2266
 
@@ -1953,7 +2294,7 @@ class CIDRTable
1953
2294
  # find space
1954
2295
  sorted_parents.each do |key|
1955
2296
  parent = parent_hash[key]
1956
- if ( parent.netmask() < subnet_size )
2297
+ if ( parent.bits() < subnet_size )
1957
2298
  if (@cidr_table[parent] != 0)
1958
2299
  child_list = []
1959
2300
  child_list = (@cidr_table[parent]).find_space(:Size => subnet_size)
@@ -1970,7 +2311,7 @@ class CIDRTable
1970
2311
 
1971
2312
  end
1972
2313
 
1973
- elsif ( (parent_hash[key].netmask() == subnet_size) &&
2314
+ elsif ( (parent_hash[key].bits() == subnet_size) &&
1974
2315
  (@cidr_table[parent] == 0) )
1975
2316
  list.push(parent)
1976
2317
 
@@ -1993,6 +2334,62 @@ class CIDRTable
1993
2334
 
1994
2335
 
1995
2336
 
2337
+ #============================================================================#
2338
+ # rem_cidr()
2339
+ #============================================================================#
2340
+
2341
+ # Remove an IPAdmin::CIDR object from this table
2342
+ #
2343
+ # - Arguments:
2344
+ # * IPAdmin::CIDR object
2345
+ #
2346
+ # - Returns:
2347
+ # * nothing
2348
+ #
2349
+ # Example:
2350
+ # table.rem_cidr(cidr)
2351
+ #
2352
+ def rem_cidr(cidr)
2353
+
2354
+ unless (cidr.kind_of? IPAdmin::CIDR)
2355
+ raise ArgumentError, "Expected IPAdmin::CIDR, but #{cidr.class} provided."
2356
+ end
2357
+
2358
+ unless (cidr.version == @version )
2359
+ raise "CIDR version #{cidr.version} is incompatible with " +
2360
+ "CIDRTable version #{@version}."
2361
+ end
2362
+
2363
+ # if cidr is part of this table
2364
+ if (@cidr_table.has_key?(cidr) )
2365
+
2366
+ if (@cidr_table[cidr] != 0)
2367
+ child_table = @cidr_table[cidr]
2368
+ child_table.cidr_table.each_key do |child|
2369
+ child_table.rem_cidr(child)
2370
+ end
2371
+ end
2372
+ @cidr_table.delete(cidr)
2373
+
2374
+ # else search @cidr_table to see if cidr is a child block
2375
+ else
2376
+ @cidr_table.each_key do |entry|
2377
+ parent,child = IPAdmin.compare_cidr(cidr,entry)
2378
+
2379
+ if (parent == entry)
2380
+ (@cidr_table[entry]).rem_cidr(cidr)
2381
+ end
2382
+ end
2383
+ end
2384
+
2385
+ end
2386
+
2387
+ #=====================================#
2388
+ #
2389
+ #=====================================#
2390
+
2391
+
2392
+
1996
2393
 
1997
2394
  end
1998
2395
 
@@ -2031,17 +2428,19 @@ class IPAddr
2031
2428
  # attr_reader/attr_writer
2032
2429
  #============================================================================#
2033
2430
 
2034
- # @ip - packed ip address
2035
- # @netmask - packed netmask
2036
- # @hostmask - inverse packed netmask
2037
-
2038
2431
  # ip version 4 or 6
2039
2432
  attr_reader :version
2040
2433
 
2041
2434
  # hash of custom tags. should be in the format tag => value
2042
2435
  attr_reader :tag
2043
- attr_writer :tag
2044
-
2436
+
2437
+ # attr_writer - hash of custom tags. should be in the format tag => value
2438
+ def tag=(new_tag)
2439
+ unless (new_tag.kind_of? Hash)
2440
+ raise ArgumentError, "Expected Hash, but #{new_tag.class} provided."
2441
+ end
2442
+ @tag = new_tag
2443
+ end
2045
2444
 
2046
2445
  #=====================================#
2047
2446
  #
@@ -2055,14 +2454,21 @@ class IPAddr
2055
2454
 
2056
2455
  # - Arguments:
2057
2456
  # * Hash with the following fields
2058
- # :IPAddr -- IPv4 or IPv6 address (assume host address by default)
2059
- # :Netmask -- IPv4 netmask in extended format ( if not part of IPAddr)
2060
- # :Tag -- Custom descriptor tag for object. Should be Hash (tag => value)
2457
+ # - :IPAddr -- IPv4 or IPv6 address (assume host address by default)
2458
+ # - :Netmask -- IPv4 netmask in extended format ( if not part of IPAddr)
2459
+ # - :Tag -- Custom descriptor tag for object. Should be Hash (tag => value)
2460
+ #
2461
+ # Example:
2462
+ # ip4 = IPAdmin::IPAddr.new(:IPAddr => '192.168.1.1',
2463
+ # :Netmask => '255.255.255.0',
2464
+ # :Tag => {'desc' => 'FastEthernet0/1'})
2465
+ #
2466
+ # ip6 = IPAdmin::IPAddr.new(:IPAddr => 'fec0::/64')
2061
2467
  #
2062
2468
  def initialize(options)
2063
2469
 
2064
2470
  unless (options.kind_of? Hash)
2065
- raise "Expected Hash, but #{options.class} provided."
2471
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
2066
2472
  end
2067
2473
 
2068
2474
  if ( options.has_key?(:IPAddr) )
@@ -2144,10 +2550,12 @@ class IPAddr
2144
2550
 
2145
2551
 
2146
2552
  # set tag if present
2147
- if ( options.has_key?(:Tag) )
2553
+ if ( options.has_key?(:Tag) )
2148
2554
  @tag = options[:Tag]
2555
+ unless (@tag.kind_of? Hash)
2556
+ raise "Expected Hash, but #{@tag.class} provided for option :Tag."
2557
+ end
2149
2558
  end
2150
-
2151
2559
 
2152
2560
  end
2153
2561
 
@@ -2170,6 +2578,9 @@ class IPAddr
2170
2578
  #
2171
2579
  # - Returns:
2172
2580
  # * base network address.
2581
+ #
2582
+ # Example:
2583
+ # base = ip.base()
2173
2584
  #
2174
2585
  def base()
2175
2586
  if (@version == 4)
@@ -2189,6 +2600,37 @@ class IPAddr
2189
2600
 
2190
2601
 
2191
2602
 
2603
+ #============================================================================#
2604
+ # bits()
2605
+ #============================================================================#
2606
+
2607
+ # Provide number of bits of Netmask.
2608
+ #
2609
+ # - Arguments:
2610
+ # * none
2611
+ #
2612
+ # - Returns:
2613
+ # * Number of bits of Netmask.
2614
+ #
2615
+ # Example:
2616
+ # bits = ip.bits()
2617
+ #
2618
+ def bits()
2619
+ if (@version == 4)
2620
+ bits = IPAdmin.unpack_ipv4_netmask(@netmask)
2621
+ else
2622
+ bits = IPAdmin.unpack_ipv6_netmask(@netmask)
2623
+ end
2624
+
2625
+ return(bits)
2626
+ end
2627
+
2628
+ #=====================================#
2629
+ #
2630
+ #=====================================#
2631
+
2632
+
2633
+
2192
2634
  #============================================================================#
2193
2635
  # broadcast()
2194
2636
  #============================================================================#
@@ -2200,6 +2642,9 @@ class IPAddr
2200
2642
  #
2201
2643
  # - Returns:
2202
2644
  # * broadcast address.
2645
+ #
2646
+ # Example:
2647
+ # bcast = ip.broadcast()
2203
2648
  #
2204
2649
  def broadcast()
2205
2650
  if (@version == 4)
@@ -2230,6 +2675,9 @@ class IPAddr
2230
2675
  #
2231
2676
  # - Returns:
2232
2677
  # * ip/netmask.
2678
+ #
2679
+ # Example:
2680
+ # desc = ip.desc()
2233
2681
  #
2234
2682
  def desc()
2235
2683
  if (@version == 4)
@@ -2262,6 +2710,9 @@ class IPAddr
2262
2710
  #
2263
2711
  # - Returns:
2264
2712
  # * IPv4 Hostmask in extended (y.y.y.y) format.
2713
+ #
2714
+ # Example:
2715
+ # hostmask = ip.hostmask_ext()
2265
2716
  #
2266
2717
  def hostmask_ext()
2267
2718
  if (@version == 4)
@@ -2290,6 +2741,9 @@ class IPAddr
2290
2741
  #
2291
2742
  # - Returns:
2292
2743
  # * IP address.
2744
+ #
2745
+ # Example:
2746
+ # addr = ip.ip()
2293
2747
  #
2294
2748
  def ip()
2295
2749
  if (@version == 4)
@@ -2311,13 +2765,16 @@ class IPAddr
2311
2765
  # netmask()
2312
2766
  #============================================================================#
2313
2767
 
2314
- # Provide Netmask for address within IPAdmin::IPAddr object.
2768
+ # Provide Netmask in cidr format.
2315
2769
  #
2316
2770
  # - Arguments:
2317
2771
  # * none
2318
2772
  #
2319
2773
  # - Returns:
2320
- # * Number of bits in the netmask.
2774
+ # * Netmask in CIDR format.
2775
+ #
2776
+ # Example:
2777
+ # netmask = ip.netmask()
2321
2778
  #
2322
2779
  def netmask()
2323
2780
  if (@version == 4)
@@ -2326,7 +2783,7 @@ class IPAddr
2326
2783
  bits = IPAdmin.unpack_ipv6_netmask(@netmask)
2327
2784
  end
2328
2785
 
2329
- return(bits)
2786
+ return("/#{bits}")
2330
2787
  end
2331
2788
 
2332
2789
  #=====================================#
@@ -2346,13 +2803,16 @@ class IPAddr
2346
2803
  #
2347
2804
  # - Returns:
2348
2805
  # * IPv4 Netmask in extended (y.y.y.y) format.
2806
+ #
2807
+ # Example:
2808
+ # netmask = ip.netmask_ext()
2349
2809
  #
2350
2810
  def netmask_ext()
2351
2811
  if (@version == 4)
2352
2812
  netmask = IPAdmin.unpack_ipv4_addr(@netmask)
2353
2813
  else
2354
2814
  raise "IPv6 does not support extended netmask notation. " +
2355
- "Use bits() method instead."
2815
+ "Use netmask() method instead."
2356
2816
  end
2357
2817
 
2358
2818
  return(netmask)
@@ -2375,6 +2835,9 @@ class IPAddr
2375
2835
  #
2376
2836
  # - Returns:
2377
2837
  # * byte-packed Hostmask.
2838
+ #
2839
+ # Example:
2840
+ # packed = ip.packed_hostmask()
2378
2841
  #
2379
2842
  def packed_hostmask()
2380
2843
  return(@hostmask)
@@ -2397,6 +2860,9 @@ class IPAddr
2397
2860
  #
2398
2861
  # - Returns:
2399
2862
  # * byte-packed IP address.
2863
+ #
2864
+ # Example:
2865
+ # packed = ip.packed_ip()
2400
2866
  #
2401
2867
  def packed_ip()
2402
2868
  return(@ip)
@@ -2419,6 +2885,9 @@ class IPAddr
2419
2885
  #
2420
2886
  # - Returns:
2421
2887
  # * byte-packed Netask.
2888
+ #
2889
+ # Example:
2890
+ # packed = ip.packed_netmask()
2422
2891
  #
2423
2892
  def packed_netmask()
2424
2893
  return(@netmask)