cisco_acl_intp 0.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.rubocop.yml +13 -0
- data/.travis.yml +3 -0
- data/.yardopts +4 -0
- data/Gemfile +19 -0
- data/LICENSE.txt +22 -0
- data/README.md +132 -0
- data/Rakefile +78 -0
- data/acl_examples/err-acl.txt +49 -0
- data/acl_examples/named-ext-acl.txt +12 -0
- data/acl_examples/named-std-acl.txt +6 -0
- data/acl_examples/numd-acl.txt +21 -0
- data/cisco_acl_intp.gemspec +31 -0
- data/lib/cisco_acl_intp/ace.rb +432 -0
- data/lib/cisco_acl_intp/ace_ip.rb +136 -0
- data/lib/cisco_acl_intp/ace_other_qualifiers.rb +102 -0
- data/lib/cisco_acl_intp/ace_port.rb +146 -0
- data/lib/cisco_acl_intp/ace_proto.rb +319 -0
- data/lib/cisco_acl_intp/ace_srcdst.rb +114 -0
- data/lib/cisco_acl_intp/ace_tcp_flags.rb +65 -0
- data/lib/cisco_acl_intp/acl.rb +272 -0
- data/lib/cisco_acl_intp/acl_base.rb +111 -0
- data/lib/cisco_acl_intp/parser.rb +3509 -0
- data/lib/cisco_acl_intp/parser.ry +1397 -0
- data/lib/cisco_acl_intp/scanner.rb +176 -0
- data/lib/cisco_acl_intp/scanner_special_token_handler.rb +66 -0
- data/lib/cisco_acl_intp/version.rb +5 -0
- data/lib/cisco_acl_intp.rb +9 -0
- data/spec/cisco_acl_intp/ace_ip_spec.rb +111 -0
- data/spec/cisco_acl_intp/ace_other_qualifier_spec.rb +63 -0
- data/spec/cisco_acl_intp/ace_port_spec.rb +214 -0
- data/spec/cisco_acl_intp/ace_proto_spec.rb +200 -0
- data/spec/cisco_acl_intp/ace_spec.rb +605 -0
- data/spec/cisco_acl_intp/ace_srcdst_spec.rb +296 -0
- data/spec/cisco_acl_intp/ace_tcp_flags_spec.rb +38 -0
- data/spec/cisco_acl_intp/acl_spec.rb +523 -0
- data/spec/cisco_acl_intp/cisco_acl_intp_spec.rb +7 -0
- data/spec/cisco_acl_intp/parser_spec.rb +53 -0
- data/spec/cisco_acl_intp/scanner_spec.rb +122 -0
- data/spec/conf/extacl_objgrp_token_seq.yml +36 -0
- data/spec/conf/extacl_token_seq.yml +88 -0
- data/spec/conf/extended_acl.yml +226 -0
- data/spec/conf/scanner_spec_data.yml +120 -0
- data/spec/conf/single_tokens.yml +235 -0
- data/spec/conf/stdacl_token_seq.yml +8 -0
- data/spec/conf/tokens1.yml +158 -0
- data/spec/conf/tokens2.yml +206 -0
- data/spec/parser_fullfill_patterns.rb +145 -0
- data/spec/spec_helper.rb +54 -0
- data/tools/check_acl.rb +48 -0
- metadata +159 -0
@@ -0,0 +1,176 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'strscan'
|
3
|
+
require 'cisco_acl_intp/scanner_special_token_handler'
|
4
|
+
|
5
|
+
module CiscoAclIntp
|
6
|
+
# Lexical analyzer (Scanner)
|
7
|
+
class Scanner
|
8
|
+
# include special tokens data and its handlers
|
9
|
+
include SpecialTokenHandler
|
10
|
+
|
11
|
+
# Constructor
|
12
|
+
# @return [Scanner]
|
13
|
+
def initialize
|
14
|
+
@arg_tokens = gen_arg_token_lists
|
15
|
+
end
|
16
|
+
|
17
|
+
# Scan ACL from file to parse
|
18
|
+
# @param [File] file File name
|
19
|
+
# @return [Array] Scanned tokens array (Queue)
|
20
|
+
def scan_file(file)
|
21
|
+
queue = []
|
22
|
+
file.each_line do |each|
|
23
|
+
queue.concat(scan_one_line(each))
|
24
|
+
end
|
25
|
+
queue.push [false, 'EOF']
|
26
|
+
end
|
27
|
+
|
28
|
+
# Scan ACL from variable
|
29
|
+
# @param [String] str Access list string
|
30
|
+
# @return [Array] Scanned tokens array (Queue)
|
31
|
+
def scan_line(str)
|
32
|
+
queue = []
|
33
|
+
str.split(/$/).each do |each|
|
34
|
+
each.chomp!
|
35
|
+
# add word separator at end of line
|
36
|
+
each.concat(' ')
|
37
|
+
queue.concat(scan_one_line(each))
|
38
|
+
end
|
39
|
+
queue.push [false, 'EOF']
|
40
|
+
end
|
41
|
+
|
42
|
+
# Scan ACL
|
43
|
+
# @param [String] line Access list string
|
44
|
+
# @return [Array] Scanned tokens array (Queue)
|
45
|
+
def scan_one_line(line)
|
46
|
+
run_scanning(line)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
# Scan a line
|
52
|
+
# @param [String] line ACL String
|
53
|
+
# @param [Array] queue Queue
|
54
|
+
# @return [Array] Scanned tokens array (Queue)
|
55
|
+
def run_scanning(line, queue = [])
|
56
|
+
ss = StringScanner.new(line)
|
57
|
+
until ss.eos?
|
58
|
+
case
|
59
|
+
when scan_match_arg_tokens(ss, queue)
|
60
|
+
when scan_match_acl_header(ss, queue)
|
61
|
+
when scan_match_ipaddr(ss, queue)
|
62
|
+
else scan_match_common(ss, queue)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
queue.push [:EOS, nil] # Add end-of-string
|
66
|
+
end
|
67
|
+
|
68
|
+
# Numbered ACL header checker
|
69
|
+
# @param [Integer] aclnum ACL number
|
70
|
+
# @return [Array] Token list
|
71
|
+
def check_numd_acl_type(aclnum)
|
72
|
+
if (1..99).include?(aclnum) || (1300..1999).include?(aclnum)
|
73
|
+
[:NUMD_STD_ACL, aclnum]
|
74
|
+
elsif (100..199).include?(aclnum) || (2000..2699).include?(aclnum)
|
75
|
+
[:NUMD_EXT_ACL, aclnum]
|
76
|
+
else
|
77
|
+
[:UNKNOWN, "access-list #{aclnum}"]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Scanner of acl header
|
82
|
+
# @param [StringScanner] ss Scanned ACL line
|
83
|
+
# @param [Array] queue Queue
|
84
|
+
# @return [Boolean] if line matched acl header
|
85
|
+
def scan_match_acl_header(ss, queue)
|
86
|
+
case
|
87
|
+
when ss.scan(/\s*!.*$/), ss.scan(/\s*#.*$/)
|
88
|
+
## "!/# comment" and whitespace line, NO-OP
|
89
|
+
when ss.scan(/\s+/), ss.scan(/\A\s*\Z/)
|
90
|
+
## whitespace, NO-OP
|
91
|
+
# queue.push [:WHITESPACE, ""] # for debug
|
92
|
+
when ss.scan(/(?:access-list)\s+(\d+)\s/)
|
93
|
+
## Numbered ACL Header
|
94
|
+
## numbered acl has no difference
|
95
|
+
## in format between Standard and Extended...
|
96
|
+
queue.push check_numd_acl_type(ss[1].to_i)
|
97
|
+
when ss.scan(/(ip\s+access\-list)\s/)
|
98
|
+
## Named ACL Header
|
99
|
+
queue.push [:NAMED_ACL, ss[1]]
|
100
|
+
end
|
101
|
+
ss.matched?
|
102
|
+
end
|
103
|
+
|
104
|
+
# Scanner of IP address
|
105
|
+
# @param [StringScanner] ss Scanned ACL line
|
106
|
+
# @param [Array] queue Queue
|
107
|
+
# @return [Boolean] if line matched IP address
|
108
|
+
def scan_match_ipaddr(ss, queue)
|
109
|
+
case
|
110
|
+
when ss.scan(/(\d+\.\d+\.\d+\.\d+)\s/)
|
111
|
+
## IP Address
|
112
|
+
queue.push [:IPV4_ADDR, ss[1]]
|
113
|
+
when ss.scan(/(\d+\.\d+\.\d+\.\d+)(\/)(\d+)\s/)
|
114
|
+
## IP Address of 'ip/mask' notation
|
115
|
+
queue.push [:IPV4_ADDR, ss[1]]
|
116
|
+
queue.push ['/', ss[2]]
|
117
|
+
queue.push [:NUMBER, ss[3].to_i]
|
118
|
+
end
|
119
|
+
ss.matched?
|
120
|
+
end
|
121
|
+
|
122
|
+
# Scanner of common tokens
|
123
|
+
# @param [StringScanner] ss Scanned ACL line
|
124
|
+
# @param [Array] queue Queue
|
125
|
+
# @return [Boolean] if line matched tokens
|
126
|
+
def scan_match_common(ss, queue)
|
127
|
+
case
|
128
|
+
when ss.scan(/(\d+)\s/)
|
129
|
+
## Number
|
130
|
+
queue.push [:NUMBER, ss[1].to_i]
|
131
|
+
when ss.scan(/([\+\-]?#{STR_REGEXP})/)
|
132
|
+
## Tokens (echo back)
|
133
|
+
## defined in module SpecialTokenHandler
|
134
|
+
## plus/minus used in tcp flag token e.g. +syn -ack
|
135
|
+
queue.push token_list(ss[1])
|
136
|
+
else
|
137
|
+
## do not match any?
|
138
|
+
## then scanned whole line and
|
139
|
+
## put in queue as unknown.
|
140
|
+
ss.scan(/(.*)$/) # match all
|
141
|
+
queue.push [:UNKNOWN, ss[1]]
|
142
|
+
end
|
143
|
+
ss.matched?
|
144
|
+
end
|
145
|
+
|
146
|
+
# Scanner of special tokens
|
147
|
+
# @param [StringScanner] ss Scanned ACL line
|
148
|
+
# @param [Array] queue Queue
|
149
|
+
# @return [Boolean] if line matched tokens
|
150
|
+
def scan_match_arg_tokens(ss, queue)
|
151
|
+
@arg_tokens.each do |(str, length)|
|
152
|
+
if ss.scan(/#{str}/)
|
153
|
+
(1...length).each do |idx|
|
154
|
+
queue.push token_list(ss[idx])
|
155
|
+
end
|
156
|
+
queue.push [:STRING, ss[length]] # last element
|
157
|
+
break
|
158
|
+
end
|
159
|
+
end
|
160
|
+
ss.matched?
|
161
|
+
end
|
162
|
+
|
163
|
+
# Generate echo-backed token array
|
164
|
+
# @param [String] token Token
|
165
|
+
# @return [Array] Token array for scanner queue
|
166
|
+
def token_list(token)
|
167
|
+
[token, token]
|
168
|
+
end
|
169
|
+
end # class Scanner
|
170
|
+
end # module
|
171
|
+
|
172
|
+
### Local variables:
|
173
|
+
### mode: Ruby
|
174
|
+
### coding: utf-8-unix
|
175
|
+
### indent-tabs-mode: nil
|
176
|
+
### End:
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'strscan'
|
3
|
+
|
4
|
+
module CiscoAclIntp
|
5
|
+
# Data and Handler functions of special tokens
|
6
|
+
module SpecialTokenHandler
|
7
|
+
# STRING token regexp:
|
8
|
+
# first letter is alphabet or digit
|
9
|
+
STR_REGEXP = '[a-zA-Z\d]\S*'
|
10
|
+
|
11
|
+
# Tokens that takes string parameter
|
12
|
+
STRING_ARG_TOKENS = [
|
13
|
+
['remark', :leftover],
|
14
|
+
['description', :leftover],
|
15
|
+
['extended', :word],
|
16
|
+
['standard', :word],
|
17
|
+
['dynamic', :word],
|
18
|
+
['log-input', :word],
|
19
|
+
['log', :word],
|
20
|
+
['time-range', :word],
|
21
|
+
['reflect', :word],
|
22
|
+
['evaluate', :word],
|
23
|
+
['object-group', 'network', :word],
|
24
|
+
['object-group', 'service', :word],
|
25
|
+
['object-group', :word], # longest match
|
26
|
+
['group-object', :word],
|
27
|
+
]
|
28
|
+
|
29
|
+
# Conversion table of string-tokens
|
30
|
+
SYMBOL_TO_REGEXPSTR = {
|
31
|
+
word: ['(', STR_REGEXP, ')'].join,
|
32
|
+
leftover: '(.*)$'
|
33
|
+
}
|
34
|
+
|
35
|
+
# Convert STRING_ARG_TOKENS to Regexp string
|
36
|
+
# @param [Array] set Special tokens set
|
37
|
+
# @returns [String] Regexp string
|
38
|
+
def convert_tokens_to_regexpstr(set)
|
39
|
+
# puts "## set #{set}"
|
40
|
+
set.map do |each|
|
41
|
+
case each
|
42
|
+
when String
|
43
|
+
'(' + each + ')'
|
44
|
+
when Symbol
|
45
|
+
SYMBOL_TO_REGEXPSTR[each]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Generate regexp string list for scanner
|
51
|
+
# @return [Array] set of regexp and number of token
|
52
|
+
def gen_arg_token_lists
|
53
|
+
STRING_ARG_TOKENS.map do |each|
|
54
|
+
re_str_list = convert_tokens_to_regexpstr(each)
|
55
|
+
# puts "### #{re_str_list}"
|
56
|
+
[re_str_list.join('\s+'), each.length]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end # module SpecialTokenMgr
|
60
|
+
end # module CiscoAclIntp
|
61
|
+
|
62
|
+
### Local variables:
|
63
|
+
### mode: Ruby
|
64
|
+
### coding: utf-8-unix
|
65
|
+
### indent-tabs-mode: nil
|
66
|
+
### End:
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe AceIpSpec do
|
5
|
+
describe '#to_s' do
|
6
|
+
it 'should be "192.168.15.15 0.0.7.6"' do
|
7
|
+
ip = AceIpSpec.new(
|
8
|
+
ipaddr: '192.168.15.15',
|
9
|
+
wildcard: '0.0.7.6'
|
10
|
+
)
|
11
|
+
ip.to_s.should be_aclstr('192.168.8.9 0.0.7.6')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should be "any"' do
|
15
|
+
ip = AceIpSpec.new(
|
16
|
+
ipaddr: '0.0.0.0',
|
17
|
+
wildcard: '255.255.255.255'
|
18
|
+
)
|
19
|
+
ip.to_s.should be_aclstr('any')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should be "any" with full-bit wildcard mask' do
|
23
|
+
ip = AceIpSpec.new(
|
24
|
+
ipaddr: '192.168.15.15',
|
25
|
+
wildcard: '255.255.255.255'
|
26
|
+
)
|
27
|
+
ip.to_s.should be_aclstr('any')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should be "any" with zero-ip' do
|
31
|
+
ip = AceIpSpec.new(
|
32
|
+
ipaddr: '0.0.0.0',
|
33
|
+
wildcard: '0.0.7.6'
|
34
|
+
)
|
35
|
+
ip.to_s.should be_aclstr('any')
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should be "host 192.168.15.15"' do
|
39
|
+
ip = AceIpSpec.new(
|
40
|
+
ipaddr: '192.168.15.15',
|
41
|
+
wildcard: '0.0.0.0'
|
42
|
+
)
|
43
|
+
ip.to_s.should be_aclstr('host 192.168.15.15')
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should be "192.168.14.0 0.0.1.255" with netmask /23' do
|
47
|
+
ip = AceIpSpec.new(
|
48
|
+
ipaddr: '192.168.15.15',
|
49
|
+
netmask: 23
|
50
|
+
)
|
51
|
+
ip.to_s.should be_aclstr('192.168.14.0 0.0.1.255')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should be "any" with netmask /0' do
|
55
|
+
ip = AceIpSpec.new(
|
56
|
+
ipaddr: '192.168.15.15',
|
57
|
+
netmask: 0
|
58
|
+
)
|
59
|
+
ip.to_s.should be_aclstr('any')
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should be "host 192.168.15.15" with netmask /32' do
|
63
|
+
ip = AceIpSpec.new(
|
64
|
+
ipaddr: '192.168.15.15',
|
65
|
+
netmask: 32
|
66
|
+
)
|
67
|
+
ip.to_s.should be_aclstr('host 192.168.15.15')
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should be "host 192.168.15.15" in default' do
|
71
|
+
ip = AceIpSpec.new(
|
72
|
+
ipaddr: '192.168.15.15'
|
73
|
+
)
|
74
|
+
ip.to_s.should be_aclstr('host 192.168.15.15')
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'Argument Error Case' do
|
78
|
+
it 'raise error without ipaddr' do
|
79
|
+
lambda do
|
80
|
+
AceIpSpec.new(
|
81
|
+
netmask: 32
|
82
|
+
)
|
83
|
+
end.should raise_error(AclArgumentError)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'raise error with invalid ipaddr' do
|
87
|
+
lambda do
|
88
|
+
AceIpSpec.new(
|
89
|
+
ipaddr: '192.168.15.256'
|
90
|
+
)
|
91
|
+
end.should raise_error
|
92
|
+
lambda do
|
93
|
+
AceIpSpec.new(
|
94
|
+
ipaddr: '192.168.250.3.3'
|
95
|
+
)
|
96
|
+
end.should raise_error
|
97
|
+
lambda do
|
98
|
+
AceIpSpec.new(
|
99
|
+
ipaddr: '192,168.250.3'
|
100
|
+
)
|
101
|
+
end.should raise_error
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
### Local variables:
|
108
|
+
### mode: Ruby
|
109
|
+
### coding: utf-8-unix
|
110
|
+
### indent-tabs-mode: nil
|
111
|
+
### End:
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe AceLogSpec do
|
5
|
+
describe '#to_s' do
|
6
|
+
it 'should be log without cookie' do
|
7
|
+
log = AceLogSpec.new
|
8
|
+
log.to_s.should be_aclstr('log')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should be log-input without cookie string' do
|
12
|
+
log = AceLogSpec.new('', true)
|
13
|
+
log.to_s.should be_aclstr('log-input')
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should be log with cookie' do
|
17
|
+
log = AceLogSpec.new('Cookie0123')
|
18
|
+
log.to_s.should be_aclstr('log Cookie0123')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should be log-input with cookie string' do
|
22
|
+
log = AceLogSpec.new('log', true)
|
23
|
+
log.to_s.should be_aclstr('log-input log')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe AceRecursiveQualifier do
|
29
|
+
describe '#to_s' do
|
30
|
+
it 'should be reflect spec string' do
|
31
|
+
rcsv = AceRecursiveQualifier.new('established')
|
32
|
+
rcsv.to_s.should be_aclstr('reflect established')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should be raised error' do
|
36
|
+
lambda do
|
37
|
+
AceRecursiveQualifier.new('')
|
38
|
+
end.should raise_error(AclArgumentError)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe AceOtherQualifierList do
|
44
|
+
describe '#to_s' do
|
45
|
+
before do
|
46
|
+
@oq1 = AceLogSpec.new
|
47
|
+
@oq2 = AceRecursiveQualifier.new('iptraffic')
|
48
|
+
@list = AceOtherQualifierList.new
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should be size 0 when empty list'do
|
52
|
+
@list.size.should be_zero
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should count-up size when added AceTcpFlag objects' do
|
56
|
+
@list.push @oq1
|
57
|
+
@list.size.should eq 1
|
58
|
+
@list.push @oq2
|
59
|
+
@list.size.should eq 2
|
60
|
+
@list.to_s.should be_aclstr('log reflect iptraffic')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe AcePortSpec do
|
5
|
+
describe '#new' do
|
6
|
+
it 'shoud be error with unknown operator' do
|
7
|
+
lambda do
|
8
|
+
AcePortSpec.new(
|
9
|
+
operator: 'equal',
|
10
|
+
port: 443
|
11
|
+
)
|
12
|
+
end.should raise_error(AclArgumentError)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should be error with invalid ports' do
|
16
|
+
lambda do
|
17
|
+
AcePortSpec.new(
|
18
|
+
operator: 'range',
|
19
|
+
begin_port: 443,
|
20
|
+
end_port: 139
|
21
|
+
)
|
22
|
+
end.should raise_error(AclArgumentError)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#to_s' do
|
27
|
+
before do
|
28
|
+
@p1 = AceTcpProtoSpec.new(number: 22)
|
29
|
+
@p2 = AceTcpProtoSpec.new(number: 80)
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'Normal case' do
|
33
|
+
it 'should be "eq 22"' do
|
34
|
+
p = AcePortSpec.new(
|
35
|
+
operator: 'eq', port: @p1
|
36
|
+
)
|
37
|
+
p.to_s.should be_aclstr('eq 22')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should be "lt www"' do
|
41
|
+
p = AcePortSpec.new(
|
42
|
+
operator: 'lt', port: @p2
|
43
|
+
)
|
44
|
+
p.to_s.should be_aclstr('lt www')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should be "gt www"' do
|
48
|
+
p = AcePortSpec.new(
|
49
|
+
operator: 'gt', port: @p2
|
50
|
+
)
|
51
|
+
p.to_s.should be_aclstr('gt www')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should be "range 22 www"' do
|
55
|
+
p = AcePortSpec.new(
|
56
|
+
operator: 'range',
|
57
|
+
begin_port: @p1, end_port: @p2
|
58
|
+
)
|
59
|
+
p.to_s.should be_aclstr('range 22 www')
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should be empty when any port' do
|
63
|
+
p = AcePortSpec.new(
|
64
|
+
operator: 'any',
|
65
|
+
begin_port: @p1, end_port: @p2
|
66
|
+
)
|
67
|
+
p.to_s.should be_empty
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
context 'Argument error case' do
|
72
|
+
it 'raise error when not specified operator' do
|
73
|
+
lambda do
|
74
|
+
AcePortSpec.new(
|
75
|
+
end_port: @p1
|
76
|
+
)
|
77
|
+
end.should raise_error(AclArgumentError)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'raise error when not specified begin_port' do
|
81
|
+
lambda do
|
82
|
+
AcePortSpec.new(
|
83
|
+
operator: 'eq',
|
84
|
+
end_port: @p1
|
85
|
+
)
|
86
|
+
end.should raise_error(AclArgumentError)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'raise error when wrong port sequence' do
|
90
|
+
lambda do
|
91
|
+
AcePortSpec.new(
|
92
|
+
operator: 'range',
|
93
|
+
begin_port: @p2, end_port: @p1
|
94
|
+
)
|
95
|
+
end.should raise_error(AclArgumentError)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#matches?' do
|
101
|
+
before do
|
102
|
+
@p1 = AceTcpProtoSpec.new(number: 22)
|
103
|
+
@p2 = AceTcpProtoSpec.new(number: 32_768)
|
104
|
+
|
105
|
+
@any = AcePortSpec.new(
|
106
|
+
operator: 'any'
|
107
|
+
)
|
108
|
+
@eq1 = AcePortSpec.new(
|
109
|
+
operator: 'eq', begin_port: @p1
|
110
|
+
)
|
111
|
+
@neq1 = AcePortSpec.new(
|
112
|
+
operator: 'neq', port: @p1
|
113
|
+
)
|
114
|
+
@lt1 = AcePortSpec.new(
|
115
|
+
operator: 'lt', port: @p1
|
116
|
+
)
|
117
|
+
@gt1 = AcePortSpec.new(
|
118
|
+
operator: 'gt', port: @p1
|
119
|
+
)
|
120
|
+
@range = AcePortSpec.new(
|
121
|
+
operator: 'range',
|
122
|
+
port: @p1, end_port: @p2
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'match any if valid port range' do
|
127
|
+
lambda do
|
128
|
+
@any.matches?(-1)
|
129
|
+
end.should raise_error(AclArgumentError)
|
130
|
+
@any.matches?(0).should be_true
|
131
|
+
@any.matches?(21).should be_true
|
132
|
+
@any.matches?(22).should be_true
|
133
|
+
@any.matches?(23).should be_true
|
134
|
+
@any.matches?(65_535).should be_true
|
135
|
+
lambda do
|
136
|
+
@any.matches?(65_536)
|
137
|
+
end.should raise_error(AclArgumentError)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'match correct number by op:eq' do
|
141
|
+
lambda do
|
142
|
+
@eq1.matches?(-1)
|
143
|
+
end.should raise_error(AclArgumentError)
|
144
|
+
@eq1.matches?(0).should be_false
|
145
|
+
@eq1.matches?(21).should be_false
|
146
|
+
@eq1.matches?(22).should be_true
|
147
|
+
@eq1.matches?(23).should be_false
|
148
|
+
@eq1.matches?(65_535).should be_false
|
149
|
+
lambda do
|
150
|
+
@eq1.matches?(65_536)
|
151
|
+
end.should raise_error(AclArgumentError)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'match correct number by op:neq' do
|
155
|
+
lambda do
|
156
|
+
@neq1.matches?(-1)
|
157
|
+
end.should raise_error(AclArgumentError)
|
158
|
+
@neq1.matches?(0).should be_true
|
159
|
+
@neq1.matches?(21).should be_true
|
160
|
+
@neq1.matches?(22).should be_false
|
161
|
+
@neq1.matches?(23).should be_true
|
162
|
+
@neq1.matches?(65_535).should be_true
|
163
|
+
lambda do
|
164
|
+
@neq1.matches?(65_536)
|
165
|
+
end.should raise_error(AclArgumentError)
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'match lower number by op:lt' do
|
169
|
+
lambda do
|
170
|
+
@lt1.matches?(-1)
|
171
|
+
end.should raise_error(AclArgumentError)
|
172
|
+
@lt1.matches?(0).should be_true
|
173
|
+
@lt1.matches?(21).should be_true
|
174
|
+
@lt1.matches?(22).should be_false
|
175
|
+
@lt1.matches?(23).should be_false
|
176
|
+
@lt1.matches?(65_535).should be_false
|
177
|
+
lambda do
|
178
|
+
@lt1.matches?(65_536)
|
179
|
+
end.should raise_error(AclArgumentError)
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'match lower number by op:gt' do
|
183
|
+
lambda do
|
184
|
+
@gt1.matches?(-1)
|
185
|
+
end.should raise_error(AclArgumentError)
|
186
|
+
@gt1.matches?(0).should be_false
|
187
|
+
@gt1.matches?(21).should be_false
|
188
|
+
@gt1.matches?(22).should be_false
|
189
|
+
@gt1.matches?(23).should be_true
|
190
|
+
@gt1.matches?(65_535).should be_true
|
191
|
+
lambda do
|
192
|
+
@gt1.matches?(65_536)
|
193
|
+
end.should raise_error(AclArgumentError)
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'match lower number by op:range' do
|
197
|
+
lambda do
|
198
|
+
@range.matches?(-1)
|
199
|
+
end.should raise_error(AclArgumentError)
|
200
|
+
@range.matches?(0).should be_false
|
201
|
+
@range.matches?(21).should be_false
|
202
|
+
@range.matches?(22).should be_true
|
203
|
+
@range.matches?(23).should be_true
|
204
|
+
@range.matches?(32_767).should be_true
|
205
|
+
@range.matches?(32_768).should be_true
|
206
|
+
@range.matches?(32_769).should be_false
|
207
|
+
@range.matches?(65_535).should be_false
|
208
|
+
lambda do
|
209
|
+
@range.matches?(65_536)
|
210
|
+
end.should raise_error(AclArgumentError)
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
end
|