line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Farly::ASA::Rewriter;
|
2
|
|
|
|
|
|
|
|
3
|
9
|
|
|
9
|
|
942
|
use 5.008008;
|
|
9
|
|
|
|
|
31
|
|
|
9
|
|
|
|
|
463
|
|
4
|
9
|
|
|
9
|
|
50
|
use strict;
|
|
9
|
|
|
|
|
20
|
|
|
9
|
|
|
|
|
277
|
|
5
|
9
|
|
|
9
|
|
47
|
use warnings;
|
|
9
|
|
|
|
|
26
|
|
|
9
|
|
|
|
|
339
|
|
6
|
9
|
|
|
9
|
|
58
|
use Carp;
|
|
9
|
|
|
|
|
17
|
|
|
9
|
|
|
|
|
726
|
|
7
|
9
|
|
|
9
|
|
458
|
use Scalar::Util qw(blessed);
|
|
9
|
|
|
|
|
92
|
|
|
9
|
|
|
|
|
638
|
|
8
|
9
|
|
|
9
|
|
55
|
use Log::Any qw($log);
|
|
9
|
|
|
|
|
15
|
|
|
9
|
|
|
|
|
105
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our $VERSION = '0.26';
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
# the parser rule name maps to an abstract syntax tree (AST) root node class
|
13
|
|
|
|
|
|
|
# this will become the 'ENTRY' model meta data in the Farly firewall model
|
14
|
|
|
|
|
|
|
# 'ENTRY' is roughly equivalent to a namespace or table name
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our $AST_Root_Class = {
|
17
|
|
|
|
|
|
|
'hostname' => 'HOSTNAME',
|
18
|
|
|
|
|
|
|
'named_ip' => 'NAME',
|
19
|
|
|
|
|
|
|
'interface' => 'INTERFACE',
|
20
|
|
|
|
|
|
|
'object' => 'OBJECT',
|
21
|
|
|
|
|
|
|
'object_group' => 'GROUP',
|
22
|
|
|
|
|
|
|
'access_list' => 'RULE',
|
23
|
|
|
|
|
|
|
'access_group' => 'ACCESS_GROUP',
|
24
|
|
|
|
|
|
|
'route' => 'ROUTE',
|
25
|
|
|
|
|
|
|
};
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# The $AST_Node_Class hash key is the rule name and the class of the parse tree node
|
28
|
|
|
|
|
|
|
# The $AST_Node_Class hash value is the new AST node class
|
29
|
|
|
|
|
|
|
# Any Token / '__VALUE__' found in the parse tree beneath the given nodes
|
30
|
|
|
|
|
|
|
# in the parse tree becomes the AST node '__VALUE__'
|
31
|
|
|
|
|
|
|
# The AST node class will become the key in the Farly::Object object
|
32
|
|
|
|
|
|
|
# AST node '__VALUE__' becomes the Farly::Object value object
|
33
|
|
|
|
|
|
|
# i.e. The $AST_Node_Class mapping defines the vendor to Farly model mapping :
|
34
|
|
|
|
|
|
|
# $object->set( ref($ast_node), $ast_node->{__VALUE__} );
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
my $AST_Node_Class = {
|
37
|
|
|
|
|
|
|
'named_ip' => 'OBJECT',
|
38
|
|
|
|
|
|
|
'name' => 'ID',
|
39
|
|
|
|
|
|
|
'name_comment' => 'COMMENT',
|
40
|
|
|
|
|
|
|
'hostname' => 'ID',
|
41
|
|
|
|
|
|
|
'interface' => 'INTERFACE',
|
42
|
|
|
|
|
|
|
'if_name' => 'ID',
|
43
|
|
|
|
|
|
|
'sec_level' => 'SECURITY_LEVEL',
|
44
|
|
|
|
|
|
|
'if_ip' => 'OBJECT',
|
45
|
|
|
|
|
|
|
'if_mask' => 'MASK',
|
46
|
|
|
|
|
|
|
'if_standby' => 'STANDBY_IP',
|
47
|
|
|
|
|
|
|
'object_id' => 'ID',
|
48
|
|
|
|
|
|
|
'object_address' => 'OBJECT',
|
49
|
|
|
|
|
|
|
'object_service_protocol' => 'PROTOCOL',
|
50
|
|
|
|
|
|
|
'object_service_src' => 'SRC_PORT',
|
51
|
|
|
|
|
|
|
'object_service_dst' => 'DST_PORT',
|
52
|
|
|
|
|
|
|
'object_icmp' => 'ICMP_TYPE',
|
53
|
|
|
|
|
|
|
'object_group' => 'GROUP_TYPE',
|
54
|
|
|
|
|
|
|
'og_id' => 'ID',
|
55
|
|
|
|
|
|
|
'og_protocol' => 'GROUP_PROTOCOL',
|
56
|
|
|
|
|
|
|
'og_network_object' => 'OBJECT',
|
57
|
|
|
|
|
|
|
'og_port_object' => 'OBJECT',
|
58
|
|
|
|
|
|
|
'og_group_object' => 'OBJECT',
|
59
|
|
|
|
|
|
|
'og_protocol_object' => 'OBJECT',
|
60
|
|
|
|
|
|
|
'og_description' => 'OBJECT',
|
61
|
|
|
|
|
|
|
'og_icmp_object' => 'OBJECT',
|
62
|
|
|
|
|
|
|
'og_service_object' => 'OBJECT',
|
63
|
|
|
|
|
|
|
'og_so_protocol' => 'PROTOCOL',
|
64
|
|
|
|
|
|
|
'og_so_src_port' => 'SRC_PORT',
|
65
|
|
|
|
|
|
|
'og_so_dst_port' => 'DST_PORT',
|
66
|
|
|
|
|
|
|
'acl_action' => 'ACTION',
|
67
|
|
|
|
|
|
|
'acl_id' => 'ID',
|
68
|
|
|
|
|
|
|
'acl_line' => 'LINE',
|
69
|
|
|
|
|
|
|
'acl_type' => 'TYPE',
|
70
|
|
|
|
|
|
|
'acl_protocol' => 'PROTOCOL',
|
71
|
|
|
|
|
|
|
'acl_src_ip' => 'SRC_IP',
|
72
|
|
|
|
|
|
|
'acl_src_port' => 'SRC_PORT',
|
73
|
|
|
|
|
|
|
'acl_dst_ip' => 'DST_IP',
|
74
|
|
|
|
|
|
|
'acl_dst_port' => 'DST_PORT',
|
75
|
|
|
|
|
|
|
'acl_icmp_type' => 'ICMP_TYPE',
|
76
|
|
|
|
|
|
|
'acl_remark' => 'COMMENT',
|
77
|
|
|
|
|
|
|
'acl_log_level' => 'LOG_LEVEL',
|
78
|
|
|
|
|
|
|
'acl_log_interval' => 'LOG_INTERVAL',
|
79
|
|
|
|
|
|
|
'acl_time_range' => 'TIME_RANGE',
|
80
|
|
|
|
|
|
|
'acl_inactive' => 'STATUS',
|
81
|
|
|
|
|
|
|
'ag_id' => 'ID',
|
82
|
|
|
|
|
|
|
'ag_direction' => 'DIRECTION',
|
83
|
|
|
|
|
|
|
'ag_interface' => 'INTERFACE',
|
84
|
|
|
|
|
|
|
'route_interface' => 'INTERFACE',
|
85
|
|
|
|
|
|
|
'route_dst' => 'DST_IP',
|
86
|
|
|
|
|
|
|
'route_nexthop' => 'NEXTHOP',
|
87
|
|
|
|
|
|
|
'route_cost' => 'COST',
|
88
|
|
|
|
|
|
|
'route_track' => 'TRACK',
|
89
|
|
|
|
|
|
|
'route_tunneled' => 'TUNNELED',
|
90
|
|
|
|
|
|
|
'port_neq' => 'NEQ', #not used yet
|
91
|
|
|
|
|
|
|
'OBJECT_TYPE' => 'OBJECT_TYPE', #imaginary token mapping
|
92
|
|
|
|
|
|
|
};
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub new {
|
95
|
6
|
|
|
6
|
0
|
25
|
my ($class) = @_;
|
96
|
|
|
|
|
|
|
|
97
|
6
|
|
|
|
|
27
|
my $self = bless {}, $class;
|
98
|
|
|
|
|
|
|
|
99
|
6
|
|
|
|
|
58
|
$log->info("$self NEW");
|
100
|
|
|
|
|
|
|
|
101
|
6
|
|
|
|
|
31
|
return $self;
|
102
|
|
|
|
|
|
|
}
|
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub rewrite {
|
105
|
326
|
|
|
326
|
0
|
631
|
my ( $self, $pt_node ) = @_;
|
106
|
|
|
|
|
|
|
# $node is a reference to the current node in the parse tree
|
107
|
|
|
|
|
|
|
# i.e. the root of the parse tree to begin with
|
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# $root is a reference to the root of the new abstract syntax tree
|
110
|
326
|
|
|
|
|
1049
|
my $root = bless( {}, 'NULL' );
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# $ast_node is a reference to current ast node
|
113
|
326
|
|
|
|
|
519
|
my $ast_node;
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
# set s of explored vertices
|
116
|
|
|
|
|
|
|
my %seen;
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
#stack is all neighbors of s
|
119
|
0
|
|
|
|
|
0
|
my @stack;
|
120
|
326
|
|
|
|
|
1016
|
push @stack, [ $pt_node, $ast_node ];
|
121
|
|
|
|
|
|
|
|
122
|
326
|
|
|
|
|
481
|
my $key;
|
123
|
|
|
|
|
|
|
|
124
|
326
|
|
|
|
|
890
|
while (@stack) {
|
125
|
|
|
|
|
|
|
|
126
|
4252
|
|
|
|
|
11609
|
my $rec = pop @stack;
|
127
|
|
|
|
|
|
|
|
128
|
4252
|
|
|
|
|
5825
|
$pt_node = $rec->[0];
|
129
|
4252
|
|
|
|
|
4663
|
$ast_node = $rec->[1];
|
130
|
|
|
|
|
|
|
|
131
|
4252
|
|
|
|
|
16009
|
$log->debug( "parse tree node = " . ref($pt_node) . " : ast node = " . ref($ast_node) );
|
132
|
|
|
|
|
|
|
|
133
|
4252
|
50
|
|
|
|
19177
|
next if ( $seen{$pt_node}++ );
|
134
|
|
|
|
|
|
|
|
135
|
4252
|
|
|
|
|
5365
|
my $pt_node_class = ref($pt_node);
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# redefine the abstract syntax tree root node class
|
138
|
4252
|
100
|
|
|
|
13285
|
if ( defined( $AST_Root_Class->{$pt_node_class} ) ) {
|
139
|
|
|
|
|
|
|
|
140
|
326
|
|
|
|
|
1192
|
$root = bless( {}, $AST_Root_Class->{$pt_node_class} );
|
141
|
326
|
|
|
|
|
732
|
$ast_node = $root;
|
142
|
|
|
|
|
|
|
|
143
|
326
|
|
|
|
|
1345
|
$log->debug( "new ast root class = " . ref($root) );
|
144
|
|
|
|
|
|
|
}
|
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
# create new abstract syntax tree nodes
|
147
|
4252
|
100
|
|
|
|
9723
|
if ( defined( $AST_Node_Class->{$pt_node_class} ) ) {
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# create a new AST node and add it to the AST
|
150
|
1654
|
|
|
|
|
2875
|
my $new_ast_node_class = $AST_Node_Class->{$pt_node_class};
|
151
|
1654
|
|
|
|
|
5667
|
$ast_node->{$new_ast_node_class} = bless( {}, $new_ast_node_class );
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
#update the $ast_node reference to refer to the new AST node
|
154
|
1654
|
|
|
|
|
2540
|
$ast_node = $ast_node->{$new_ast_node_class};
|
155
|
|
|
|
|
|
|
|
156
|
1654
|
|
|
|
|
5876
|
$log->debug( "mapped $pt_node_class to AST class " . ref($ast_node) );
|
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# the AST root class has to have been changed or something is very wrong
|
159
|
1654
|
50
|
|
|
|
10140
|
confess "rewrite error" if ( $root->isa('NULL') );
|
160
|
|
|
|
|
|
|
}
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# continue exploring the parse tree
|
163
|
4252
|
|
|
|
|
9415
|
foreach my $key ( keys %$pt_node ) {
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
# not interested in the EOL token
|
166
|
9515
|
100
|
|
|
|
17578
|
next if ( $key eq "EOL" );
|
167
|
|
|
|
|
|
|
|
168
|
9113
|
|
|
|
|
11750
|
my $next = $pt_node->{$key};
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
# skip and filter out string values
|
171
|
9113
|
100
|
|
|
|
28622
|
if ( blessed($next) ) {
|
172
|
|
|
|
|
|
|
|
173
|
5570
|
100
|
|
|
|
9000
|
if ( $key eq '__VALUE__' ) {
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
#then $next isa token
|
176
|
1644
|
|
|
|
|
2745
|
$ast_node->{'__VALUE__'} = $next;
|
177
|
1644
|
|
|
|
|
6150
|
$log->debug( "ast node = " . ref($ast_node) . " : token = " . ref($next) );
|
178
|
|
|
|
|
|
|
}
|
179
|
|
|
|
|
|
|
else {
|
180
|
3926
|
|
|
|
|
13231
|
push @stack, [ $next, $ast_node ];
|
181
|
|
|
|
|
|
|
}
|
182
|
|
|
|
|
|
|
}
|
183
|
|
|
|
|
|
|
}
|
184
|
|
|
|
|
|
|
}
|
185
|
|
|
|
|
|
|
|
186
|
326
|
50
|
|
|
|
3175
|
confess "rewrite error" if ( $root->isa('NULL') );
|
187
|
|
|
|
|
|
|
|
188
|
326
|
|
|
|
|
1917
|
return $root;
|
189
|
|
|
|
|
|
|
}
|
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
1;
|
192
|
|
|
|
|
|
|
__END__
|