cisco_acl_intp 0.0.1 → 0.0.2
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/.coveralls.yml +1 -0
- data/.travis.yml +2 -0
- data/.yardopts +1 -1
- data/Gemfile +5 -1
- data/README.md +76 -22
- data/Rakefile +18 -6
- data/cisco_acl_intp.gemspec +5 -5
- data/lib/cisco_acl_intp.rb +8 -0
- data/lib/cisco_acl_intp/ace.rb +36 -39
- data/lib/cisco_acl_intp/ace_ip.rb +73 -31
- data/lib/cisco_acl_intp/ace_other_qualifiers.rb +2 -2
- data/lib/cisco_acl_intp/ace_port.rb +114 -28
- data/lib/cisco_acl_intp/ace_proto.rb +160 -73
- data/lib/cisco_acl_intp/ace_srcdst.rb +57 -25
- data/lib/cisco_acl_intp/ace_tcp_flags.rb +1 -1
- data/lib/cisco_acl_intp/acl.rb +81 -35
- data/lib/cisco_acl_intp/acl_base.rb +65 -66
- data/lib/cisco_acl_intp/parser.rb +914 -1037
- data/lib/cisco_acl_intp/parser.ry +68 -215
- data/lib/cisco_acl_intp/parser_api.rb +248 -0
- data/lib/cisco_acl_intp/scanner.rb +58 -63
- data/lib/cisco_acl_intp/scanner_special_token_handler.rb +2 -4
- data/lib/cisco_acl_intp/version.rb +9 -1
- data/spec/cisco_acl_intp/ace_ip_spec.rb +45 -0
- data/spec/cisco_acl_intp/ace_port_spec.rb +119 -0
- data/spec/cisco_acl_intp/ace_proto_spec.rb +40 -1
- data/spec/cisco_acl_intp/ace_spec.rb +3 -3
- data/spec/cisco_acl_intp/ace_srcdst_spec.rb +95 -1
- data/spec/cisco_acl_intp/acl_base_spec.rb +60 -0
- data/spec/cisco_acl_intp/acl_spec.rb +2 -0
- data/spec/cisco_acl_intp/cisco_acl_intp_spec.rb +8 -0
- data/spec/cisco_acl_intp/parser_spec.rb +80 -2
- data/spec/cisco_acl_intp/scanner_spec.rb +0 -1
- data/spec/conf/extended_acl.yml +18 -18
- data/spec/parser_fullfill_patterns.rb +3 -3
- data/spec/spec_helper.rb +6 -0
- data/tools/check_acl.rb +23 -5
- metadata +27 -23
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d664d74e52b4738c1835532f0fecefe1ee162ece
|
|
4
|
+
data.tar.gz: 56a40d167de808a4bf0ef778d8f443b01c408a22
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 63c07906a0c2910a1cdbb6cb53b02cb9ef36c32b4138223c400147d8447f101b9c44fb9af211363a9a79be6f4dde533f448483975cb132fd6461a4e49a7cf463
|
|
7
|
+
data.tar.gz: c5208c436298dde049720eb9b5f15f41b09d482b696aa592c95220ec5fc6f779f2e8b4aebd2dda7539946d8eded55cdbfc4ba1a1b871afebefb1daf88b5d9cc2
|
data/.coveralls.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
service_name: travis-ci
|
data/.travis.yml
CHANGED
data/.yardopts
CHANGED
data/Gemfile
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
1
3
|
source 'https://rubygems.org'
|
|
2
4
|
|
|
3
5
|
# Specify your gem's dependencies in cisco_acl_intp.gemspec
|
|
4
6
|
gemspec
|
|
5
7
|
|
|
6
8
|
group :development, :test do
|
|
9
|
+
gem 'coveralls', require: false
|
|
7
10
|
gem 'racc', '~> 1.4.11'
|
|
8
11
|
gem 'rake', '~> 10.1.1'
|
|
12
|
+
gem 'reek', '~> 1.3.6'
|
|
9
13
|
gem 'rspec', '~> 2.14.1'
|
|
10
|
-
gem 'rubocop', '~> 0.
|
|
14
|
+
gem 'rubocop', '~> 0.18.1' if RUBY_VERSION >= '1.9.0'
|
|
11
15
|
gem 'simplecov', '~> 0.8.2' if RUBY_VERSION >= '1.9.0'
|
|
12
16
|
gem 'yard', '~> 0.8.7'
|
|
13
17
|
end
|
data/README.md
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
# CiscoAclIntp
|
|
2
|
+
[](http://badge.fury.io/rb/cisco_acl_intp)
|
|
3
|
+
[](https://travis-ci.org/stereocat/cisco_acl_intp)
|
|
4
|
+
[](https://gemnasium.com/stereocat/cisco_acl_intp)
|
|
5
|
+
[](https://coveralls.io/r/stereocat/cisco_acl_intp?branch=master)
|
|
2
6
|
|
|
3
7
|
CiscoAclIntp is a interpreter of Cisco IOS access control list (ACL).
|
|
4
8
|
|
|
@@ -52,28 +56,70 @@ CiscoAclIntp parser and output parser results.
|
|
|
52
56
|
In directory `acl_examples`, there are some Cisco IOS ACL sample
|
|
53
57
|
files. Run `check_acl.rb` with ACL sample files, like below.
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
59
|
+
```
|
|
60
|
+
$ ruby tools/check_acl.rb -c term -f acl_examples/err-acl.txt
|
|
61
|
+
--------------------
|
|
62
|
+
in acl: 100, line: 6, near value: udp, (token: "udp")
|
|
63
|
+
in acl: 100, line: 8, near value: 100, (token: NUMBER)
|
|
64
|
+
in acl: 100, line: 11, Wrong protocol number: 256
|
|
65
|
+
in acl: 100, line: 14, near value: hoge, (token: error)
|
|
66
|
+
in acl: FA8-OUT, line: 4, Wrong protocol number: 65536
|
|
67
|
+
in acl: FA8-OUT, line: 7, Provided wildcard mask failed validation: 0.0.240.256 is invalid (IPv4 octets should be between 0 and 255).
|
|
68
|
+
in acl: FA8-OUT, line: 13, near value: up, (token: error)
|
|
69
|
+
--------------------
|
|
70
|
+
acl name : 1
|
|
71
|
+
access-list 1 permit 192.168.0.0 0.0.255.255
|
|
72
|
+
access-list 1 deny any log
|
|
73
|
+
acl name : 100
|
|
74
|
+
access-list 100 remark General Internet Access
|
|
75
|
+
access-list 100 permit icmp any any
|
|
76
|
+
access-list 100 permit ip 192.168.0.0 0.0.255.255 any
|
|
77
|
+
access-list 100 permit tcp any host 210.197.74.200
|
|
78
|
+
access-list 100 remark !wrong acl number!
|
|
79
|
+
access-list 100 remark !------cleared------!
|
|
80
|
+
access-list 100 remark !wrong header! caccess-list
|
|
81
|
+
access-list 100 remark !------cleared------!
|
|
82
|
+
access-list 100 permit 41 any host 192.88.99.1
|
|
83
|
+
access-list 100 remark !wrong ip proto number!
|
|
84
|
+
access-list 100 !! error !! 192.88.99.1
|
|
85
|
+
access-list 100 remark !------cleared------!
|
|
86
|
+
access-list 100 remark !wrong ip proto!
|
|
87
|
+
access-list 100 !! error !! 192.88.99.1
|
|
88
|
+
access-list 100 remark !------cleared------!
|
|
89
|
+
access-list 100 permit ip any host 192.88.99.1
|
|
90
|
+
access-list 100 remark others
|
|
91
|
+
access-list 100 permit tcp any eq 0 any eq 0
|
|
92
|
+
access-list 100 permit udp any eq 0 any eq 0
|
|
93
|
+
access-list 100 deny ip any any log
|
|
94
|
+
acl name : 10
|
|
95
|
+
access-list 10 !! error !! ntp
|
|
96
|
+
acl name : 110
|
|
97
|
+
access-list 110 remark SPLIT_VPN
|
|
98
|
+
access-list 110 permit ip 192.168.0.0 0.0.255.255 any
|
|
99
|
+
acl name : FA8-OUT
|
|
100
|
+
ip access-list extended FA8-OUT
|
|
101
|
+
deny udp any any eq bootpc
|
|
102
|
+
deny udp any any eq bootps
|
|
103
|
+
remark !argment error! 65536
|
|
104
|
+
!! error !! 65536
|
|
105
|
+
remark !------cleared------!
|
|
106
|
+
remark !argment error! 255 => 256
|
|
107
|
+
!! error !! 80
|
|
108
|
+
remark !------cleared------!
|
|
109
|
+
remark network access-list remark!!
|
|
110
|
+
permit tcp any any established
|
|
111
|
+
deny tcp any any syn rst
|
|
112
|
+
remark !syntax error! tcp -> tp (typo)
|
|
113
|
+
!! error !! hoge
|
|
114
|
+
remark !------cleared------!
|
|
115
|
+
permit ip any any log
|
|
116
|
+
acl name : remote-ipv4
|
|
117
|
+
ip access-list standard remote-ipv4
|
|
118
|
+
permit 192.168.0.0 0.0.255.255
|
|
119
|
+
remark standard access-list last deny!?
|
|
120
|
+
deny any log
|
|
121
|
+
$
|
|
122
|
+
```
|
|
77
123
|
|
|
78
124
|
By putting `-c` (`--color`) option, `check_acl.rb` outputs
|
|
79
125
|
**color-coded ACL** according to type of each word. It can parse
|
|
@@ -117,8 +163,16 @@ table is "ACL object". "ACL object" is build by ACL components. For
|
|
|
117
163
|
example, source/destination address obj, action obj, tcp/udp protocol
|
|
118
164
|
obj,... See more detail in documents (see also, Documents section)
|
|
119
165
|
|
|
166
|
+
### ACL Varidator Web Frontend
|
|
167
|
+
|
|
168
|
+
Front-end of ACL Varidator is at
|
|
169
|
+
[github](https://github.com/stereocat/cisco_acl_web). It not only can
|
|
170
|
+
parse (with CLI tool, it can only parse), but also search for ACL(ACE).
|
|
171
|
+
|
|
120
172
|
## Documents
|
|
121
173
|
|
|
174
|
+
* [API document generated with YARD](http://rubydoc.info/gems/cisco_acl_intp/)
|
|
175
|
+
|
|
122
176
|
It can generate documents with YARD.
|
|
123
177
|
|
|
124
178
|
$ rake yard
|
data/Rakefile
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
1
3
|
require 'bundler/gem_tasks'
|
|
2
4
|
require 'rspec/core/rake_task'
|
|
3
5
|
require 'rake/clean'
|
|
6
|
+
require 'yard'
|
|
7
|
+
require 'yard/rake/yardoc_task'
|
|
8
|
+
require 'reek/rake/task'
|
|
4
9
|
|
|
5
10
|
LIB_DIR = './lib'
|
|
6
11
|
PACKAGE_NAME = 'cisco_acl_intp'
|
|
@@ -23,7 +28,8 @@ CLOBBER.include(
|
|
|
23
28
|
CLASS_GRAPH_PNG
|
|
24
29
|
)
|
|
25
30
|
|
|
26
|
-
task default:
|
|
31
|
+
task default: :travis
|
|
32
|
+
task travis: [:parser, :spec, :rubocop]
|
|
27
33
|
task parser: [PARSER_RUBY]
|
|
28
34
|
task spec: [SPEC_DATA_DIR]
|
|
29
35
|
|
|
@@ -47,12 +53,9 @@ RSpec::Core::RakeTask.new(fullspec: [:fullfill]) do |spec|
|
|
|
47
53
|
spec.rspec_opts = '--format documentation --color'
|
|
48
54
|
end
|
|
49
55
|
|
|
50
|
-
# documentation by yard
|
|
51
|
-
require 'yard'
|
|
52
|
-
require 'yard/rake/yardoc_task'
|
|
53
56
|
YARD::Rake::YardocTask.new do |task|
|
|
54
57
|
# yardoc options in .yardopts
|
|
55
|
-
task.files = ["#{LIB_DIR}/**/*.rb"]
|
|
58
|
+
task.files = FileList["#{LIB_DIR}/**/*.rb"]
|
|
56
59
|
end
|
|
57
60
|
|
|
58
61
|
task :docgraph do
|
|
@@ -61,7 +64,16 @@ task :docgraph do
|
|
|
61
64
|
sh "dot -Tpng #{CLASS_GRAPH_DOT} -o #{CLASS_GRAPH_PNG}"
|
|
62
65
|
end
|
|
63
66
|
|
|
64
|
-
|
|
67
|
+
Reek::Rake::Task.new do |t|
|
|
68
|
+
t.fail_on_error = false
|
|
69
|
+
t.verbose = false
|
|
70
|
+
t.ruby_opts = ['-rubygems']
|
|
71
|
+
t.reek_opts = '--quiet'
|
|
72
|
+
t.source_files = FileList["#{LIB_DIR}/**/*.rb"].delete_if do |f|
|
|
73
|
+
f =~ /parser.rb/
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
65
77
|
if RUBY_VERSION >= '1.9.0'
|
|
66
78
|
task quality: :rubocop
|
|
67
79
|
require 'rubocop/rake_task'
|
data/cisco_acl_intp.gemspec
CHANGED
|
@@ -9,9 +9,9 @@ Gem::Specification.new do |spec|
|
|
|
9
9
|
spec.version = CiscoAclIntp::VERSION
|
|
10
10
|
spec.authors = ['stereocat']
|
|
11
11
|
spec.email = ['stereocat@gmail.com']
|
|
12
|
-
spec.description = %q{Cisco
|
|
13
|
-
spec.summary = %q{Cisco Access List Interpreter}
|
|
14
|
-
spec.homepage = ''
|
|
12
|
+
spec.description = %q{Cisco ACL Interpreter}
|
|
13
|
+
spec.summary = %q{Cisco IOS Access Control List Interpreter}
|
|
14
|
+
spec.homepage = 'https://github.com/stereocat/cisco_acl_intp'
|
|
15
15
|
spec.license = 'MIT'
|
|
16
16
|
|
|
17
17
|
spec.files = `git ls-files`.split("\n")
|
|
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
|
|
|
20
20
|
spec.require_paths = ['lib']
|
|
21
21
|
|
|
22
22
|
spec.add_runtime_dependency 'netaddr', '~> 1.5.0'
|
|
23
|
-
spec.add_runtime_dependency 'term-ansicolor', '~> 1.
|
|
24
|
-
spec.add_development_dependency 'bundler', '~> 1.3'
|
|
23
|
+
spec.add_runtime_dependency 'term-ansicolor', '~> 1.3.0'
|
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.5.3'
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
### Local variables:
|
data/lib/cisco_acl_intp.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
1
3
|
require 'rubygems'
|
|
2
4
|
require 'cisco_acl_intp/acl'
|
|
3
5
|
require 'cisco_acl_intp/parser'
|
|
@@ -7,3 +9,9 @@ require 'cisco_acl_intp/version'
|
|
|
7
9
|
# define scanner functions and ACL container classes
|
|
8
10
|
module CiscoAclIntp
|
|
9
11
|
end
|
|
12
|
+
|
|
13
|
+
### Local variables:
|
|
14
|
+
### mode: Ruby
|
|
15
|
+
### coding: utf-8-unix
|
|
16
|
+
### indent-tabs-mode: nil
|
|
17
|
+
### End:
|
data/lib/cisco_acl_intp/ace.rb
CHANGED
|
@@ -47,6 +47,20 @@ module CiscoAclIntp
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
# Error entry container
|
|
51
|
+
class ErrorAce < AceBase
|
|
52
|
+
attr_accessor :line
|
|
53
|
+
|
|
54
|
+
def initialize(line)
|
|
55
|
+
super({})
|
|
56
|
+
@line = line
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def to_s
|
|
60
|
+
tag_error(sprintf('!! error !! %s', @line))
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
50
64
|
# Remark entry container
|
|
51
65
|
class RemarkAce < AceBase
|
|
52
66
|
# @param [String] value Comment string
|
|
@@ -70,7 +84,7 @@ module CiscoAclIntp
|
|
|
70
84
|
# Generate string for Cisco IOS access list
|
|
71
85
|
# @return [String] Comment string
|
|
72
86
|
def to_s
|
|
73
|
-
sprintf '
|
|
87
|
+
sprintf 'remark %s', tag_remark(@comment.to_s)
|
|
74
88
|
end
|
|
75
89
|
|
|
76
90
|
# Search matched ACE
|
|
@@ -118,14 +132,14 @@ module CiscoAclIntp
|
|
|
118
132
|
# Generate string for Cisco IOS access list
|
|
119
133
|
# @return [String]
|
|
120
134
|
def to_s
|
|
121
|
-
sprintf 'evaluate %s',
|
|
135
|
+
sprintf 'evaluate %s', tag_name(@recursive_name)
|
|
122
136
|
end
|
|
123
137
|
|
|
124
138
|
# Search matched ACE
|
|
125
139
|
# @param [Hash] opts Options
|
|
126
|
-
# return [Boolean]
|
|
140
|
+
# return [Boolean]
|
|
141
|
+
# @todo for Recursive name matching is not implemented yet
|
|
127
142
|
def matches?(opts = nil)
|
|
128
|
-
## TODO
|
|
129
143
|
false
|
|
130
144
|
end
|
|
131
145
|
end
|
|
@@ -170,10 +184,10 @@ module CiscoAclIntp
|
|
|
170
184
|
# @return [String]
|
|
171
185
|
def to_s
|
|
172
186
|
sprintf(
|
|
173
|
-
'
|
|
174
|
-
|
|
187
|
+
'%s %s %s',
|
|
188
|
+
tag_action(@action.to_s),
|
|
175
189
|
@src_spec,
|
|
176
|
-
@log_spec ? @log_spec : ''
|
|
190
|
+
tag_other_qualifier(@log_spec ? @log_spec : '')
|
|
177
191
|
)
|
|
178
192
|
end
|
|
179
193
|
|
|
@@ -184,7 +198,7 @@ module CiscoAclIntp
|
|
|
184
198
|
# @raise [AclArgumentError] Invalid src_ip
|
|
185
199
|
def matches?(opts)
|
|
186
200
|
if opts.key?(:src_ip)
|
|
187
|
-
@src_spec.
|
|
201
|
+
@src_spec.matches?(opts[:src_ip])
|
|
188
202
|
else
|
|
189
203
|
fail AclArgumentError, 'Invalid match target src IP address'
|
|
190
204
|
end
|
|
@@ -310,13 +324,13 @@ module CiscoAclIntp
|
|
|
310
324
|
# @return [String]
|
|
311
325
|
def to_s
|
|
312
326
|
sprintf(
|
|
313
|
-
'
|
|
314
|
-
|
|
315
|
-
|
|
327
|
+
'%s %s %s %s %s %s',
|
|
328
|
+
tag_action(@action.to_s),
|
|
329
|
+
tag_protocol(@protocol.to_s),
|
|
316
330
|
@src_spec,
|
|
317
331
|
@dst_spec,
|
|
318
|
-
@tcp_flags
|
|
319
|
-
@tcp_other_qualifiers
|
|
332
|
+
@tcp_flags,
|
|
333
|
+
@tcp_other_qualifiers
|
|
320
334
|
)
|
|
321
335
|
end
|
|
322
336
|
|
|
@@ -325,21 +339,19 @@ module CiscoAclIntp
|
|
|
325
339
|
# @option opts [String] :protocol L3/L4 protocol name
|
|
326
340
|
# (allows "tcp", "udp" and "icmp")
|
|
327
341
|
# @option opts [String] :src_ip Source IP Address
|
|
328
|
-
# @option opts [Integer] :src_port Source Port No
|
|
342
|
+
# @option opts [Integer,String] :src_port Source Port No./Name
|
|
329
343
|
# @option opts [String] :dst_ip Destination IP Address
|
|
330
|
-
# @option opts [Integer] :dst_port Destination Port No
|
|
344
|
+
# @option opts [Integer,String] :dst_port Destination Port No./Name
|
|
331
345
|
# @return [Boolean] Matched or not
|
|
332
346
|
# @raise [AclArgumentError]
|
|
333
347
|
def matches?(opts)
|
|
334
348
|
if opts.key?(:protocol)
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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])
|
|
338
352
|
else
|
|
339
353
|
fail AclArgumentError, 'Invalid match target protocol'
|
|
340
354
|
end
|
|
341
|
-
|
|
342
|
-
(match_proto && match_src && match_dst)
|
|
343
355
|
end
|
|
344
356
|
|
|
345
357
|
private
|
|
@@ -350,30 +362,15 @@ module CiscoAclIntp
|
|
|
350
362
|
# @raise [AclArgumentError]
|
|
351
363
|
def match_protocol?(protocol)
|
|
352
364
|
protocol_str = @protocol.to_s
|
|
353
|
-
if protocol_str
|
|
354
|
-
true # allow tcp/udp
|
|
365
|
+
if [protocol_str, protocol].include?('ip')
|
|
366
|
+
true # allow any of icmp/tcp/udp
|
|
355
367
|
else
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
# In principle, it must be compared by object.
|
|
368
|
+
# @todo what to do when NO name and only protocol number is
|
|
369
|
+
# specified? In principle, it must be compared by object.
|
|
359
370
|
protocol == protocol_str
|
|
360
371
|
end
|
|
361
372
|
end
|
|
362
373
|
|
|
363
|
-
# check src/dst address
|
|
364
|
-
# @option srcdst_spec [AceSrcDstSpec] src/dst address/port
|
|
365
|
-
# @option ip [String] ip addr to compare
|
|
366
|
-
# @option port [Integer] port number to compare
|
|
367
|
-
# @return [Boolean] Matched or not
|
|
368
|
-
# @raise [AclArgumentError]
|
|
369
|
-
def match_addr_port?(srcdst_spec, ip, port)
|
|
370
|
-
if ip
|
|
371
|
-
srcdst_spec.matches?(ip, port)
|
|
372
|
-
else
|
|
373
|
-
fail AclArgumentError, 'Not specified match target IP Addr'
|
|
374
|
-
end
|
|
375
|
-
end
|
|
376
|
-
|
|
377
374
|
# Set instance variables
|
|
378
375
|
# return [AceIpProtoSpec] IP protocol object
|
|
379
376
|
# raise [AclArgumentError]
|
|
@@ -12,20 +12,19 @@ module CiscoAclIntp
|
|
|
12
12
|
# @param [NetAddr::CIDR] value IP address
|
|
13
13
|
# (dotted decimal notation)
|
|
14
14
|
# @return [NetAddr::CIDR]
|
|
15
|
-
|
|
15
|
+
attr_reader :ipaddr
|
|
16
16
|
|
|
17
17
|
# @param [Integer] value Netmask length
|
|
18
18
|
# @return [Integer]
|
|
19
|
-
|
|
19
|
+
attr_reader :netmask
|
|
20
20
|
|
|
21
21
|
# @param [String] value Wildcard mask
|
|
22
22
|
# (dotted decimal and bit flapped notation)
|
|
23
23
|
# @return [String]
|
|
24
|
-
|
|
24
|
+
attr_reader :wildcard
|
|
25
25
|
|
|
26
26
|
def_delegator :@ipaddr, :ip, :ipaddr
|
|
27
|
-
|
|
28
|
-
def_delegator :@ipaddr, :is_contained?, :contained_ip?
|
|
27
|
+
|
|
29
28
|
# `matches?' method is wildcard mask operation
|
|
30
29
|
def_delegators :@ipaddr, :matches?
|
|
31
30
|
|
|
@@ -40,7 +39,8 @@ module CiscoAclIntp
|
|
|
40
39
|
# @return [AceIpSpec]
|
|
41
40
|
def initialize(opts)
|
|
42
41
|
if opts.key?(:ipaddr)
|
|
43
|
-
|
|
42
|
+
@options = opts
|
|
43
|
+
define_addrinfo
|
|
44
44
|
else
|
|
45
45
|
fail AclArgumentError, 'Not specified IP address'
|
|
46
46
|
end
|
|
@@ -59,13 +59,13 @@ module CiscoAclIntp
|
|
|
59
59
|
def to_s
|
|
60
60
|
if to_wmasked_ip_s == '0.0.0.0'
|
|
61
61
|
# ip = '0.0.0.0' or wildcard = '255.255.255.255'
|
|
62
|
-
|
|
62
|
+
tag_ip('any')
|
|
63
63
|
else
|
|
64
64
|
if @wildcard == '0.0.0.0'
|
|
65
65
|
# /32 mask
|
|
66
|
-
sprintf('%s %s',
|
|
66
|
+
sprintf('%s %s', tag_mask('host'), tag_ip(@ipaddr.ip))
|
|
67
67
|
else
|
|
68
|
-
sprintf('%s %s',
|
|
68
|
+
sprintf('%s %s', tag_ip(to_wmasked_ip_s), tag_mask(@wildcard))
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
end
|
|
@@ -75,54 +75,96 @@ module CiscoAclIntp
|
|
|
75
75
|
def to_wmasked_ip_s
|
|
76
76
|
ai = NetAddr.ip_to_i(@ipaddr.ip)
|
|
77
77
|
mi = NetAddr.ip_to_i(@ipaddr.wildcard_mask)
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
NetAddr.i_to_ip(ai & mi)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Check subnet contained this object or not.
|
|
82
|
+
# @param [String] address Subnet address string
|
|
83
|
+
# e.g. 192.168.0.0/24, 192.168.0.0/255.255.255.0
|
|
84
|
+
# @return [Boolean]
|
|
85
|
+
# @raise [NetAddr::ValidationError]
|
|
86
|
+
def contains?(address)
|
|
87
|
+
# `@ipaddr` contains(1), is same block(0),
|
|
88
|
+
# is `contained(-1), is not related(nil)
|
|
89
|
+
[0, 1].include?(@ipaddr.cmp(address))
|
|
80
90
|
end
|
|
81
91
|
|
|
82
92
|
private
|
|
83
93
|
|
|
94
|
+
# Convert table of IPv4 bit-flapped wildcard octet to bit length
|
|
95
|
+
OCTET_BIT_LENGTH = {
|
|
96
|
+
'255' => 0, '127' => 1, '63' => 2, '31' => 3,
|
|
97
|
+
'15' => 4, '7' => 5, '3' => 6, '1' => 7, '0' => 8
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# Covnet IPv4 bit-flapped wildcard to netmask length
|
|
101
|
+
# @return [Fixnum] netmask length
|
|
102
|
+
# or `nil` when discontinuous-bits-wildcard-mask
|
|
103
|
+
def wildcard_bitlength
|
|
104
|
+
@wildcard.split(/\./).reduce(0) do |len, octet|
|
|
105
|
+
if len && OCTET_BIT_LENGTH.key?(octet)
|
|
106
|
+
len + OCTET_BIT_LENGTH[octet]
|
|
107
|
+
else
|
|
108
|
+
nil
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
84
113
|
# Set instance variables
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
114
|
+
def define_addrinfo
|
|
115
|
+
if @options.key?(:wildcard)
|
|
116
|
+
define_addrinfo_prefer_wildcard
|
|
117
|
+
else
|
|
118
|
+
define_addrinfo_by_netmask_or_default
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Set instance variables. assume that wildcard is primary option.
|
|
123
|
+
def define_addrinfo_prefer_wildcard
|
|
124
|
+
@wildcard = @options[:wildcard]
|
|
125
|
+
@netmask = wildcard_bitlength
|
|
126
|
+
if @netmask
|
|
127
|
+
@options[:netmask] = @netmask
|
|
128
|
+
define_addrinfo_with_netmask
|
|
129
|
+
else
|
|
130
|
+
define_addrinfo_with_wildcard
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Set instance variables. Secondary prioritize option is netmask,
|
|
135
|
+
# and third(last) one is default-mask
|
|
136
|
+
def define_addrinfo_by_netmask_or_default
|
|
137
|
+
if @options.key?(:netmask)
|
|
138
|
+
define_addrinfo_with_netmask
|
|
92
139
|
else
|
|
93
|
-
define_addrinfo_with_default_netmask
|
|
140
|
+
define_addrinfo_with_default_netmask
|
|
94
141
|
end
|
|
95
142
|
end
|
|
96
143
|
|
|
97
144
|
# Set instance variables with ip/wildcard
|
|
98
|
-
|
|
99
|
-
def define_addrinfo_with_wildcard(opts)
|
|
100
|
-
@wildcard = opts[:wildcard]
|
|
145
|
+
def define_addrinfo_with_wildcard
|
|
101
146
|
@ipaddr = NetAddr::CIDR.create(
|
|
102
|
-
|
|
147
|
+
@options[:ipaddr],
|
|
103
148
|
WildcardMask: [@wildcard, true]
|
|
104
149
|
)
|
|
105
|
-
## TBD : is it OK? must convert if possible?
|
|
106
150
|
@netmask = nil
|
|
107
151
|
end
|
|
108
152
|
|
|
109
153
|
# Set instance variables with ip/netmask
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
@netmask = opts[:netmask]
|
|
154
|
+
def define_addrinfo_with_netmask
|
|
155
|
+
@netmask = @options[:netmask]
|
|
113
156
|
@ipaddr = NetAddr::CIDR.create(
|
|
114
|
-
[
|
|
157
|
+
[@options[:ipaddr], @netmask].join('/')
|
|
115
158
|
)
|
|
116
159
|
@wildcard = @ipaddr.wildcard_mask(true)
|
|
117
160
|
end
|
|
118
161
|
|
|
119
162
|
# Set instance variables with ip/default-netmask
|
|
120
|
-
|
|
121
|
-
def define_addrinfo_with_default_netmask(opts)
|
|
163
|
+
def define_addrinfo_with_default_netmask
|
|
122
164
|
# default mask
|
|
123
165
|
@netmask = '255.255.255.255'
|
|
124
166
|
@ipaddr = NetAddr::CIDR.create(
|
|
125
|
-
[
|
|
167
|
+
[@options[:ipaddr], @netmask].join(' ')
|
|
126
168
|
)
|
|
127
169
|
@wildcard = @ipaddr.wildcard_mask(true)
|
|
128
170
|
end
|