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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +64 -3
- data/cisco_acl_intp.gemspec +2 -2
- data/lib/cisco_acl_intp/ace.rb +9 -286
- data/lib/cisco_acl_intp/ace_ip.rb +24 -22
- data/lib/cisco_acl_intp/ace_other_qualifiers.rb +23 -6
- data/lib/cisco_acl_intp/ace_port.rb +37 -182
- data/lib/cisco_acl_intp/ace_port_opr.rb +251 -0
- data/lib/cisco_acl_intp/ace_port_opr_base.rb +138 -0
- data/lib/cisco_acl_intp/ace_proto.rb +133 -328
- data/lib/cisco_acl_intp/ace_proto_base.rb +163 -0
- data/lib/cisco_acl_intp/ace_srcdst.rb +30 -40
- data/lib/cisco_acl_intp/ace_tcp_flags.rb +9 -3
- data/lib/cisco_acl_intp/acl.rb +1 -251
- data/lib/cisco_acl_intp/acl_base.rb +1 -1
- data/lib/cisco_acl_intp/acl_utils.rb +120 -0
- data/lib/cisco_acl_intp/extended_ace.rb +149 -0
- data/lib/cisco_acl_intp/mono_function_acl.rb +161 -0
- data/lib/cisco_acl_intp/parser.rb +237 -395
- data/lib/cisco_acl_intp/parser.ry +85 -243
- data/lib/cisco_acl_intp/parser_api.rb +2 -2
- data/lib/cisco_acl_intp/single_acl_base.rb +137 -0
- data/lib/cisco_acl_intp/standard_ace.rb +105 -0
- data/lib/cisco_acl_intp/version.rb +1 -1
- data/spec/cisco_acl_intp/ace_ip_spec.rb +63 -0
- data/spec/cisco_acl_intp/ace_other_qualifier_spec.rb +52 -1
- data/spec/cisco_acl_intp/ace_port_operator_spec.rb +340 -0
- data/spec/cisco_acl_intp/ace_port_spec.rb +67 -217
- data/spec/cisco_acl_intp/ace_proto_spec.rb +118 -41
- data/spec/cisco_acl_intp/ace_spec.rb +38 -547
- data/spec/cisco_acl_intp/ace_srcdst_spec.rb +115 -226
- data/spec/cisco_acl_intp/ace_tcp_flags_spec.rb +36 -4
- data/spec/cisco_acl_intp/acl_base_spec.rb +2 -2
- data/spec/cisco_acl_intp/extended_ace_spec.rb +411 -0
- data/spec/cisco_acl_intp/extended_acl_spec.rb +265 -0
- data/spec/cisco_acl_intp/scanner_spec.rb +13 -12
- data/spec/cisco_acl_intp/standard_ace_spec.rb +77 -0
- data/spec/cisco_acl_intp/standard_acl_spec.rb +245 -0
- data/spec/conf/scanner_spec_data.yml +32 -0
- data/spec/spec_helper.rb +2 -2
- metadata +20 -4
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60c56206a4b40ecdfc1b4cae9ddb3fa11da7e07e
|
4
|
+
data.tar.gz: 25b304576447f136c1da714cf0205531318bac33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
|
169
|
-
|
170
|
-
|
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
|
|
data/cisco_acl_intp.gemspec
CHANGED
@@ -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
|
13
|
-
spec.summary = %q
|
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
|
|
data/lib/cisco_acl_intp/ace.rb
CHANGED
@@ -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
|
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(
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
64
|
+
format '%s %s', tag_mask('host'), tag_ip(@ipaddr.ip)
|
67
65
|
else
|
68
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|