cisco_acl_intp 0.0.2 → 0.0.3

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.
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