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
@@ -1,5 +1,4 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
|
3
2
|
require 'netaddr'
|
4
3
|
require 'cisco_acl_intp/ace_ip'
|
5
4
|
require 'cisco_acl_intp/ace_port'
|
@@ -9,7 +8,7 @@ require 'cisco_acl_intp/ace_tcp_flags'
|
|
9
8
|
module CiscoAclIntp
|
10
9
|
# IP Address and TCP/UDP Port Info
|
11
10
|
# @todo Src/Dst takes Network Object Group or IP/wildcard.
|
12
|
-
# object
|
11
|
+
# "object-group" is not implemented yet.
|
13
12
|
class AceSrcDstSpec < AclContainerBase
|
14
13
|
# @param [AceIpSpec] value IP address and Wildcard-mask
|
15
14
|
# @return [AceIpSpec]
|
@@ -25,8 +24,9 @@ module CiscoAclIntp
|
|
25
24
|
# @option opts [String] :ipaddr IP Address (dotted notation)
|
26
25
|
# @option opts [String] :wildcard Wildcard mask
|
27
26
|
# (dotted/bit-flipped notation)
|
27
|
+
# @option opts [Integer] :netmask Subnet mask length (e.g. 24)
|
28
28
|
# @option opts [AcePortSpec] :port_spec Port/Operator object
|
29
|
-
# @option opts [String] :operator Port operator
|
29
|
+
# @option opts [String, Symbol] :operator Port operator
|
30
30
|
# @option opts [AceProtoSpecBase] :port port number (single/lower)
|
31
31
|
# (same as :begin_port, alias for unary operator)
|
32
32
|
# @option opts [AceProtoSpecBase] :begin_port port number (single/lower)
|
@@ -52,52 +52,44 @@ module CiscoAclIntp
|
|
52
52
|
# Generate string for Cisco IOS access list
|
53
53
|
# @return [String]
|
54
54
|
def to_s
|
55
|
-
|
55
|
+
format '%s %s', @ip_spec, @port_spec
|
56
56
|
end
|
57
57
|
|
58
|
-
# Check address and port number
|
59
|
-
# @param [
|
60
|
-
# @param [Integer,String] port Port No./Name
|
58
|
+
# Check address and port number contains this object or not.
|
59
|
+
# @param [AceSrcDstSpec] other Conditions to compare
|
61
60
|
# @return [Boolean]
|
62
61
|
# @raise [AclArgumentError]
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
# AceSrcDstSpec#matches?('any', 'www') # any host and port 80
|
67
|
-
def matches?(address, port = nil)
|
68
|
-
if address
|
69
|
-
matches_address?(address) && matches_port?(port)
|
70
|
-
else
|
71
|
-
fail AclArgumentError, 'Not specified match target IP Addr'
|
72
|
-
end
|
62
|
+
def contains?(other)
|
63
|
+
contains_address?(other.ip_spec) &&
|
64
|
+
contains_port?(other.port_spec)
|
73
65
|
end
|
74
66
|
|
75
67
|
private
|
76
68
|
|
77
69
|
# Check port match
|
78
|
-
# @param [
|
70
|
+
# @param [AcePortSpec] port_spec TCP/UDP Port spec
|
79
71
|
# @return [Boolean]
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
true
|
84
|
-
else
|
85
|
-
@port_spec.matches?(port)
|
86
|
-
end
|
72
|
+
def contains_port?(port_spec = nil)
|
73
|
+
port_spec = AcePortSpec.new(operator: :any) if port_spec.nil?
|
74
|
+
@port_spec.contains?(port_spec)
|
87
75
|
end
|
88
76
|
|
89
|
-
# Check address match
|
90
|
-
# @param [
|
77
|
+
# Check address match (by NetAddr)
|
78
|
+
# @param [AceIpSpec] ip_spec IP address spec.
|
91
79
|
# @return [Boolean]
|
92
|
-
def
|
93
|
-
case
|
94
|
-
when /
|
95
|
-
# addr/mask or addr/mask-length notation
|
96
|
-
@ip_spec.contains?(address)
|
97
|
-
when '0.0.0.0', '0.0.0.0/0', 'any'
|
80
|
+
def contains_address?(ip_spec = nil)
|
81
|
+
case ip_spec
|
82
|
+
when nil # 'any', '0.0.0.0/0'
|
98
83
|
true
|
99
84
|
else
|
100
|
-
|
85
|
+
# IP match/contain checks are delegated to NetAddr
|
86
|
+
if @ip_spec.netmask.nil?
|
87
|
+
# check by wildcard
|
88
|
+
@ip_spec.matches?(ip_spec.ipaddr)
|
89
|
+
else
|
90
|
+
# check by CIDR(netmask)
|
91
|
+
@ip_spec.contains?(ip_spec.ipaddr)
|
92
|
+
end
|
101
93
|
end
|
102
94
|
end
|
103
95
|
|
@@ -106,13 +98,10 @@ module CiscoAclIntp
|
|
106
98
|
# @return [AceIpSpec] IP address/Mask object
|
107
99
|
# @see #initialize
|
108
100
|
def define_ipspec
|
109
|
-
if @options.key?(:ip_spec)
|
101
|
+
if @options.key?(:ip_spec) # AceIpSpec Obj
|
110
102
|
@options[:ip_spec]
|
111
103
|
elsif @options.key?(:ipaddr)
|
112
|
-
AceIpSpec.new(
|
113
|
-
ipaddr: @options[:ipaddr],
|
114
|
-
wildcard: @options[:wildcard]
|
115
|
-
)
|
104
|
+
AceIpSpec.new(@options)
|
116
105
|
else
|
117
106
|
fail AclArgumentError, 'Not specified: ip spec'
|
118
107
|
end
|
@@ -122,7 +111,8 @@ module CiscoAclIntp
|
|
122
111
|
# @return [AcePortSpec] Port/Operator object
|
123
112
|
# @see #initialize
|
124
113
|
def define_portspec
|
125
|
-
if @options.key?(:port_spec)
|
114
|
+
if @options.key?(:port_spec) &&
|
115
|
+
@options[:port_spec].kind_of?(AcePortSpec)
|
126
116
|
@options[:port_spec]
|
127
117
|
elsif @options.key?(:operator)
|
128
118
|
AcePortSpec.new(
|
@@ -40,8 +40,11 @@ module CiscoAclIntp
|
|
40
40
|
|
41
41
|
def_delegators :@list, :push, :pop, :shift, :unshift, :size, :length
|
42
42
|
|
43
|
-
|
44
|
-
|
43
|
+
# Constructor
|
44
|
+
# @param [Array<AceTcpFlag>] list TCP Flag Objects
|
45
|
+
# @todo If the object that are same are included in the list?
|
46
|
+
def initialize(list = [])
|
47
|
+
@list = list
|
45
48
|
end
|
46
49
|
|
47
50
|
# Generate string for Cisco IOS access list
|
@@ -51,9 +54,12 @@ module CiscoAclIntp
|
|
51
54
|
end
|
52
55
|
|
53
56
|
# @param [AceTcpFlagList] other RHS Object
|
57
|
+
# @note Checked each entry in randum order.
|
54
58
|
# @return [Boolean]
|
55
59
|
def ==(other)
|
56
|
-
@list
|
60
|
+
@list.reduce(true) do |res, each|
|
61
|
+
res && other.list.include?(each)
|
62
|
+
end
|
57
63
|
end
|
58
64
|
end
|
59
65
|
end # module
|
data/lib/cisco_acl_intp/acl.rb
CHANGED
@@ -1,259 +1,9 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
require 'forwardable'
|
4
|
-
require 'cisco_acl_intp/
|
4
|
+
require 'cisco_acl_intp/mono_function_acl'
|
5
5
|
|
6
6
|
module CiscoAclIntp
|
7
|
-
# Single access-list container base
|
8
|
-
class SingleAclBase < AclContainerBase
|
9
|
-
extend Forwardable
|
10
|
-
include Enumerable
|
11
|
-
|
12
|
-
# @return [String] name ACL name,
|
13
|
-
# when numbered acl, /\d+/ string
|
14
|
-
attr_reader :name
|
15
|
-
# Some Enumerable included methods returns Array of ACE objects
|
16
|
-
# (e.g. sort),the returned Array was used as ACE object by
|
17
|
-
# overwrite accessor 'list'.
|
18
|
-
# @return [Array<AceBase>] list ACE object Array
|
19
|
-
attr_accessor :list
|
20
|
-
# @return [String, Symbol] acl_type ACL type
|
21
|
-
attr_reader :acl_type
|
22
|
-
# @return [String, Symbol] name_type ACL name type
|
23
|
-
attr_reader :name_type
|
24
|
-
|
25
|
-
def_delegators :@list, :each # for Enumerable
|
26
|
-
def_delegators :@list, :push, :pop, :shift, :unshift
|
27
|
-
def_delegators :@list, :size, :length
|
28
|
-
|
29
|
-
# Increment number of ACL sequence number
|
30
|
-
SEQ_NUM_DIV = 10
|
31
|
-
|
32
|
-
# Constructor
|
33
|
-
# @param [String] name ACL name
|
34
|
-
# @return [SingleAclBase]
|
35
|
-
def initialize(name)
|
36
|
-
@name = name
|
37
|
-
@list = []
|
38
|
-
@seq_number = 0
|
39
|
-
|
40
|
-
@acl_type = nil # :standard or :extended
|
41
|
-
@name_type = nil # :named or :numbered
|
42
|
-
end
|
43
|
-
|
44
|
-
# duplicate ACE list
|
45
|
-
# @param [Array<AceBase>] list List of ACE
|
46
|
-
# @return [SingleAclBase]
|
47
|
-
def dup_with_list(list)
|
48
|
-
acl = dup
|
49
|
-
acl.list = list.dup
|
50
|
-
acl
|
51
|
-
end
|
52
|
-
|
53
|
-
# Add ACE to ACL (push with sequence number)
|
54
|
-
# @param [AceBase] ace ACE object
|
55
|
-
def add_entry(ace)
|
56
|
-
# 'ace' is AceBase Object
|
57
|
-
# it will be ExtendedAce/StandardAce/RemarkAce/EvaluateAce
|
58
|
-
ace.seq_number? ||
|
59
|
-
ace.seq_number = (@list.length + 1) * SEQ_NUM_DIV
|
60
|
-
@list.push ace
|
61
|
-
end
|
62
|
-
|
63
|
-
# Renumber ACL by list sequence
|
64
|
-
def renumber
|
65
|
-
# re-numbering seq_number of each entry
|
66
|
-
@list.reduce(SEQ_NUM_DIV) do |number, each|
|
67
|
-
each.seq_number = number
|
68
|
-
number + SEQ_NUM_DIV
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# @return [Boolean]
|
73
|
-
def ==(other)
|
74
|
-
if @acl_type &&
|
75
|
-
@name_type &&
|
76
|
-
@acl_type == other.acl_type &&
|
77
|
-
@name_type == other.name_type
|
78
|
-
@list == other.list
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Search matched ACE from list
|
83
|
-
# @param [Hash] opts Options (target packet info)
|
84
|
-
# @option [String, Symbol] protocol L3/L4 protocol name
|
85
|
-
# (allows :tcp, :udp and :icmp)
|
86
|
-
# @option [String] src_ip Source IP Address
|
87
|
-
# @option [Integer,String] src_port Source Port No./Name
|
88
|
-
# @option [String] dst_ip Destination IP Address
|
89
|
-
# @option [Integer,String] dst_port Destination Port No./Name
|
90
|
-
# @return [AceBase] Matched ACE object or nil(not found)
|
91
|
-
# @raise [AclArgumentError]
|
92
|
-
def search_ace(opts)
|
93
|
-
@list.find { |each| each.matches?(opts) }
|
94
|
-
end
|
95
|
-
|
96
|
-
# acl string clean-up (override)
|
97
|
-
# @param [String] str ACL string.
|
98
|
-
# @return [String]
|
99
|
-
def clean_acl_string(str)
|
100
|
-
str =~ /remark/ ? str : super
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
############################################################
|
105
|
-
|
106
|
-
# Features for Extended ACL
|
107
|
-
# @todo Does it have to raise error if add_entry called with
|
108
|
-
# StandardAce?
|
109
|
-
module ExtAcl
|
110
|
-
# Generate a Extended ACE by parameters
|
111
|
-
# and Add it to ACL
|
112
|
-
# @param [Hash] opts Options to create {ExtendedAce}
|
113
|
-
def add_entry_by_params(opts)
|
114
|
-
ace = ExtendedAce.new opts
|
115
|
-
add_entry ace
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# Features for Standard ACL
|
120
|
-
# @todo Does it have to raise error if add_entry called with
|
121
|
-
# ExtendedAce?
|
122
|
-
module StdAcl
|
123
|
-
# Generate a Standard ACE by parameters
|
124
|
-
# and Add it to ACL
|
125
|
-
# @param [Hash] opts Options to create {StandardAce}
|
126
|
-
def add_entry_by_params(opts)
|
127
|
-
ace = StandardAce.new opts
|
128
|
-
add_entry ace
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
############################################################
|
133
|
-
|
134
|
-
# Named ACL container base
|
135
|
-
class NamedAcl < SingleAclBase
|
136
|
-
# check acl type,Named ACL or not?
|
137
|
-
# @return [Boolean]
|
138
|
-
def named_acl?
|
139
|
-
true
|
140
|
-
end
|
141
|
-
|
142
|
-
# check acl type, Numbered ACL or not?
|
143
|
-
# @return [Boolean]
|
144
|
-
def numbered_acl?
|
145
|
-
false
|
146
|
-
end
|
147
|
-
|
148
|
-
# Generate ACL header string
|
149
|
-
# @return [String] ACL header string
|
150
|
-
def header_string
|
151
|
-
sprintf(
|
152
|
-
'%s %s %s',
|
153
|
-
tag_header('ip access-list'),
|
154
|
-
tag_type(@acl_type),
|
155
|
-
tag_name(@name)
|
156
|
-
)
|
157
|
-
end
|
158
|
-
|
159
|
-
# Generate ACL line string
|
160
|
-
# @param [AceBase] entry ACE object
|
161
|
-
def line_string(entry)
|
162
|
-
# add indent
|
163
|
-
sprintf(' %s', clean_acl_string(entry.to_s))
|
164
|
-
end
|
165
|
-
|
166
|
-
# Generate string for Cisco IOS access list
|
167
|
-
# @return [String]
|
168
|
-
def to_s
|
169
|
-
strings = @list.each_with_object([header_string]) do |entry, strlist|
|
170
|
-
strlist.push line_string(entry)
|
171
|
-
end
|
172
|
-
strings.join("\n")
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
# Numbered ACL container base
|
177
|
-
class NumberedAcl < SingleAclBase
|
178
|
-
# @return [Integer] Access list number
|
179
|
-
attr_reader :number
|
180
|
-
|
181
|
-
# check acl type,Named ACL or not?
|
182
|
-
# @return [Boolean]
|
183
|
-
def named_acl?
|
184
|
-
false
|
185
|
-
end
|
186
|
-
|
187
|
-
# check acl type, Numbered ACL or not?
|
188
|
-
# @return [Boolean]
|
189
|
-
def numbered_acl?
|
190
|
-
true
|
191
|
-
end
|
192
|
-
|
193
|
-
# Constructor
|
194
|
-
# @param [String, Integer] name ACL number
|
195
|
-
# @raise [AclArgumentError]
|
196
|
-
# @return [NumberedAcl]
|
197
|
-
# @todo It ought to do something about assignment operator...
|
198
|
-
# (attr_reader)
|
199
|
-
def initialize(name)
|
200
|
-
super
|
201
|
-
case name
|
202
|
-
when Fixnum
|
203
|
-
set_name_and_number(name.to_s, name)
|
204
|
-
when String
|
205
|
-
validate_name_by_string(name)
|
206
|
-
else
|
207
|
-
fail AclArgumentError, 'acl number error'
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
# Generate ACL header string
|
212
|
-
# @return [String] ACL header string
|
213
|
-
def header_string
|
214
|
-
sprintf(
|
215
|
-
'%s %s',
|
216
|
-
tag_header('access-list'),
|
217
|
-
tag_name(@name)
|
218
|
-
)
|
219
|
-
end
|
220
|
-
|
221
|
-
# Generate ACL line string
|
222
|
-
# @param [AceBase] entry ACE object
|
223
|
-
def line_string(entry)
|
224
|
-
clean_acl_string(sprintf('%s %s', header_string, entry))
|
225
|
-
end
|
226
|
-
|
227
|
-
# Generate string for Cisco IOS access list
|
228
|
-
# @return [String]
|
229
|
-
def to_s
|
230
|
-
strings = @list.each_with_object([]) do |entry, strlist|
|
231
|
-
strlist.push line_string(entry)
|
232
|
-
end
|
233
|
-
strings.join("\n")
|
234
|
-
end
|
235
|
-
|
236
|
-
private
|
237
|
-
|
238
|
-
# validate instance variables
|
239
|
-
# @param [String] name ACL Name
|
240
|
-
def validate_name_by_string(name)
|
241
|
-
if name =~ /\A\d+\Z/
|
242
|
-
set_name_and_number(name, name.to_i)
|
243
|
-
else
|
244
|
-
fail AclArgumentError, 'acl number string is not integer'
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
# Set instance variables
|
249
|
-
def set_name_and_number(name, number)
|
250
|
-
@name = name
|
251
|
-
@number = number
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
############################################################
|
256
|
-
|
257
7
|
# Named extended ACL container
|
258
8
|
class NamedExtAcl < NamedAcl
|
259
9
|
include ExtAcl
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'cisco_acl_intp/extended_ace'
|
3
|
+
|
4
|
+
module CiscoAclIntp
|
5
|
+
# Extended Ace utilities for ace search
|
6
|
+
module AceSearchUtility
|
7
|
+
module_function
|
8
|
+
|
9
|
+
# Select protocol spec class for tcp/udp.
|
10
|
+
# @param [String] proto Protocol name.
|
11
|
+
# @return [Class] Class name.
|
12
|
+
def select_proto_class(proto)
|
13
|
+
case proto
|
14
|
+
when 'tcp'
|
15
|
+
AceTcpProtoSpec
|
16
|
+
when 'udp'
|
17
|
+
AceUdpProtoSpec
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [String] proto Protocol name.
|
22
|
+
# @param [Integer, String] port Port No./Name.
|
23
|
+
# @return [AceTcpProtoSpec, AceUdpProtoSpec] TCP/UDP port object.
|
24
|
+
def generate_port_obj(proto, port = nil)
|
25
|
+
port.nil? ? nil : select_proto_class(proto).new(port)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Generate port spec by protocol
|
29
|
+
# @param [String] proto Protocol name.
|
30
|
+
# @param [String, Symbol] opr Port operator.
|
31
|
+
# @param [Integer, String] begin_port Port No./Name.
|
32
|
+
# @param [Integer, String] end_port Port No./Name.
|
33
|
+
# @return [AcePortSpec] Port spec.
|
34
|
+
def port_spec_by_protocol(proto, opr, begin_port = nil, end_port = nil)
|
35
|
+
if opr.nil?
|
36
|
+
AcePortSpec.new(operator: :any) # any
|
37
|
+
else
|
38
|
+
AcePortSpec.new(
|
39
|
+
operator: opr,
|
40
|
+
begin_port: generate_port_obj(proto, begin_port),
|
41
|
+
end_port: generate_port_obj(proto, end_port)
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Generate Src/Dst search condition
|
47
|
+
# @param [AceIpProtoSpec] proto IP protocol info
|
48
|
+
# @param [String] ip IP address info
|
49
|
+
# @param [String, Symbol] opr Port operator
|
50
|
+
# @param [Integer, String] begin_port Port No./Name.
|
51
|
+
# @param [Integer, String] end_port Port No./Name.
|
52
|
+
def srcdst_condition(proto, ip, opr, begin_port = nil, end_port = nil)
|
53
|
+
case proto.name
|
54
|
+
when 'tcp', 'udp'
|
55
|
+
AceSrcDstSpec.new(
|
56
|
+
ipaddr: ip,
|
57
|
+
port_spec: port_spec_by_protocol(
|
58
|
+
proto.name, opr, begin_port, end_port
|
59
|
+
)
|
60
|
+
)
|
61
|
+
else
|
62
|
+
# if L3 protocol is not tcp/udp, it did not need port condition
|
63
|
+
AceSrcDstSpec.new(ipaddr: ip)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Generate hash key to slice
|
68
|
+
# @param [Symbol] pt Prefix of key
|
69
|
+
# @param [Symbol] key Postfix of key
|
70
|
+
# @return [Symbol]
|
71
|
+
def ptkey(pt, key)
|
72
|
+
[pt.to_s, key.to_s].join('_').intern
|
73
|
+
end
|
74
|
+
|
75
|
+
# Generate list of values sliced hash (args of srcdst_condition)
|
76
|
+
# @param [AceIpProtoSpec] proto_cond IP protocol condition
|
77
|
+
# @param [Symbol] pt Prefix of key
|
78
|
+
# @param [Hash] opts Option hash for slice
|
79
|
+
def slice_contains_opts(proto_cond, pt, opts)
|
80
|
+
[
|
81
|
+
proto_cond,
|
82
|
+
opts[ptkey(pt, :ip)],
|
83
|
+
opts[ptkey(pt, :operator)],
|
84
|
+
(opts[ptkey(pt, :port)] || opts[ptkey(pt, :begin_port)]),
|
85
|
+
opts[ptkey(pt, :end_port)]
|
86
|
+
]
|
87
|
+
end
|
88
|
+
|
89
|
+
# Generate ACE components
|
90
|
+
# @param [Hash] opts Options (target packet info)
|
91
|
+
# @see options is same as ExtendedAce#contains?
|
92
|
+
# @return [Array<AceIpProtoSpec, AceSrcDstSpec, AceSrcDstSpec>]
|
93
|
+
def search_conditions(opts)
|
94
|
+
proto_cond = AceIpProtoSpec.new(opts[:protocol])
|
95
|
+
[
|
96
|
+
proto_cond,
|
97
|
+
srcdst_condition(*slice_contains_opts(proto_cond, :src, opts)),
|
98
|
+
srcdst_condition(*slice_contains_opts(proto_cond, :dst, opts))
|
99
|
+
]
|
100
|
+
end
|
101
|
+
|
102
|
+
# Generate ACE search(contains?) conditions
|
103
|
+
# @param [Hash] opts Options (target packet info)
|
104
|
+
# @see options is same as ExtendedAce#contains?
|
105
|
+
# @return [ExtendedAce]
|
106
|
+
def target_ace(opts)
|
107
|
+
(proto_cond, src_cond, dst_cond) = search_conditions(opts)
|
108
|
+
ExtendedAce.new(
|
109
|
+
action: 'permit', protocol: proto_cond.name,
|
110
|
+
src: src_cond, dst: dst_cond
|
111
|
+
)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end # module
|
115
|
+
|
116
|
+
### Local variables:
|
117
|
+
### mode: Ruby
|
118
|
+
### coding: utf-8-unix
|
119
|
+
### indent-tabs-mode: nil
|
120
|
+
### End:
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'cisco_acl_intp/standard_ace'
|
3
|
+
|
4
|
+
module CiscoAclIntp
|
5
|
+
# ACE for extended access list
|
6
|
+
class ExtendedAce < StandardAce
|
7
|
+
# @param [AceIpProtoSpec] value L3/L4 protocol
|
8
|
+
# @return [AceIpProtoSpec]
|
9
|
+
attr_accessor :protocol
|
10
|
+
|
11
|
+
# @param [AceSrcDstSpec] value Destination spec object
|
12
|
+
# @return [AceSrcDstSpec]
|
13
|
+
attr_accessor :dst_spec
|
14
|
+
|
15
|
+
# @param [AceTcpFlagList] value
|
16
|
+
# TCP flags (used when '@protocol':tcp)
|
17
|
+
# @return [AceTcpFlagList]
|
18
|
+
attr_accessor :tcp_flags
|
19
|
+
|
20
|
+
# @param [AceOtherQualifierList] value
|
21
|
+
# TCP other qualifier list object (used when '@protocol':tcp)
|
22
|
+
# @return [AceOtherQualifierList]
|
23
|
+
attr_accessor :tcp_other_qualifiers
|
24
|
+
|
25
|
+
# Option,
|
26
|
+
# :src and :dst can handle multiple types of object generation,
|
27
|
+
# so that the argments can takes hash of AceSrcDstSpec.new or
|
28
|
+
# AceSrcDstSpec instance.
|
29
|
+
# :protocol and so on. (AceIpProtoSpec Object)
|
30
|
+
#
|
31
|
+
# about :protocol, it has specification of name and number
|
32
|
+
# (specified in internal of parser).
|
33
|
+
# basically, it is OK that specify only name.
|
34
|
+
# (does it convert name <=> number each oether?)
|
35
|
+
# (does it use number?
|
36
|
+
#
|
37
|
+
|
38
|
+
# Constructor
|
39
|
+
# @param [Hash] opts Options
|
40
|
+
# @option opts [String] :protocol L3/L4 protocol
|
41
|
+
# @option opts [Integer] :number Protocol/Port number
|
42
|
+
# @option opts [String] :action Action
|
43
|
+
# @option opts [AceSrcDstSpec] :src Source spec object
|
44
|
+
# @option opts [Hash] :src Source spec parmeters
|
45
|
+
# @option opts [AceSrcDstSpec] :dst Destination spec object
|
46
|
+
# @option opts [Hash] :dst Destination spec parmeters
|
47
|
+
# @option opts [AceTcpFlagList] :tcp_port_qualifier
|
48
|
+
# TCP Flags object
|
49
|
+
# @raise [AclArgumentError]
|
50
|
+
# @return [ExtendACE]
|
51
|
+
def initialize(opts)
|
52
|
+
super
|
53
|
+
@options = opts
|
54
|
+
@protocol = define_protocol
|
55
|
+
@dst_spec = define_dst_spec
|
56
|
+
@tcp_flags = define_tcp_flags
|
57
|
+
@tcp_other_qualifiers = nil # not yet.
|
58
|
+
end
|
59
|
+
|
60
|
+
# @param [ExtendACE] other RHS object
|
61
|
+
# @return [Boolean]
|
62
|
+
def ==(other)
|
63
|
+
@action == other.action &&
|
64
|
+
@protocol == other.protocol &&
|
65
|
+
@src_spec == other.src_spec &&
|
66
|
+
@dst_spec == other.dst_spec &&
|
67
|
+
@tcp_flags == other.tcp_flags
|
68
|
+
## does it need to compare? : tcp_other_qualifiers
|
69
|
+
end
|
70
|
+
|
71
|
+
# Generate string for Cisco IOS access list
|
72
|
+
# @return [String]
|
73
|
+
def to_s
|
74
|
+
format(
|
75
|
+
'%s %s %s %s %s %s',
|
76
|
+
tag_action(@action.to_s),
|
77
|
+
tag_protocol(@protocol.to_s),
|
78
|
+
@src_spec,
|
79
|
+
@dst_spec,
|
80
|
+
@tcp_flags,
|
81
|
+
@tcp_other_qualifiers
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Search matched ACE
|
86
|
+
# @param [ExtendedAce] other Target ACE
|
87
|
+
# @return [Boolean] Matched or not
|
88
|
+
# @see SingleAceBase#search_ace
|
89
|
+
def contains?(other)
|
90
|
+
super(other) &&
|
91
|
+
@protocol.contains?(other.protocol) &&
|
92
|
+
@dst_spec.contains?(other.dst_spec)
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
# Set instance variables
|
98
|
+
# return [AceIpProtoSpec] IP protocol object
|
99
|
+
# raise [AclArgumentError]
|
100
|
+
def define_protocol
|
101
|
+
if @options.key?(:protocol)
|
102
|
+
protocol = @options[:protocol]
|
103
|
+
case protocol
|
104
|
+
when AceIpProtoSpec
|
105
|
+
protocol
|
106
|
+
else
|
107
|
+
AceIpProtoSpec.new(protocol)
|
108
|
+
end
|
109
|
+
else
|
110
|
+
fail AclArgumentError, 'Not specified IP protocol'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Set instance variables
|
115
|
+
# @return [AceSrcDstSpec] Destination spec object
|
116
|
+
# @raise [AclArgumentError]
|
117
|
+
def define_dst_spec
|
118
|
+
if @options.key?(:dst)
|
119
|
+
dst = @options[:dst]
|
120
|
+
case dst
|
121
|
+
when Hash
|
122
|
+
AceSrcDstSpec.new(dst)
|
123
|
+
when AceSrcDstSpec
|
124
|
+
dst
|
125
|
+
else
|
126
|
+
fail AclArgumentError, 'Dst spec: unknown class'
|
127
|
+
end
|
128
|
+
else
|
129
|
+
fail AclArgumentError, 'Not specified dst spec'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Set instance variables
|
134
|
+
# @return [AceOtherQualifierList]
|
135
|
+
def define_tcp_flags
|
136
|
+
if @protocol.name == 'tcp' && @options.key?(:tcp_flags_qualifier)
|
137
|
+
@options[:tcp_flags_qualifier]
|
138
|
+
else
|
139
|
+
nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end # module
|
144
|
+
|
145
|
+
### Local variables:
|
146
|
+
### mode: Ruby
|
147
|
+
### coding: utf-8-unix
|
148
|
+
### indent-tabs-mode: nil
|
149
|
+
### End:
|