File Coverage

blib/lib/Farly/ASA/Rewriter.pm
Criterion Covered Total %
statement 54 55 98.1
branch 13 16 81.2
condition n/a
subroutine 8 8 100.0
pod 0 2 0.0
total 75 81 92.5


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__