fix: distingush initial vector from request vector when print evlog
[adaptation/xorg/driver/xserver-xorg-module-xdbg.git] / common / ds / bool_exp_rule_checker.c
1 /**************************************************************************
2
3 xserver-xorg-video-exynos
4
5 Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: Boram Park <boram1288.park@samsung.com>
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <stdlib.h>
35
36 #include "bool_exp_parser.h"
37 #include "bool_exp_rule_checker.h"
38
39 #define MAX_RULE        64
40
41 typedef struct
42 {
43     POLICY_TYPE policy;
44
45     BINARY_TREE tree;
46 } RULE;
47
48 struct _RULE_CHECKER
49 {
50     RULE rules[MAX_RULE];
51
52     int count;
53 };
54
55 typedef struct
56 {
57     int type;
58     int reqID;
59     const char * name;
60     int pid;
61     char * cmd;
62 } VAL_ARGUMENTS;
63
64 static int print_func (BINARY_TREE tree, BINARY_TREE_NODE node, BINARY_TREE_NODE parent, void * arg)
65 {
66     int len;
67     char ** string = (char **)arg;
68     char * operators[] = { "==", "<", ">", "<=", ">=", "!=" };
69
70     PARSE_DATA data = bintree_get_node_data (node);
71
72     if (data->node_type == ALL)
73     {
74         len = sprintf (*string, "ALL");
75         (*string) += len;
76     }
77     else if (data->node_type == AND)
78     {
79         len = sprintf (*string, " and ");
80         (*string) += len;
81     }
82     else if (data->node_type == OR)
83     {
84         len = sprintf (*string, " or ");
85         (*string) += len;
86     }
87     else // data->node_type == DATA
88     {
89         if (node == bintree_get_left_child (parent))
90         {
91             **string = '(';
92             (*string) ++;
93         }
94
95         len = sprintf (*string, "%s %s ", data->variable_name, operators[data->compare]);
96         (*string) += len;
97         if (data->value_type == INTEGER)
98             len = sprintf (*string, "%d", data->value.integer);
99         else
100             len = sprintf (*string, "%s", data->value.string);
101         (*string) += len;
102
103         if (node == bintree_get_right_child (parent))
104         {
105             **string = ')';
106             (*string) ++;
107         }
108     }
109
110     return 0;
111 }
112
113 static int compare_string (COMPARER compare, char * str2, char * str1)
114 {
115     int result = strcasecmp (str2, str1);
116     switch (compare)
117     {
118     case EQUAL:
119         return result == 0;
120     case LESS:
121         return result < 0;
122     case GREATER:
123         return result > 0;
124     case LESS_EQ:
125         return result <= 0;
126     case GREATER_EQ:
127         return result >= 0;
128     case NOT_EQ:
129         return result != 0;
130     }
131
132     return 0;
133 }
134
135 static int compare_int (COMPARER compare, int int2, int int1)
136 {
137     switch (compare)
138     {
139     case EQUAL:
140         return int1 == int2;
141     case LESS:
142         return int1 < int2;
143     case GREATER:
144         return int1 > int2;
145     case LESS_EQ:
146         return int1 <= int2;
147     case GREATER_EQ:
148         return int1 >= int2;
149     case NOT_EQ:
150         return int1 != int2;
151     }
152
153     return 0;
154 }
155
156 static int validate_func (BINARY_TREE tree, BINARY_TREE_NODE node, BINARY_TREE_NODE parent, void * arg)
157 {
158     VAL_ARGUMENTS * args = (VAL_ARGUMENTS*)arg;
159     BINARY_TREE_NODE left, right;
160
161     PARSE_DATA left_data = NULL, right_data = NULL;
162     PARSE_DATA data = bintree_get_node_data (node);
163
164     data->result = BEP_UNKNOWN;
165
166     if (data->node_type == AND || data->node_type == OR)
167     {
168         left = bintree_get_left_child (node);
169         right = bintree_get_right_child (node);
170         if (left == NULL || right == NULL)
171         {
172             printf ("Node error\n");
173             return -1;
174         }
175
176         left_data = bintree_get_node_data (left);
177         right_data = bintree_get_node_data (right);
178     }
179
180     if (data->node_type == ALL)
181     {
182         data->result = BEP_TRUE;
183     }
184     else if (data->node_type == DATA)
185     {
186         char major[64];
187         char * minor = NULL;
188
189         if (args->name)
190             minor = index (args->name, ':');
191         if (minor)
192         {
193             strncpy (major, args->name, minor - args->name);
194             major[minor - args->name] = '\0';
195             minor++;
196         }
197         if (!strcasecmp (data->variable_name, "TYPE"))
198         {
199             char * type_string;
200             if (args->type == 0) // EVENT
201                 type_string = "EVENT";
202             else if (args->type == 1)
203                 type_string = "REQUEST";
204             else if (args->type == 2)
205                 type_string = "REPLY";
206             else if (args->type == 3)
207                 type_string = "FLUSH";
208             else
209             {
210                 fprintf (stderr, "Invalid type %d\n", args->type);
211                 return -1;
212             }
213
214             if (compare_string (data->compare, data->value.string, type_string))
215                 data->result = BEP_TRUE;
216             else
217                 data->result = BEP_FALSE;
218         }
219         else if (!strcasecmp (data->variable_name, "MAJOR"))
220         {
221             if (minor && compare_string (data->compare, data->value.string, major))
222                 data->result = BEP_TRUE;
223             else
224                 data->result = BEP_FALSE;
225         }
226         else if (!strcasecmp (data->variable_name, "MINOR"))
227         {
228             if (minor && compare_string (data->compare, data->value.string, minor))
229                 data->result = BEP_TRUE;
230             else
231                 data->result = BEP_FALSE;
232         }
233         else if (!strcasecmp (data->variable_name, "PID"))
234         {
235             if (compare_int (data->compare, data->value.integer, args->pid))
236                 data->result = BEP_TRUE;
237             else
238                 data->result = BEP_FALSE;
239         }
240         else if (!strcasecmp (data->variable_name, "CMD") || !strcasecmp (data->variable_name, "COMMAND"))
241         {
242             if (args->cmd && compare_string (data->compare, data->value.string, args->cmd))
243                 data->result = BEP_TRUE;
244             else
245                 data->result = BEP_FALSE;
246         }
247     }
248     else if (data->node_type == AND)
249     {
250         if (left_data->result == BEP_TRUE && right_data->result == BEP_TRUE)
251             data->result = BEP_TRUE;
252         else
253             data->result = BEP_FALSE;
254     }
255     else if (data->node_type == OR)
256     {
257         if (left_data->result == BEP_TRUE || right_data->result == BEP_TRUE)
258             data->result = BEP_TRUE;
259         else
260             data->result = BEP_FALSE;
261     }
262     else
263         return -1;
264
265     return 0;
266 }
267
268
269 RULE_CHECKER rulechecker_init()
270 {
271     RULE_CHECKER rc = calloc (sizeof (struct _RULE_CHECKER), 1);
272     if (rc == NULL)
273         return NULL;
274
275     rc->count = 0;
276
277     return rc;
278 }
279
280 void rulechecker_destroy (RULE_CHECKER rc)
281 {
282     int i;
283     for (i=rc->count - 1; i>=0; i--)
284         rulechecker_remove_rule (rc, i);
285
286     free (rc);
287 }
288
289 RC_RESULT_TYPE rulechecker_add_rule (RULE_CHECKER rc, POLICY_TYPE policy, const char * rule_string)
290 {
291     if (rc->count == MAX_RULE)
292         return RC_ERR_TOO_MANY_RULES;
293
294     rc->rules[rc->count].tree = bool_exp_parse (rule_string);
295     if (rc->rules[rc->count].tree == NULL)
296         return RC_ERR_PARSE_ERROR;
297     rc->rules[rc->count].policy = policy;
298
299     rc->count++;
300
301     return RC_OK;
302 }
303
304 RC_RESULT_TYPE rulechecker_remove_rule (RULE_CHECKER rc, int index)
305 {
306     if (index < 0 || index >= rc->count)
307         return RC_ERR_NO_RULE;
308
309     bintree_destroy_tree (rc->rules[index].tree);
310
311     rc->count--;
312     if (index != rc->count)
313         memmove (&rc->rules[index], &rc->rules[index + 1], sizeof (RULE) * (rc->count - index));
314
315     return RC_OK;
316 }
317
318 void rulechecker_print_rule (RULE_CHECKER rc, char * rules_buf)
319 {
320     char * rules_print = rules_buf;
321     int len;
322
323     int i;
324
325     len = sprintf (rules_print, " ---------------- Evlog Rules ----------------\n");
326     rules_print += len;
327
328     for (i=0; i<rc->count; i++)
329     {
330         len = sprintf (rules_print, " [Rule %d] [%s] \"", i, rc->rules[i].policy == ALLOW ? "ALLOW" : "DENY");
331         rules_print += len;
332         bintree_inorder_traverse (rc->rules[i].tree, print_func, (void*)&rules_print);
333         *rules_print = '\"';
334         rules_print++;
335         *rules_print = '\n';
336         rules_print++;
337     }
338     *rules_print = '\0';
339 }
340
341 const char * rulechecker_print_usage()
342 {
343     return
344         "######################################################################\n"
345         "###     RuleChecker 1.0 for XDBG EvLog filtering.                  ###\n"
346         "###                 Designed and developed by                      ###\n"
347         "###                 YoungHoon Jung <yhoon.jung@samsung.com>        ###\n"
348         "######################################################################\n"
349         "\n"
350         "-----------------------------------------------------------------\n"
351         "How to read evlog messages :\n"
352         "      Client(pid: [PID]|       [CMD])   <======     [TYPE]( [MAJOR]:  [MINOR])   =====     XServer\n"
353         "\n"
354         "   ie)\n"
355         "        Client(pid:00345|        xdbg)   <======    Event (       X11:SendEvent)   =====     XServer\n"
356         "             ==> type = event && pid = 345 && cmd = xdbg && major = X11 && minor = SendEvent\n"
357         "        Client(pid:00111|        xeyes)     =====   Request(       SHM:ShmAttach)   ======>   XServer\n"
358         "             ==> type = request && pid = 111 && cmd = xeyes && major = SHM && minor = ShmAttach\n"
359         "\n"
360         "-----------------------------------------------------------------\n"
361         "Usage : xdbg evlog_rule add [POLICY] [RULE]\n"
362         "        xdbg evlog_rule remove [INDEX]\n"
363         "        xdbg evlog_rule help / print\n"
364         "      [POLICY] : allow / deny \n"
365         "      [RULE] : C Language-style boolean expression syntax. [VARIABLE] [COMPAROTOR] [VALUE]\n"
366         "      [VARIABLE] : type / major / minor / command / cmd / pid\n"
367         "      [COMPARATOR] : & / && / and / | / || / or / = / == / != / > / >= / < / <=\n"
368         "      [VALUE] : string / number  \n"
369         "\n"
370         "   ie)\n"
371         "        xdbg evlog_rule add allow \"(type=request) && (major == X11 and (minor = SendEvent or minor = ReceiveEvent))\"\n"
372         "        xdbg evlog_rule add deny cmd!=ls\n"
373         "        xdbg evlog_rule remove 1\n"
374         "\n";
375 }
376
377 int rulechecker_validate_rule (RULE_CHECKER rc, int type, int reqID, const char * name, int pid, char * cmd)
378 {
379     VAL_ARGUMENTS args = { type, reqID, name, pid, cmd };
380     BINARY_TREE_NODE node;
381     PARSE_DATA data;
382
383     // set default value here
384     POLICY_TYPE default_policy = DENY;
385     int i;
386     for (i=rc->count - 1; i >= 0; i--)
387     {
388         bintree_postorder_traverse (rc->rules[i].tree, validate_func, &args);
389         node = bintree_get_head (rc->rules[i].tree);
390         data = bintree_get_node_data (node);
391
392         if (data->result == BEP_TRUE)
393         {
394             return rc->rules[i].policy == ALLOW;
395         }
396     }
397
398     return default_policy == ALLOW;
399 }