cisco_acl_intp 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/cisco_acl_intp.png)](http://badge.fury.io/rb/cisco_acl_intp)
|
3
|
+
[![Build Status](https://travis-ci.org/stereocat/cisco_acl_intp.png?branch=master)](https://travis-ci.org/stereocat/cisco_acl_intp)
|
4
|
+
[![Dependency Status](https://gemnasium.com/stereocat/cisco_acl_intp.png)](https://gemnasium.com/stereocat/cisco_acl_intp)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/stereocat/cisco_acl_intp/badge.png?branch=master)](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
|