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
@@ -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 group is not implemented yet.
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
- sprintf('%s %s', @ip_spec, @port_spec)
55
+ format '%s %s', @ip_spec, @port_spec
56
56
  end
57
57
 
58
- # Check address and port number matches this object or not.
59
- # @param [String] address IP address (dotted notation)
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
- # @example Example of AceSrcDstSpec#matches?
64
- # AceSrcDstSpec#matches?('192.168.3.3') # /32 host and port any
65
- # AceSrcDstSpec#matches?('172.30.240.0/24', '80') # a subnet and port 80
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 [Integer,String] port Port No.
70
+ # @param [AcePortSpec] port_spec TCP/UDP Port spec
79
71
  # @return [Boolean]
80
- def matches_port?(port)
81
- case port
82
- when nil, 'any'
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 [String] address IP address (dotted notation)
77
+ # Check address match (by NetAddr)
78
+ # @param [AceIpSpec] ip_spec IP address spec.
91
79
  # @return [Boolean]
92
- def matches_address?(address)
93
- case address
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
- @ip_spec.matches?(address)
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
- def initialize
44
- @list = []
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 == other.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
@@ -1,259 +1,9 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  require 'forwardable'
4
- require 'cisco_acl_intp/ace'
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
@@ -53,7 +53,7 @@ module CiscoAclIntp
53
53
  when :term
54
54
  TERM_COLOR_TABLE[tag]
55
55
  when :html
56
- %Q{<span class="acltag_#{tag.to_s}">}
56
+ %Q(<span class="acltag_#{tag}">)
57
57
  else
58
58
  ''
59
59
  end
@@ -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: