cisco_acl_intp 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +64 -3
  4. data/cisco_acl_intp.gemspec +2 -2
  5. data/lib/cisco_acl_intp/ace.rb +9 -286
  6. data/lib/cisco_acl_intp/ace_ip.rb +24 -22
  7. data/lib/cisco_acl_intp/ace_other_qualifiers.rb +23 -6
  8. data/lib/cisco_acl_intp/ace_port.rb +37 -182
  9. data/lib/cisco_acl_intp/ace_port_opr.rb +251 -0
  10. data/lib/cisco_acl_intp/ace_port_opr_base.rb +138 -0
  11. data/lib/cisco_acl_intp/ace_proto.rb +133 -328
  12. data/lib/cisco_acl_intp/ace_proto_base.rb +163 -0
  13. data/lib/cisco_acl_intp/ace_srcdst.rb +30 -40
  14. data/lib/cisco_acl_intp/ace_tcp_flags.rb +9 -3
  15. data/lib/cisco_acl_intp/acl.rb +1 -251
  16. data/lib/cisco_acl_intp/acl_base.rb +1 -1
  17. data/lib/cisco_acl_intp/acl_utils.rb +120 -0
  18. data/lib/cisco_acl_intp/extended_ace.rb +149 -0
  19. data/lib/cisco_acl_intp/mono_function_acl.rb +161 -0
  20. data/lib/cisco_acl_intp/parser.rb +237 -395
  21. data/lib/cisco_acl_intp/parser.ry +85 -243
  22. data/lib/cisco_acl_intp/parser_api.rb +2 -2
  23. data/lib/cisco_acl_intp/single_acl_base.rb +137 -0
  24. data/lib/cisco_acl_intp/standard_ace.rb +105 -0
  25. data/lib/cisco_acl_intp/version.rb +1 -1
  26. data/spec/cisco_acl_intp/ace_ip_spec.rb +63 -0
  27. data/spec/cisco_acl_intp/ace_other_qualifier_spec.rb +52 -1
  28. data/spec/cisco_acl_intp/ace_port_operator_spec.rb +340 -0
  29. data/spec/cisco_acl_intp/ace_port_spec.rb +67 -217
  30. data/spec/cisco_acl_intp/ace_proto_spec.rb +118 -41
  31. data/spec/cisco_acl_intp/ace_spec.rb +38 -547
  32. data/spec/cisco_acl_intp/ace_srcdst_spec.rb +115 -226
  33. data/spec/cisco_acl_intp/ace_tcp_flags_spec.rb +36 -4
  34. data/spec/cisco_acl_intp/acl_base_spec.rb +2 -2
  35. data/spec/cisco_acl_intp/extended_ace_spec.rb +411 -0
  36. data/spec/cisco_acl_intp/extended_acl_spec.rb +265 -0
  37. data/spec/cisco_acl_intp/scanner_spec.rb +13 -12
  38. data/spec/cisco_acl_intp/standard_ace_spec.rb +77 -0
  39. data/spec/cisco_acl_intp/standard_acl_spec.rb +245 -0
  40. data/spec/conf/scanner_spec_data.yml +32 -0
  41. data/spec/spec_helper.rb +2 -2
  42. metadata +20 -4
  43. data/spec/cisco_acl_intp/acl_spec.rb +0 -525
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d664d74e52b4738c1835532f0fecefe1ee162ece
4
- data.tar.gz: 56a40d167de808a4bf0ef778d8f443b01c408a22
3
+ metadata.gz: 60c56206a4b40ecdfc1b4cae9ddb3fa11da7e07e
4
+ data.tar.gz: 25b304576447f136c1da714cf0205531318bac33
5
5
  SHA512:
6
- metadata.gz: 63c07906a0c2910a1cdbb6cb53b02cb9ef36c32b4138223c400147d8447f101b9c44fb9af211363a9a79be6f4dde533f448483975cb132fd6461a4e49a7cf463
7
- data.tar.gz: c5208c436298dde049720eb9b5f15f41b09d482b696aa592c95220ec5fc6f779f2e8b4aebd2dda7539946d8eded55cdbfc4ba1a1b871afebefb1daf88b5d9cc2
6
+ metadata.gz: 42749dd6747920756f5a5f2c0a87e0ecbbed20d59db964244446d6bfa136c3c714edd9f6371b86fd8f2b5c57254aed782ffb6e1080ef4b58d4f4ea1b4c7f8457
7
+ data.tar.gz: 7cdd4c8d508a3bb271eef640636fc1f98bc7658d07f3ce718f1684719e5b943f5c5acf05c5ec2e44927bd3cb88b1f6c5f2e49a233dbd22f16d565b567a941b1d
data/Gemfile CHANGED
@@ -11,7 +11,7 @@ group :development, :test do
11
11
  gem 'rake', '~> 10.1.1'
12
12
  gem 'reek', '~> 1.3.6'
13
13
  gem 'rspec', '~> 2.14.1'
14
- gem 'rubocop', '~> 0.18.1' if RUBY_VERSION >= '1.9.0'
14
+ gem 'rubocop', '~> 0.19.1' if RUBY_VERSION >= '1.9.0'
15
15
  gem 'simplecov', '~> 0.8.2' if RUBY_VERSION >= '1.9.0'
16
16
  gem 'yard', '~> 0.8.7'
17
17
  end
data/README.md CHANGED
@@ -165,9 +165,70 @@ obj,... See more detail in documents (see also, Documents section)
165
165
 
166
166
  ### ACL Varidator Web Frontend
167
167
 
168
- Front-end of ACL Varidator is at
169
- [github](https://github.com/stereocat/cisco_acl_web). It not only can
170
- parse (with CLI tool, it can only parse), but also search for ACL(ACE).
168
+ [Web front-end of ACL Varidator](https://github.com/stereocat/cisco_acl_web)
169
+ is at my github repository. It not only can parse (with CLI tool, it
170
+ can only parse), but also search for ACL(ACE).
171
+
172
+ ## ACL operation as IP/Port set operation
173
+ ### Overview
174
+
175
+ A CIDR-IP-Subnet, IP address with wildcard mask, TCP/UDP port
176
+ numbere(s) with operator (`any`, `eq`, `neq`, `lt`, `gt`, `range`),
177
+ these are set of IPs and/or ports. In CiscoAclIntp, `contains?`
178
+ methods are implemented some ACL/ACE class. It is a set operation
179
+ method of IP address and TCP/UDP port (to check set inclusion
180
+ relation).
181
+
182
+ Example:
183
+ ```ruby
184
+ src = AceSrcDstSpec.new(
185
+ ipaddr: '192.168.15.15', wildcard: '0.0.7.6',
186
+ operator: 'gt', port: AceTcpProtoSpec.new(32_767)
187
+ )
188
+ dst = AceSrcDstSpec.new(
189
+ ipaddr: '192.168.30.3', wildcard: '0.0.0.0',
190
+ operator: 'range',
191
+ begin_port: AceTcpProtoSpec.new(1_024),
192
+ end_port: AceTcpProtoSpec.new(65_535)
193
+ )
194
+
195
+ # permit tcp 192.168.15.15 0.0.7.6 gt 32767 host 192.168.30.3 range 1024 65535
196
+ ace = ExtendedAce.new(
197
+ action: 'permit', protocol: 'tcp', src: src, dst: dst
198
+ )
199
+
200
+ ace.contains?(
201
+ protocol: 'tcp',
202
+ src_operator: :eq, src_ip: '192.168.9.11', src_port: 51234
203
+ )
204
+ #=> true
205
+ ```
206
+
207
+ ### IP Addr Operation
208
+
209
+ See `NetAddr::CIDR#matches?` for CIDR subnet operation and
210
+ `NetAddr::CIDR#contains?` for IP with wildcard mask.
211
+
212
+ ### Port Operation
213
+
214
+ | User | any | eq X | neq X | lt X | gt X | range X1 X2 |
215
+ |------------|------|--------|--------|--------|--------|---------------|
216
+ | any | true | true | true | true | true | true |
217
+ | strict_any | true | false | false | false | false | false |
218
+ | eq P | true | P = X | P != X | P < X | X < P | X1 <= P <= X2 |
219
+ | neq P | true | false | P = X | P = X = 65535 | P = X = 0 | (P=X1=0 and X2=65535) or (X1=0 and P=X2=65535) |
220
+ | lt P | true | false | P <= X | P <= X | false | X1 = 0 and P < X2 |
221
+ | gt P | true | false | X <= P | false | X <= P | X1 < P and X2 = 65535 |
222
+ | range P1 P2| true | false | P2 < X or X < P1 | P2 < X | X < P1 | X1 <= P1 and P2 <= X2 |
223
+
224
+ In above table, “User” column is the argment of `contains?`, and,
225
+ operators at table header are receiver of `contains?`. For example,
226
+ `[gt X].contains?([eq P])` will be `true` if port `X < P`. It means
227
+ the ACL `[gt X]` permit (or deny) the flow `[eq P]`. You can search
228
+ ACEs which matches a flows specified by search conditions.
229
+
230
+ `:strict_any` is a special operator to search acl, the operator is
231
+ matches only `:any` operator.
171
232
 
172
233
  ## Documents
173
234
 
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.version = CiscoAclIntp::VERSION
10
10
  spec.authors = ['stereocat']
11
11
  spec.email = ['stereocat@gmail.com']
12
- spec.description = %q{Cisco ACL Interpreter}
13
- spec.summary = %q{Cisco IOS Access Control List Interpreter}
12
+ spec.description = %q(Cisco ACL Interpreter)
13
+ spec.summary = %q(Cisco IOS Access Control List Interpreter)
14
14
  spec.homepage = 'https://github.com/stereocat/cisco_acl_intp'
15
15
  spec.license = 'MIT'
16
16
 
@@ -1,5 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
-
3
2
  require 'cisco_acl_intp/ace_srcdst'
4
3
 
5
4
  module CiscoAclIntp
@@ -42,7 +41,7 @@ module CiscoAclIntp
42
41
  # Search matched ACE
43
42
  # @return [Boolean] Matched or not
44
43
  # @abstract
45
- def matches?
44
+ def contains?
46
45
  false
47
46
  end
48
47
  end
@@ -57,7 +56,7 @@ module CiscoAclIntp
57
56
  end
58
57
 
59
58
  def to_s
60
- tag_error(sprintf('!! error !! %s', @line))
59
+ tag_error(format('!! error !! %s', @line))
61
60
  end
62
61
  end
63
62
 
@@ -78,19 +77,19 @@ module CiscoAclIntp
78
77
  # Check equality
79
78
  # @return [Boolean] Compare with comment string
80
79
  def ==(other)
81
- @comment == other.comment
80
+ other.instance_of?(RemarkAce) && @comment == other.comment
82
81
  end
83
82
 
84
83
  # Generate string for Cisco IOS access list
85
84
  # @return [String] Comment string
86
85
  def to_s
87
- sprintf 'remark %s', tag_remark(@comment.to_s)
86
+ format 'remark %s', tag_remark(@comment.to_s)
88
87
  end
89
88
 
90
89
  # Search matched ACE
91
90
  # @param [Hash] opts Options
92
91
  # return [Boolean] false, Remark does not match anithyng.
93
- def matches?(opts = nil)
92
+ def contains?(opts = nil)
94
93
  false
95
94
  end
96
95
  end
@@ -126,300 +125,24 @@ module CiscoAclIntp
126
125
 
127
126
  # @return [Boolean] Compare with recursive entry name
128
127
  def ==(other)
129
- @recursive_name == other.recursive_name
128
+ other.instance_of?(EvaluateAce) &&
129
+ @recursive_name == other.recursive_name
130
130
  end
131
131
 
132
132
  # Generate string for Cisco IOS access list
133
133
  # @return [String]
134
134
  def to_s
135
- sprintf 'evaluate %s', tag_name(@recursive_name)
135
+ format 'evaluate %s', tag_name(@recursive_name)
136
136
  end
137
137
 
138
138
  # Search matched ACE
139
139
  # @param [Hash] opts Options
140
140
  # return [Boolean]
141
141
  # @todo for Recursive name matching is not implemented yet
142
- def matches?(opts = nil)
142
+ def contains?(opts = nil)
143
143
  false
144
144
  end
145
145
  end
146
-
147
- # ACE for standard access list
148
- class StandardAce < AceBase
149
- # @param [String] value Action
150
- # @return [String]
151
- attr_accessor :action
152
-
153
- # @param [AceSrcDstSpec] value Source spec object
154
- # @return [AceSrcDstSpec]
155
- attr_accessor :src_spec
156
-
157
- # @param [AceLogSpec] value Log spec object
158
- # @return [AceLogSpec]
159
- attr_accessor :log_spec
160
-
161
- # Constructor
162
- # @param [Hash] opts Options
163
- # @option opts [Integer] :number Sequence number
164
- # @option opts [String] :action Action (permit/deny)
165
- # @option opts [AceSrcDstSpec] :src Source spec object
166
- # @option opts [Hash] :src Source spec parmeters
167
- # @option opts [AceLogSpec] :log Log spec object
168
- # @return [StandardAce]
169
- # @raise [AclArgumentError]
170
- def initialize(opts)
171
- super
172
- @options = opts
173
- @action = define_action
174
- @src_spec = define_src_spec
175
- @log_spec = define_log_spec
176
- end
177
-
178
- # @return [Boolean]
179
- def ==(other)
180
- @action == other.action && @src_spec == other.src_spec
181
- end
182
-
183
- # Generate string for Cisco IOS access list
184
- # @return [String]
185
- def to_s
186
- sprintf(
187
- '%s %s %s',
188
- tag_action(@action.to_s),
189
- @src_spec,
190
- tag_other_qualifier(@log_spec ? @log_spec : '')
191
- )
192
- end
193
-
194
- # Search matched ACE
195
- # @param [Hash] opts Options (target packet info)
196
- # @option opts [String] :src_ip Source IP Address
197
- # @return [Boolean] Matched or not
198
- # @raise [AclArgumentError] Invalid src_ip
199
- def matches?(opts)
200
- if opts.key?(:src_ip)
201
- @src_spec.matches?(opts[:src_ip])
202
- else
203
- fail AclArgumentError, 'Invalid match target src IP address'
204
- end
205
- end
206
-
207
- private
208
-
209
- # Set instance variables
210
- # @return [String] Action string
211
- # @raise [AclArgumentError]
212
- def define_action
213
- if @options.key?(:action)
214
- @options[:action]
215
- else
216
- fail AclArgumentError, 'Not specified action'
217
- end
218
- end
219
-
220
- # Set instance variables
221
- # @return [AceSrcDstSpec] Source spec object
222
- # @raise [AclArgumentError]
223
- def define_src_spec
224
- if @options.key?(:src)
225
- src = @options[:src]
226
- case src
227
- when Hash
228
- AceSrcDstSpec.new(src)
229
- when AceSrcDstSpec
230
- src
231
- else
232
- fail AclArgumentError, 'src spec: unknown class'
233
- end
234
- else
235
- fail AclArgumentError, 'Not specified src spec'
236
- end
237
- end
238
-
239
- # Set instance variables
240
- # @return [String] Log spec object
241
- # @raise [AclArgumentError]
242
- def define_log_spec
243
- @options[:log] || nil
244
- end
245
- end
246
-
247
- # ACE for extended access list
248
- class ExtendedAce < StandardAce
249
- # @param [String] value L3/L4 protocol
250
- # @return [String]
251
- attr_accessor :protocol
252
-
253
- # @param [AceSrcDstSpec] value Destination spec object
254
- # @return [AceSrcDstSpec]
255
- attr_accessor :dst_spec
256
-
257
- # @param [AceTcpFlagList] value
258
- # TCP flags (used when '@protocol':tcp)
259
- # @return [AceTcpFlagList]
260
- attr_accessor :tcp_flags
261
-
262
- # @param [AceOtherQualifierList] value
263
- # TCP other qualifier list object (used when '@protocol':tcp)
264
- # @return [AceOtherQualifierList]
265
- attr_accessor :tcp_other_qualifiers
266
-
267
- # Option,
268
- # :src and :dst can handle multiple types of object generation,
269
- # so that the argments can takes hash of AceSrcDstSpec.new or
270
- # AceSrcDstSpec instance.
271
- # :protocol and so on. (AceIpProtoSpec Object)
272
- #
273
- # about :protocol, it has specification of name and number
274
- # (specified in internal of parser).
275
- # basically, it is OK that specify only name.
276
- # (does it convert name <=> number each oether?)
277
- # (does it use number?
278
- #
279
-
280
- # Constructor
281
- # @param [Hash] opts Options
282
- # @option opts [String] :protocol L3/L4 protocol
283
- # @option opts [Integer] :number Protocol/Port number
284
- # @option opts [String] :action Action
285
- # @option opts [AceSrcDstSpec] :src Source spec object
286
- # @option opts [Hash] :src Source spec parmeters
287
- # @option opts [AceSrcDstSpec] :dst Destination spec object
288
- # @option opts [Hash] :dst Destination spec parmeters
289
- # @option opts [AceTcpFlagList] :tcp_port_qualifier
290
- # TCP Flags object
291
- # @raise [AclArgumentError]
292
- # @return [ExtendACE]
293
- #
294
- # @example Construct ACE object
295
- # ExtendACE.new(
296
- # :protocol => 'tcp',
297
- # :number => 10,
298
- # :action => 'permit',
299
- # :src => { :ipaddr => '192.168.3.0', :wildcard => '0.0.0.127' },
300
- # :dst => { :ipaddr => '172.30.0.0', :wildcard => '0.0.7.127',
301
- # :operator => 'eq', :begin_port => 80 })
302
- #
303
- def initialize(opts)
304
- super
305
- @options = opts
306
- @protocol = define_protocol
307
- @dst_spec = define_dst_spec
308
- @tcp_flags = define_tcp_flags
309
- @tcp_other_qualifiers = nil # not yet.
310
- end
311
-
312
- # @param [ExtendACE] other RHS object
313
- # @return [Boolean]
314
- def ==(other)
315
- @action == other.action &&
316
- @protocol == other.protocol &&
317
- @src_spec == other.src_spec &&
318
- @dst_spec == other.dst_spec &&
319
- @tcp_flags == other.tcp_flags
320
- ## does it need to compare? : tcp_other_qualifiers
321
- end
322
-
323
- # Generate string for Cisco IOS access list
324
- # @return [String]
325
- def to_s
326
- sprintf(
327
- '%s %s %s %s %s %s',
328
- tag_action(@action.to_s),
329
- tag_protocol(@protocol.to_s),
330
- @src_spec,
331
- @dst_spec,
332
- @tcp_flags,
333
- @tcp_other_qualifiers
334
- )
335
- end
336
-
337
- # Search matched ACE
338
- # @param [Hash] opts Options (target packet info)
339
- # @option opts [String] :protocol L3/L4 protocol name
340
- # (allows "tcp", "udp" and "icmp")
341
- # @option opts [String] :src_ip Source IP Address
342
- # @option opts [Integer,String] :src_port Source Port No./Name
343
- # @option opts [String] :dst_ip Destination IP Address
344
- # @option opts [Integer,String] :dst_port Destination Port No./Name
345
- # @return [Boolean] Matched or not
346
- # @raise [AclArgumentError]
347
- def matches?(opts)
348
- if opts.key?(:protocol)
349
- match_protocol?(opts[:protocol]) &&
350
- @src_spec.matches?(opts[:src_ip], opts[:src_port]) &&
351
- @dst_spec.matches?(opts[:dst_ip], opts[:dst_port])
352
- else
353
- fail AclArgumentError, 'Invalid match target protocol'
354
- end
355
- end
356
-
357
- private
358
-
359
- # check protocol
360
- # @option protocol [AceProtoSpecBase] protocol
361
- # @return [Boolean] Matched or not
362
- # @raise [AclArgumentError]
363
- def match_protocol?(protocol)
364
- protocol_str = @protocol.to_s
365
- if [protocol_str, protocol].include?('ip')
366
- true # allow any of icmp/tcp/udp
367
- else
368
- # @todo what to do when NO name and only protocol number is
369
- # specified? In principle, it must be compared by object.
370
- protocol == protocol_str
371
- end
372
- end
373
-
374
- # Set instance variables
375
- # return [AceIpProtoSpec] IP protocol object
376
- # raise [AclArgumentError]
377
- def define_protocol
378
- if @options.key?(:protocol)
379
- protocol = @options[:protocol]
380
- case protocol
381
- when AceIpProtoSpec
382
- protocol
383
- else
384
- AceIpProtoSpec.new(
385
- name: protocol,
386
- number: @options[:protocol_num]
387
- )
388
- end
389
- else
390
- fail AclArgumentError, 'Not specified IP protocol'
391
- end
392
- end
393
-
394
- # Set instance variables
395
- # @return [AceSrcDstSpec] Destination spec object
396
- # @raise [AclArgumentError]
397
- def define_dst_spec
398
- if @options.key?(:dst)
399
- dst = @options[:dst]
400
- case dst
401
- when Hash
402
- AceSrcDstSpec.new(dst)
403
- when AceSrcDstSpec
404
- dst
405
- else
406
- fail AclArgumentError, 'Dst spec: unknown class'
407
- end
408
- else
409
- fail AclArgumentError, 'Not specified dst spec'
410
- end
411
- end
412
-
413
- # Set instance variables
414
- # @return [AceOtherQualifierList]
415
- def define_tcp_flags
416
- if @protocol.name == 'tcp' && @options.key?(:tcp_flags_qualifier)
417
- @options[:tcp_flags_qualifier]
418
- else
419
- nil
420
- end
421
- end
422
- end
423
146
  end # module
424
147
 
425
148
  ### Local variables:
@@ -1,5 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
-
3
2
  require 'forwardable'
4
3
  require 'netaddr'
5
4
  require 'cisco_acl_intp/acl_base'
@@ -14,7 +13,7 @@ module CiscoAclIntp
14
13
  # @return [NetAddr::CIDR]
15
14
  attr_reader :ipaddr
16
15
 
17
- # @param [Integer] value Netmask length
16
+ # @param [Integer] value Netmask *length*
18
17
  # @return [Integer]
19
18
  attr_reader :netmask
20
19
 
@@ -23,10 +22,10 @@ module CiscoAclIntp
23
22
  # @return [String]
24
23
  attr_reader :wildcard
25
24
 
26
- def_delegator :@ipaddr, :ip, :ipaddr
27
-
28
25
  # `matches?' method is wildcard mask operation
29
- def_delegators :@ipaddr, :matches?
26
+ def_delegators :@ipaddr, :matches?, :contains?
27
+ # ip returns non-masked address
28
+ def_delegators :@ipaddr, :ip
30
29
 
31
30
  # Constructor
32
31
  # @param [Hash] opts Options
@@ -49,9 +48,8 @@ module CiscoAclIntp
49
48
  # @param [AceIpSpec] other RHS Object
50
49
  # @return [Boolean]
51
50
  def ==(other)
52
- @ipaddr == other.ipaddr &&
53
- @netmask == other.netmask &&
54
- @wildcard == other.wildcard
51
+ @ipaddr == other.ipaddr && ip == other.ip &&
52
+ @netmask == other.netmask && @wildcard == other.wildcard
55
53
  end
56
54
 
57
55
  # Generate string for Cisco IOS access list
@@ -63,9 +61,9 @@ module CiscoAclIntp
63
61
  else
64
62
  if @wildcard == '0.0.0.0'
65
63
  # /32 mask
66
- sprintf('%s %s', tag_mask('host'), tag_ip(@ipaddr.ip))
64
+ format '%s %s', tag_mask('host'), tag_ip(@ipaddr.ip)
67
65
  else
68
- sprintf('%s %s', tag_ip(to_wmasked_ip_s), tag_mask(@wildcard))
66
+ format '%s %s', tag_ip(to_wmasked_ip_s), tag_mask(@wildcard)
69
67
  end
70
68
  end
71
69
  end
@@ -100,6 +98,8 @@ module CiscoAclIntp
100
98
  # Covnet IPv4 bit-flapped wildcard to netmask length
101
99
  # @return [Fixnum] netmask length
102
100
  # or `nil` when discontinuous-bits-wildcard-mask
101
+ # @todo Known bug: it cannot handle wrong wildcard,
102
+ # e.g. '0.0.0.1.255' #=> 31
103
103
  def wildcard_bitlength
104
104
  @wildcard.split(/\./).reduce(0) do |len, octet|
105
105
  if len && OCTET_BIT_LENGTH.key?(octet)
@@ -110,8 +110,19 @@ module CiscoAclIntp
110
110
  end
111
111
  end
112
112
 
113
+ # Check ip addr string: alias 'any' ipaddr
114
+ # @return [AceIpSpec] IP spec object.
115
+ def check_ip_any_alias
116
+ case @options[:ipaddr]
117
+ when nil, '', 'any', /^\s*$/
118
+ @options[:ipaddr] = '0.0.0.0'
119
+ @options[:netmask] = 0
120
+ end
121
+ end
122
+
113
123
  # Set instance variables
114
124
  def define_addrinfo
125
+ check_ip_any_alias
115
126
  if @options.key?(:wildcard)
116
127
  define_addrinfo_prefer_wildcard
117
128
  else
@@ -137,7 +148,8 @@ module CiscoAclIntp
137
148
  if @options.key?(:netmask)
138
149
  define_addrinfo_with_netmask
139
150
  else
140
- define_addrinfo_with_default_netmask
151
+ @options[:netmask] = 32 # default ('host' mask)
152
+ define_addrinfo_with_netmask
141
153
  end
142
154
  end
143
155
 
@@ -154,17 +166,7 @@ module CiscoAclIntp
154
166
  def define_addrinfo_with_netmask
155
167
  @netmask = @options[:netmask]
156
168
  @ipaddr = NetAddr::CIDR.create(
157
- [@options[:ipaddr], @netmask].join('/')
158
- )
159
- @wildcard = @ipaddr.wildcard_mask(true)
160
- end
161
-
162
- # Set instance variables with ip/default-netmask
163
- def define_addrinfo_with_default_netmask
164
- # default mask
165
- @netmask = '255.255.255.255'
166
- @ipaddr = NetAddr::CIDR.create(
167
- [@options[:ipaddr], @netmask].join(' ')
169
+ format '%s/%s', @options[:ipaddr], @netmask
168
170
  )
169
171
  @wildcard = @ipaddr.wildcard_mask(true)
170
172
  end
@@ -16,8 +16,8 @@ module CiscoAclIntp
16
16
 
17
17
  # Constructor
18
18
  # @return [AceOtherQualifierList]
19
- def initialize
20
- @list = []
19
+ def initialize(list = [])
20
+ @list = list
21
21
  end
22
22
 
23
23
  # Generate string for Cisco IOS access list
@@ -29,7 +29,9 @@ module CiscoAclIntp
29
29
  # @param [AceOtherQualifierList] other RHS Object
30
30
  # @return [Boolean]
31
31
  def ==(other)
32
- @list == other.list
32
+ @list.reduce(true) do |res, each|
33
+ res && other.list.include?(each)
34
+ end
33
35
  end
34
36
  end
35
37
 
@@ -45,7 +47,7 @@ module CiscoAclIntp
45
47
 
46
48
  # Specified log-input logging?
47
49
  # @return [Boolean]
48
- attr_reader :input
50
+ attr_accessor :input
49
51
 
50
52
  # alias as boolean method
51
53
  # @return [Boolean]
@@ -63,12 +65,20 @@ module CiscoAclIntp
63
65
  # Generate string for Cisco IOS access list
64
66
  # @return [String]
65
67
  def to_s
66
- sprintf(
68
+ format(
67
69
  '%s %s',
68
70
  @input ? 'log-input' : 'log',
69
71
  @cookie ? @cookie : ''
70
72
  )
71
73
  end
74
+
75
+ # @param [AceLogSpec] other RHS object
76
+ # @return [Boolean]
77
+ def ==(other)
78
+ other.instance_of?(AceLogSpec) &&
79
+ @input == other.input &&
80
+ @cookie == other.cookie
81
+ end
72
82
  end
73
83
 
74
84
  # Recursive qualifier container
@@ -90,7 +100,14 @@ module CiscoAclIntp
90
100
  # Generate string for Cisco IOS access list
91
101
  # @return [String]
92
102
  def to_s
93
- sprintf 'reflect %s', tag_name(@recursive_name)
103
+ format 'reflect %s', tag_name(@recursive_name)
104
+ end
105
+
106
+ # @param [AceRecursiveQualifier] other RHS object
107
+ # @return [Boolean]
108
+ def ==(other)
109
+ other.instance_of?(AceRecursiveQualifier) &&
110
+ @recursive_name == other.recursive_name
94
111
  end
95
112
  end
96
113
  end # module