1/*
2 * Copyright (c) 2002-2013 Balabit
3 * Copyright (c) 1998-2011 Balázs Scheidler
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 *
19 * As an additional exemption you are allowed to compile & link against the
20 * OpenSSL libraries as published by the OpenSSL project. See the file
21 * COPYING for details.
22 *
23 */
24
25%code requires {
26
27#include "filter/filter-expr-parser.h"
28
29}
30
31%code {
32
33#include "filter/filter-netmask.h"
34#include "filter/filter-netmask6.h"
35#include "filter/filter-op.h"
36#include "filter/filter-cmp.h"
37#include "filter/filter-in-list.h"
38#include "filter/filter-tags.h"
39#include "filter/filter-call.h"
40#include "filter/filter-re.h"
41#include "filter/filter-pri.h"
42#include "filter/filter-throttle.h"
43#include "messages.h"
44#include "template/templates.h"
45#include "syslog-names.h"
46#include "plugin.h"
47#include "cfg-grammar-internal.h"
48
49FilterExprNode *last_filter_expr;
50
51}
52
53%define api.prefix {filter_expr_}
54%lex-param {CfgLexer *lexer}
55%parse-param {CfgLexer *lexer}
56%parse-param {FilterExprNode **result}
57%parse-param {gpointer arg}
58
59/* INCLUDE_DECLS */
60
61%token KW_PROGRAM
62%token KW_IN_LIST
63%token KW_RATE
64
65%left   ';'
66%left	KW_OR
67%left	KW_AND
68%left   KW_NOT
69%left   KW_LT KW_LE KW_EQ KW_NE KW_GE KW_GT
70%left   KW_NUM_LT KW_NUM_LE KW_NUM_EQ KW_NUM_NE KW_NUM_GE KW_NUM_GT
71
72%type	<node> filter_expr
73%type	<node> filter_simple_expr
74%type	<node> filter_plugin
75%type	<node> filter_comparison
76%type	<node> filter_throttle
77
78%type   <num> filter_fac_list
79%type   <num> filter_fac
80%type	<num> filter_severity_list
81%type	<num> filter_severity
82
83%type   <token> operator
84
85%%
86
87start
88        : filter_expr                           { *result = $1; if (yychar != FILTER_EXPR_EMPTY) { cfg_lexer_unput_token(lexer, &yylval); } YYACCEPT; }
89	;
90
91filter_expr
92	: filter_simple_expr			{ $$ = $1; if (!$1) YYERROR; }
93        | KW_NOT filter_expr			{ ((FilterExprNode *) $2)->comp = !(((FilterExprNode *) $2)->comp); $$ = $2; }
94	| filter_expr KW_OR filter_expr		{ $$ = fop_or_new($1, $3); }
95	| filter_expr KW_AND filter_expr	{ $$ = fop_and_new($1, $3); }
96	| filter_expr ';' filter_expr	        { $$ = fop_and_new($1, $3); }
97	|  filter_expr ';'	                { $$ = $1; }
98	| '(' filter_expr ')'			{ $$ = $2; }
99	;
100
101filter_simple_expr
102	: KW_FACILITY '(' filter_fac_list ')'	{ $$ = filter_facility_new($3);  }
103	| KW_FACILITY '(' LL_NUMBER ')'		{ $$ = filter_facility_new(0x80000000 | $3); }
104	| KW_SEVERITY '(' filter_severity_list ')' { $$ = filter_severity_new($3); }
105	| KW_FILTER '(' string ')'		{ $$ = filter_call_new($3, configuration); free($3); }
106	| KW_NETMASK '(' string ')'    { $$ = filter_netmask_new($3); free($3); }
107  | KW_NETMASK6 '(' string ')'   {
108  #if SYSLOG_NG_ENABLE_IPV6
109                                    $$ = filter_netmask6_new($3);
110  #else
111                                    YYERROR;
112  #endif
113                                    free($3);
114                                  }
115        | KW_TAGS '(' string_list ')'           { $$ = filter_tags_new($3); }
116        | KW_IN_LIST '(' string string ')'
117          {
118            const gchar *p = $4;
119            if (p[0] == '$')
120              {
121                msg_warning("Value references in filters should not use the '$' prefix, those are only needed in templates",
122                            evt_tag_str("value", $4),
123                            cfg_lexer_format_location_tag(lexer, &@4));
124                p++;
125              }
126            $$ = filter_in_list_new($3, p);
127            free($3);
128            free($4);
129          }
130        | KW_IN_LIST '(' string KW_VALUE '(' string ')' ')'
131          {
132            const gchar *p = $6;
133            if (p[0] == '$')
134              {
135                msg_warning("Value references in filters should not use the '$' prefix, those are only needed in templates",
136                            evt_tag_str("value", $6),
137                            cfg_lexer_format_location_tag(lexer, &@6));
138                p++;
139              }
140            $$ = filter_in_list_new($3, p);
141            free($3);
142            free($6);
143          }
144	| filter_re					{ $$ = last_filter_expr; }
145	| filter_plugin
146	| filter_comparison
147	| filter_throttle   { $$ = last_filter_expr; }
148	;
149
150
151filter_plugin
152        : LL_IDENTIFIER
153          {
154            Plugin *p;
155            gint context = LL_CONTEXT_FILTER;
156            FilterExprNode *node;
157
158            p = cfg_find_plugin(configuration, context, $1);
159            CHECK_ERROR(p, @1, "%s plugin %s not found OR you may not used double quotes in your filter expression", cfg_lexer_lookup_context_name_by_type(context), $1);
160
161            node = (FilterExprNode *) cfg_parse_plugin(configuration, p, &@1, NULL);
162            free($1);
163            if (!node)
164              {
165                YYERROR;
166              }
167            $$ = node;
168          }
169	;
170
171filter_comparison
172	: LL_STRING operator LL_STRING
173          {
174            LogTemplate *left, *right;
175            GError *error = NULL;
176
177            left = log_template_new(configuration, NULL);
178            right = log_template_new(configuration, NULL);
179            CHECK_ERROR_GERROR(log_template_compile(left, $1, &error), @1, error, "compiling the left-hand-side template failed");
180            CHECK_ERROR_GERROR(log_template_compile(right, $3, &error), @3, error, "compiling the right-hand-side template failed");
181
182            free($1);
183            free($3);
184            $$ = fop_cmp_new(left, right, $2);
185          }
186        ;
187
188operator
189	: KW_NUM_LT	{ $$ = yylval.token; }
190	| KW_NUM_LE	{ $$ = yylval.token; }
191	| KW_NUM_EQ     { $$ = yylval.token; }
192	| KW_NUM_NE     { $$ = yylval.token; }
193	| KW_NUM_GE     { $$ = yylval.token; }
194	| KW_NUM_GT     { $$ = yylval.token; }
195	| KW_LT		{ $$ = yylval.token; }
196	| KW_LE		{ $$ = yylval.token; }
197	| KW_EQ         { $$ = yylval.token; }
198	| KW_NE         { $$ = yylval.token; }
199	| KW_GE         { $$ = yylval.token; }
200	| KW_GT         { $$ = yylval.token; }
201	;
202
203filter_re
204        : KW_PROGRAM { last_filter_expr = filter_re_new(LM_V_PROGRAM); } filter_re_params
205	| KW_HOST    { last_filter_expr = filter_re_new(LM_V_HOST); } filter_re_params
206	| KW_MESSAGE { last_filter_expr = filter_re_new(LM_V_MESSAGE); } filter_re_params
207        | KW_SOURCE  { last_filter_expr = filter_source_new();  } filter_re_params
208	| KW_MATCH   { last_filter_expr = filter_match_new(); } filter_match_params
209	;
210
211filter_re_params
212	: '(' string filter_re_opts ')'
213          {
214            GError *error = NULL;
215
216            CHECK_ERROR_GERROR(filter_re_compile_pattern(last_filter_expr, $2, &error), @2, error, "compiling the regexp failed");
217            free($2);
218          }
219	;
220
221filter_re_opts
222        : filter_re_opt filter_re_opts
223        |
224        ;
225
226filter_re_opt
227	: { last_matcher_options = filter_re_get_matcher_options(last_filter_expr); } matcher_option
228        ;
229
230
231filter_match_params
232        : '(' string filter_match_opts ')'
233          {
234            GError *error = NULL;
235
236            CHECK_ERROR_GERROR(filter_re_compile_pattern(last_filter_expr, $2, &error), @2, error, "compiling the regexp failed");
237            free($2);
238
239            if (filter_match_is_usage_obsolete(last_filter_expr))
240              {
241                msg_warning_once("WARNING: the match() filter without the use of the value() "
242                                 "option is deprecated and hinders performance, please use a "
243                                 "more specific filter like message() and/or program() instead",
244                                 cfg_lexer_format_location_tag(lexer, &@0));
245              }
246
247          }
248
249filter_match_opts
250        : filter_match_opt filter_match_opts
251        |
252        ;
253
254filter_match_opt
255        : filter_re_opt
256        | KW_VALUE '(' string ')'
257          {
258            const gchar *p = $3;
259            if (p[0] == '$')
260              {
261                msg_warning("WARNING: value references in filters should not use the '$' prefix, those are only needed in templates, removing automatically",
262                            evt_tag_str("value", $3),
263                            cfg_lexer_format_location_tag(lexer, &@3));
264                p++;
265              }
266            if (p[0] == '(' || strchr(p, '$') != NULL)
267              {
268                msg_error("value() reference for the match() filter cannot contain a full template string, use the template() option or stick to a single value",
269                          evt_tag_str("value", $3),
270                          cfg_lexer_format_location_tag(lexer, &@3));
271                free($3);
272                YYERROR;
273              }
274            filter_match_set_value_handle(last_filter_expr, log_msg_get_value_handle(p));
275            free($3);
276          }
277	| KW_TEMPLATE '(' template_content ')'
278	  {
279            filter_match_set_template_ref(last_filter_expr, $3);
280          }
281        ;
282
283filter_fac_list
284	: filter_fac filter_fac_list		{ $$ = $1 | $2; }
285	| filter_fac				{ $$ = $1; }
286	;
287
288filter_fac
289	: facility_string LL_DOTDOT facility_string
290	  {
291	    $$ = syslog_make_range($1 >> 3, $3 >> 3);
292	  }
293        | facility_string			{ $$ = 1 << ($1 >> 3); }
294	;
295
296filter_severity_list
297	: filter_severity filter_severity_list	{ $$ = $1 | $2; }
298	| filter_severity				{ $$ = $1; }
299	;
300
301filter_severity
302	: severity_string LL_DOTDOT severity_string
303	  {
304	    $$ = syslog_make_range($1, $3);
305	  }
306	| severity_string
307	  {
308	    $$ = 1 << $1;
309	  }
310	;
311
312filter_throttle_arg
313  : KW_TEMPLATE '(' template_content ')'
314          {
315            filter_throttle_set_key_template(last_filter_expr, $3);
316            log_template_unref($3);
317          }
318  | KW_RATE '(' positive_integer ')'
319          {
320            filter_throttle_set_rate(last_filter_expr, $3);
321          }
322  ;
323
324filter_throttle_args
325  : filter_throttle_arg filter_throttle_args
326  |
327  ;
328
329filter_throttle
330  : KW_THROTTLE { last_filter_expr = filter_throttle_new(); } '(' filter_throttle_args ')'
331  ;
332
333/* INCLUDE_RULES */
334
335%%
336