1 /* 2 * Copyright (c) 2012 Nagy, Attila <bra@fsn.hu> 3 * Copyright (c) 2012-2014 Balabit 4 * Copyright (c) 2012-2014 Gergely Nagy <algernon@balabit.hu> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published 8 * by the Free Software Foundation, or (at your option) any later version. 9 * 10 * This program 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 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; 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 "afamqp-parser.h" 28 29 } 30 31 %code { 32 33 #include "cfg-grammar-internal.h" 34 35 } 36 37 %define api.prefix {afamqp_} 38 %lex-param {CfgLexer *lexer} 39 %parse-param {CfgLexer *lexer} 40 %parse-param {LogDriver **instance} 41 %parse-param {gpointer arg} 42 43 44 45 %require "3.7.6" 46 %locations 47 %define api.pure 48 %define api.value.type {CFG_STYPE} 49 %define api.location.type {CFG_LTYPE} 50 %define parse.error verbose 51 52 %code { 53 54 # define YYLLOC_DEFAULT(Current, Rhs, N) \ 55 do { \ 56 if (N) \ 57 { \ 58 (Current).level = YYRHSLOC(Rhs, 1).level; \ 59 (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ 60 (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ 61 (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ 62 (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ 63 } \ 64 else \ 65 { \ 66 (Current).level = YYRHSLOC(Rhs, 0).level; \ 67 (Current).first_line = (Current).last_line = \ 68 YYRHSLOC (Rhs, 0).last_line; \ 69 (Current).first_column = (Current).last_column = \ 70 YYRHSLOC (Rhs, 0).last_column; \ 71 } \ 72 } while (0) 73 74 #define CHECK_ERROR_WITHOUT_MESSAGE(val, token) do { \ 75 if (!(val)) \ 76 { \ 77 YYERROR; \ 78 } \ 79 } while (0) 80 81 #define CHECK_ERROR(val, token, errorfmt, ...) do { \ 82 if (!(val)) \ 83 { \ 84 if (errorfmt) \ 85 { \ 86 gchar __buf[256]; \ 87 g_snprintf(__buf, sizeof(__buf), errorfmt, ## __VA_ARGS__); \ 88 yyerror(& (token), lexer, NULL, NULL, __buf); \ 89 } \ 90 YYERROR; \ 91 } \ 92 } while (0) 93 94 #define CHECK_ERROR_GERROR(val, token, error, errorfmt, ...) do { \ 95 if (!(val)) \ 96 { \ 97 if (errorfmt) \ 98 { \ 99 gchar __buf[256]; \ 100 g_snprintf(__buf, sizeof(__buf), errorfmt ", error=%s", ## __VA_ARGS__, error->message); \ 101 yyerror(& (token), lexer, NULL, NULL, __buf); \ 102 } \ 103 g_clear_error(&error); \ 104 YYERROR; \ 105 } \ 106 } while (0) 107 108 #define YYMAXDEPTH 20000 109 110 111 } 112 113 /* plugin types, must be equal to the numerical values of the plugin type in plugin.h */ 114 115 %token LL_CONTEXT_ROOT 1 116 %token LL_CONTEXT_DESTINATION 2 117 %token LL_CONTEXT_SOURCE 3 118 %token LL_CONTEXT_PARSER 4 119 %token LL_CONTEXT_REWRITE 5 120 %token LL_CONTEXT_FILTER 6 121 %token LL_CONTEXT_LOG 7 122 %token LL_CONTEXT_BLOCK_DEF 8 123 %token LL_CONTEXT_BLOCK_REF 9 124 %token LL_CONTEXT_BLOCK_CONTENT 10 125 %token LL_CONTEXT_BLOCK_ARG 11 126 %token LL_CONTEXT_PRAGMA 12 127 %token LL_CONTEXT_FORMAT 13 128 %token LL_CONTEXT_TEMPLATE_FUNC 14 129 %token LL_CONTEXT_INNER_DEST 15 130 %token LL_CONTEXT_INNER_SRC 16 131 %token LL_CONTEXT_CLIENT_PROTO 17 132 %token LL_CONTEXT_SERVER_PROTO 18 133 %token LL_CONTEXT_OPTIONS 19 134 %token LL_CONTEXT_CONFIG 20 135 136 /* this is a placeholder for unit tests, must be the latest & largest */ 137 %token LL_CONTEXT_MAX 21 138 139 140 /* statements */ 141 %token KW_SOURCE 10000 142 %token KW_FILTER 10001 143 %token KW_PARSER 10002 144 %token KW_DESTINATION 10003 145 %token KW_LOG 10004 146 %token KW_OPTIONS 10005 147 %token KW_INCLUDE 10006 148 %token KW_BLOCK 10007 149 %token KW_JUNCTION 10008 150 %token KW_CHANNEL 10009 151 %token KW_IF 10010 152 %token KW_ELSE 10011 153 %token KW_ELIF 10012 154 155 /* source & destination items */ 156 %token KW_INTERNAL 10020 157 %token KW_SYSLOG 10060 158 159 /* option items */ 160 %token KW_MARK_FREQ 10071 161 %token KW_STATS_FREQ 10072 162 %token KW_STATS_LEVEL 10073 163 %token KW_STATS_LIFETIME 10074 164 %token KW_FLUSH_LINES 10075 165 %token KW_SUPPRESS 10076 166 %token KW_FLUSH_TIMEOUT 10077 167 %token KW_LOG_MSG_SIZE 10078 168 %token KW_FILE_TEMPLATE 10079 169 %token KW_PROTO_TEMPLATE 10080 170 %token KW_MARK_MODE 10081 171 %token KW_ENCODING 10082 172 %token KW_TYPE 10083 173 %token KW_STATS_MAX_DYNAMIC 10084 174 %token KW_MIN_IW_SIZE_PER_READER 10085 175 %token KW_WORKERS 10086 176 %token KW_BATCH_LINES 10087 177 %token KW_BATCH_TIMEOUT 10088 178 %token KW_TRIM_LARGE_MESSAGES 10089 179 180 %token KW_CHAIN_HOSTNAMES 10090 181 %token KW_NORMALIZE_HOSTNAMES 10091 182 %token KW_KEEP_HOSTNAME 10092 183 %token KW_CHECK_HOSTNAME 10093 184 %token KW_BAD_HOSTNAME 10094 185 186 %token KW_KEEP_TIMESTAMP 10100 187 188 %token KW_USE_DNS 10110 189 %token KW_USE_FQDN 10111 190 %token KW_CUSTOM_DOMAIN 10112 191 192 %token KW_DNS_CACHE 10120 193 %token KW_DNS_CACHE_SIZE 10121 194 195 %token KW_DNS_CACHE_EXPIRE 10130 196 %token KW_DNS_CACHE_EXPIRE_FAILED 10131 197 %token KW_DNS_CACHE_HOSTS 10132 198 199 %token KW_PERSIST_ONLY 10140 200 %token KW_USE_RCPTID 10141 201 %token KW_USE_UNIQID 10142 202 203 %token KW_TZ_CONVERT 10150 204 %token KW_TS_FORMAT 10151 205 %token KW_FRAC_DIGITS 10152 206 207 %token KW_LOG_FIFO_SIZE 10160 208 %token KW_LOG_FETCH_LIMIT 10162 209 %token KW_LOG_IW_SIZE 10163 210 %token KW_LOG_PREFIX 10164 211 %token KW_PROGRAM_OVERRIDE 10165 212 %token KW_HOST_OVERRIDE 10166 213 214 %token KW_THROTTLE 10170 215 %token KW_THREADED 10171 216 %token KW_PASS_UNIX_CREDENTIALS 10231 217 218 %token KW_PERSIST_NAME 10302 219 220 %token KW_READ_OLD_RECORDS 10304 221 %token KW_USE_SYSLOGNG_PID 10305 222 223 /* log statement options */ 224 %token KW_FLAGS 10190 225 226 /* reader options */ 227 %token KW_PAD_SIZE 10200 228 %token KW_TIME_ZONE 10201 229 %token KW_RECV_TIME_ZONE 10202 230 %token KW_SEND_TIME_ZONE 10203 231 %token KW_LOCAL_TIME_ZONE 10204 232 %token KW_FORMAT 10205 233 234 /* destination writer options */ 235 %token KW_TRUNCATE_SIZE 10206 236 237 /* timers */ 238 %token KW_TIME_REOPEN 10210 239 %token KW_TIME_REAP 10211 240 %token KW_TIME_SLEEP 10212 241 242 /* destination options */ 243 %token KW_TMPL_ESCAPE 10220 244 245 /* driver specific options */ 246 %token KW_OPTIONAL 10230 247 248 /* file related options */ 249 %token KW_CREATE_DIRS 10240 250 251 %token KW_OWNER 10250 252 %token KW_GROUP 10251 253 %token KW_PERM 10252 254 255 %token KW_DIR_OWNER 10260 256 %token KW_DIR_GROUP 10261 257 %token KW_DIR_PERM 10262 258 259 %token KW_TEMPLATE 10270 260 %token KW_TEMPLATE_ESCAPE 10271 261 %token KW_TEMPLATE_FUNCTION 10272 262 263 %token KW_DEFAULT_FACILITY 10300 264 %token KW_DEFAULT_SEVERITY 10301 265 266 %token KW_PORT 10323 267 /* misc options */ 268 269 %token KW_USE_TIME_RECVD 10340 270 271 /* filter items*/ 272 %token KW_FACILITY 10350 273 %token KW_SEVERITY 10351 274 %token KW_HOST 10352 275 %token KW_MATCH 10353 276 %token KW_MESSAGE 10354 277 %token KW_NETMASK 10355 278 %token KW_TAGS 10356 279 %token KW_NETMASK6 10357 280 281 /* parser items */ 282 283 /* rewrite items */ 284 %token KW_REWRITE 10370 285 %token KW_CONDITION 10371 286 %token KW_VALUE 10372 287 288 /* yes/no switches */ 289 290 %token KW_YES 10380 291 %token KW_NO 10381 292 293 %token KW_IFDEF 10410 294 %token KW_ENDIF 10411 295 296 %token LL_DOTDOT 10420 297 %token LL_DOTDOTDOT 10421 298 %token LL_PRAGMA 10422 299 %token LL_EOL 10423 300 %token LL_ERROR 10424 301 %token LL_ARROW 10425 302 303 %token <cptr> LL_IDENTIFIER 10430 304 %token <num> LL_NUMBER 10431 305 %token <fnum> LL_FLOAT 10432 306 %token <cptr> LL_STRING 10433 307 %token <token> LL_TOKEN 10434 308 %token <cptr> LL_BLOCK 10435 309 310 %destructor { free($$); } <cptr> 311 312 /* value pairs */ 313 %token KW_VALUE_PAIRS 10500 314 %token KW_EXCLUDE 10502 315 %token KW_PAIR 10503 316 %token KW_KEY 10504 317 %token KW_SCOPE 10505 318 %token KW_SHIFT 10506 319 %token KW_SHIFT_LEVELS 10507 320 %token KW_REKEY 10508 321 %token KW_ADD_PREFIX 10509 322 %token KW_REPLACE_PREFIX 10510 323 324 %token KW_ON_ERROR 10511 325 326 %token KW_RETRIES 10512 327 328 %token KW_FETCH_NO_DATA_DELAY 10513 329 330 %type <ptr> source_content 331 %type <ptr> source_items 332 %type <ptr> source_item 333 %type <ptr> source_afinter 334 %type <ptr> source_plugin 335 %type <ptr> source_afinter_params 336 337 %type <ptr> dest_content 338 %type <ptr> dest_items 339 %type <ptr> dest_item 340 %type <ptr> dest_plugin 341 342 %type <ptr> template_content 343 %type <ptr> template_content_list 344 345 %type <ptr> filter_content 346 347 %type <ptr> parser_content 348 349 %type <ptr> rewrite_content 350 351 %type <ptr> log_items 352 %type <ptr> log_item 353 354 %type <ptr> log_last_junction 355 %type <ptr> log_junction 356 %type <ptr> log_content 357 %type <ptr> log_conditional 358 %type <ptr> log_if 359 %type <ptr> log_forks 360 %type <ptr> log_fork 361 362 %type <num> log_flags 363 %type <num> log_flags_items 364 365 %type <ptr> value_pair_option 366 367 %type <num> yesno 368 %type <num> dnsmode 369 %type <num> dest_writer_options_flags 370 371 %type <cptr> string 372 %type <cptr> string_or_number 373 %type <cptr> normalized_flag 374 %type <ptr> string_list 375 %type <ptr> string_list_build 376 %type <num> facility_string 377 %type <num> severity_string 378 379 %type <num> positive_integer 380 %type <num> positive_integer64 381 %type <num> nonnegative_integer 382 %type <num> nonnegative_integer64 383 %type <fnum> positive_float 384 %type <fnum> nonnegative_float 385 %type <cptr> path_no_check 386 %type <cptr> path_secret 387 %type <cptr> path_check 388 %type <cptr> path 389 390 391 %token KW_AMQP 392 %token KW_EXCHANGE 393 %token KW_EXCHANGE_DECLARE 394 %token KW_EXCHANGE_TYPE 395 %token KW_PERSISTENT 396 %token KW_VHOST 397 %token KW_ROUTING_KEY 398 %token KW_BODY 399 %token KW_AUTH_METHOD 400 %token KW_PASSWORD 401 %token KW_USERNAME 402 %token KW_MAX_CHANNEL 403 %token KW_FRAME_SIZE 404 %token KW_HEARTBEAT 405 %token KW_CA_FILE 406 %token KW_KEY_FILE 407 %token KW_CERT_FILE 408 %token KW_PEER_VERIFY 409 %token KW_TLS 410 411 %% 412 413 start 414 : LL_CONTEXT_DESTINATION KW_AMQP 415 { 416 last_driver = *instance = afamqp_dd_new(configuration); 417 } 418 '(' afamqp_options ')' { YYACCEPT; } 419 ; 420 421 afamqp_options 422 : afamqp_option afamqp_options 423 | 424 ; 425 426 afamqp_option 427 : KW_HOST '(' string ')' { afamqp_dd_set_host(last_driver, $3); free($3); } 428 | KW_PORT '(' positive_integer ')' { afamqp_dd_set_port(last_driver, $3); } 429 | KW_VHOST '(' string ')' { afamqp_dd_set_vhost(last_driver, $3); free($3); } 430 | KW_EXCHANGE '(' string ')' { afamqp_dd_set_exchange(last_driver, $3); free($3); } 431 | KW_EXCHANGE_DECLARE '(' yesno ')' { afamqp_dd_set_exchange_declare(last_driver, $3); } 432 | KW_EXCHANGE_TYPE '(' string ')' { afamqp_dd_set_exchange_type(last_driver, $3); free($3); } 433 | KW_ROUTING_KEY '(' template_content ')' { afamqp_dd_set_routing_key(last_driver, $3); } 434 | KW_BODY '(' template_content ')' { afamqp_dd_set_body(last_driver, $3); } 435 | KW_PERSISTENT '(' yesno ')' { afamqp_dd_set_persistent(last_driver, $3); } 436 | KW_AUTH_METHOD '(' string ')' { CHECK_ERROR(afamqp_dd_set_auth_method(last_driver, $3), @3, "unknown auth-method() argument"); free($3); } 437 | KW_USERNAME '(' string ')' { afamqp_dd_set_user(last_driver, $3); free($3); } 438 | KW_PASSWORD '(' string ')' { afamqp_dd_set_password(last_driver, $3); free($3); } 439 | KW_MAX_CHANNEL '(' positive_integer ')' { afamqp_dd_set_max_channel(last_driver, $3); } 440 | KW_FRAME_SIZE '(' positive_integer ')' { afamqp_dd_set_frame_size(last_driver, $3); } 441 | KW_HEARTBEAT '(' nonnegative_integer ')' { afamqp_dd_set_offered_heartbeat(last_driver, $3); } 442 | value_pair_option { afamqp_dd_set_value_pairs(last_driver, $1); } 443 | threaded_dest_driver_general_option 444 | afamqp_tls_option 445 | KW_TLS '(' afamqp_tls_options ')' 446 | { last_template_options = afamqp_dd_get_template_options(last_driver); } template_option 447 ; 448 449 450 afamqp_tls_options 451 : afamqp_tls_option afamqp_tls_options 452 | 453 ; 454 455 afamqp_tls_option 456 : KW_CA_FILE '(' path_check ')' { afamqp_dd_set_ca_file(last_driver, $3); free($3); } 457 | KW_KEY_FILE '(' path_secret ')' { afamqp_dd_set_key_file(last_driver, $3); free($3); } 458 | KW_CERT_FILE '(' path_check ')' { afamqp_dd_set_cert_file(last_driver, $3); free($3); } 459 | KW_PEER_VERIFY '(' yesno ')' { afamqp_dd_set_peer_verify(last_driver, $3); } 460 ; 461 462 463 source_content 464 : 465 { cfg_lexer_push_context(lexer, LL_CONTEXT_SOURCE, NULL, "source statement"); } 466 source_items 467 { cfg_lexer_pop_context(lexer); } 468 { 469 $$ = log_expr_node_new_junction($2, &@$); 470 } 471 ; 472 473 source_items 474 : source_item semicolons source_items { $$ = log_expr_node_append_tail(log_expr_node_new_pipe($1, &@1), $3); } 475 | log_fork semicolons source_items { $$ = log_expr_node_append_tail($1, $3); } 476 | { $$ = NULL; } 477 ; 478 479 source_item 480 : source_afinter { $$ = $1; } 481 | source_plugin { $$ = $1; } 482 ; 483 484 source_plugin 485 : LL_IDENTIFIER 486 { 487 Plugin *p; 488 gint context = LL_CONTEXT_SOURCE; 489 490 p = cfg_find_plugin(configuration, context, $1); 491 CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); 492 493 last_driver = (LogDriver *) cfg_parse_plugin(configuration, p, &@1, NULL); 494 free($1); 495 if (!last_driver) 496 { 497 YYERROR; 498 } 499 $$ = last_driver; 500 } 501 ; 502 503 source_afinter 504 : KW_INTERNAL '(' source_afinter_params ')' { $$ = $3; } 505 ; 506 507 source_afinter_params 508 : { 509 last_driver = afinter_sd_new(configuration); 510 last_source_options = &((AFInterSourceDriver *) last_driver)->source_options.super; 511 } 512 source_afinter_options { $$ = last_driver; } 513 ; 514 515 source_afinter_options 516 : source_afinter_option source_afinter_options 517 | 518 ; 519 520 source_afinter_option 521 : KW_LOG_FIFO_SIZE '(' positive_integer ')' { ((AFInterSourceOptions *) last_source_options)->queue_capacity = $3; } 522 | source_option 523 ; 524 525 526 filter_content 527 : { 528 FilterExprNode *last_filter_expr = NULL; 529 530 CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&filter_expr_parser, lexer, (gpointer *) &last_filter_expr, NULL), @$); 531 532 $$ = log_expr_node_new_pipe(log_filter_pipe_new(last_filter_expr, configuration), &@$); 533 } 534 ; 535 536 parser_content 537 : 538 { 539 LogExprNode *last_parser_expr = NULL; 540 541 CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&parser_expr_parser, lexer, (gpointer *) &last_parser_expr, NULL), @$); 542 $$ = last_parser_expr; 543 } 544 ; 545 546 rewrite_content 547 : 548 { 549 LogExprNode *last_rewrite_expr = NULL; 550 551 CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&rewrite_expr_parser, lexer, (gpointer *) &last_rewrite_expr, NULL), @$); 552 $$ = last_rewrite_expr; 553 } 554 ; 555 556 dest_content 557 : { cfg_lexer_push_context(lexer, LL_CONTEXT_DESTINATION, NULL, "destination statement"); } 558 dest_items 559 { cfg_lexer_pop_context(lexer); } 560 { 561 $$ = log_expr_node_new_junction($2, &@$); 562 } 563 ; 564 565 566 dest_items 567 /* all destination drivers are added as an independent branch in a junction*/ 568 : dest_item semicolons dest_items { $$ = log_expr_node_append_tail(log_expr_node_new_pipe($1, &@1), $3); } 569 | log_fork semicolons dest_items { $$ = log_expr_node_append_tail($1, $3); } 570 | { $$ = NULL; } 571 ; 572 573 dest_item 574 : dest_plugin { $$ = $1; } 575 ; 576 577 dest_plugin 578 : LL_IDENTIFIER 579 { 580 Plugin *p; 581 gint context = LL_CONTEXT_DESTINATION; 582 583 p = cfg_find_plugin(configuration, context, $1); 584 CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); 585 586 last_driver = (LogDriver *) cfg_parse_plugin(configuration, p, &@1, NULL); 587 free($1); 588 if (!last_driver) 589 { 590 YYERROR; 591 } 592 $$ = last_driver; 593 } 594 ; 595 596 log_items 597 : log_item semicolons log_items { log_expr_node_append_tail($1, $3); $$ = $1; } 598 | { $$ = NULL; } 599 ; 600 601 log_item 602 : KW_SOURCE '(' string ')' { $$ = log_expr_node_new_source_reference($3, &@$); free($3); } 603 | KW_SOURCE '{' source_content '}' { $$ = log_expr_node_new_source(NULL, $3, &@$); } 604 | KW_FILTER '(' string ')' { $$ = log_expr_node_new_filter_reference($3, &@$); free($3); } 605 | KW_FILTER '{' filter_content '}' { $$ = log_expr_node_new_filter(NULL, $3, &@$); } 606 | KW_PARSER '(' string ')' { $$ = log_expr_node_new_parser_reference($3, &@$); free($3); } 607 | KW_PARSER '{' parser_content '}' { $$ = log_expr_node_new_parser(NULL, $3, &@$); } 608 | KW_REWRITE '(' string ')' { $$ = log_expr_node_new_rewrite_reference($3, &@$); free($3); } 609 | KW_REWRITE '{' rewrite_content '}' { $$ = log_expr_node_new_rewrite(NULL, $3, &@$); } 610 | KW_DESTINATION '(' string ')' { $$ = log_expr_node_new_destination_reference($3, &@$); free($3); } 611 | KW_DESTINATION '{' dest_content '}' { $$ = log_expr_node_new_destination(NULL, $3, &@$); } 612 | log_conditional { $$ = $1; } 613 | log_junction { $$ = $1; } 614 ; 615 616 log_junction 617 : KW_JUNCTION '{' log_forks '}' { $$ = log_expr_node_new_junction($3, &@$); } 618 ; 619 620 log_last_junction 621 622 /* this rule matches the last set of embedded log {} 623 * statements at the end of the log {} block. 624 * It is the final junction and was the only form of creating 625 * a processing tree before syslog-ng 3.4. 626 * 627 * We emulate if the user was writing junction {} explicitly. 628 */ 629 : log_forks { $$ = $1 ? log_expr_node_new_junction($1, &@1) : NULL; } 630 ; 631 632 633 log_forks 634 : log_fork semicolons log_forks { log_expr_node_append_tail($1, $3); $$ = $1; } 635 | { $$ = NULL; } 636 ; 637 638 log_fork 639 : KW_LOG '{' log_content '}' { $$ = $3; } 640 | KW_CHANNEL '{' log_content '}' { $$ = $3; } 641 ; 642 643 log_conditional 644 : log_if { $$ = $1; } 645 | log_if KW_ELSE '{' log_content '}' 646 { 647 log_expr_node_conditional_set_false_branch_of_the_last_if($1, $4); 648 $$ = $1; 649 } 650 ; 651 652 log_if 653 : KW_IF '(' filter_content ')' '{' log_content '}' 654 { 655 $$ = log_expr_node_new_conditional_with_filter($3, $6, &@$); 656 } 657 | KW_IF '{' log_content '}' 658 { 659 $$ = log_expr_node_new_conditional_with_block($3, &@$); 660 } 661 | log_if KW_ELIF '(' filter_content ')' '{' log_content '}' 662 { 663 LogExprNode *false_branch; 664 665 false_branch = log_expr_node_new_conditional_with_filter($4, $7, &@$); 666 log_expr_node_conditional_set_false_branch_of_the_last_if($1, false_branch); 667 $$ = $1; 668 } 669 | log_if KW_ELIF '{' log_content '}' 670 { 671 LogExprNode *false_branch; 672 673 false_branch = log_expr_node_new_conditional_with_block($4, &@$); 674 log_expr_node_conditional_set_false_branch_of_the_last_if($1, false_branch); 675 $$ = $1; 676 } 677 ; 678 679 log_content 680 : log_items log_last_junction log_flags { $$ = log_expr_node_new_log(log_expr_node_append_tail($1, $2), $3, &@$); } 681 ; 682 683 log_flags 684 : KW_FLAGS '(' log_flags_items ')' semicolons { $$ = $3; } 685 | { $$ = 0; } 686 ; 687 688 log_flags_items 689 : normalized_flag log_flags_items { $$ = log_expr_node_lookup_flag($1) | $2; free($1); } 690 | { $$ = 0; } 691 ; 692 693 694 template_content_inner 695 : string 696 { 697 GError *error = NULL; 698 699 CHECK_ERROR_GERROR(log_template_compile(last_template, $1, &error), @1, error, "Error compiling template"); 700 free($1); 701 } 702 | LL_IDENTIFIER '(' string ')' 703 { 704 GError *error = NULL; 705 706 CHECK_ERROR_GERROR(log_template_compile(last_template, $3, &error), @3, error, "Error compiling template"); 707 free($3); 708 709 CHECK_ERROR_GERROR(log_template_set_type_hint(last_template, $1, &error), @1, error, "Error setting the template type-hint \"%s\"", $1); 710 free($1); 711 } 712 ; 713 714 template_content 715 : { last_template = log_template_new(configuration, NULL); } template_content_inner { $$ = last_template; } 716 ; 717 718 template_content_list 719 : template_content template_content_list { $$ = g_list_prepend($2, $1); } 720 | { $$ = NULL; } 721 ; 722 723 724 725 string 726 : LL_IDENTIFIER 727 | LL_STRING 728 ; 729 730 yesno 731 : KW_YES { $$ = 1; } 732 | KW_NO { $$ = 0; } 733 | LL_NUMBER { $$ = $1; } 734 ; 735 736 dnsmode 737 : yesno { $$ = $1; } 738 | KW_PERSIST_ONLY { $$ = 2; } 739 ; 740 741 nonnegative_integer64 742 : LL_NUMBER 743 { 744 CHECK_ERROR(($1 >= 0), @1, "It cannot be negative"); 745 } 746 ; 747 748 nonnegative_integer 749 : nonnegative_integer64 750 { 751 CHECK_ERROR(($1 <= G_MAXINT32), @1, "Must be smaller than 2^31"); 752 } 753 ; 754 755 positive_integer64 756 : LL_NUMBER 757 { 758 CHECK_ERROR(($1 > 0), @1, "Must be positive"); 759 } 760 ; 761 762 positive_integer 763 : positive_integer64 764 { 765 CHECK_ERROR(($1 <= G_MAXINT32), @1, "Must be smaller than 2^31"); 766 } 767 ; 768 769 nonnegative_float 770 : LL_FLOAT 771 { 772 CHECK_ERROR(($1 >= 0), @1, "It cannot be negative"); 773 } 774 | nonnegative_integer 775 { 776 $$ = (double) $1; 777 } 778 ; 779 780 positive_float 781 : LL_FLOAT 782 { 783 CHECK_ERROR(($1 > 0), @1, "Must be positive"); 784 } 785 | positive_integer 786 { 787 $$ = (double) $1; 788 } 789 ; 790 791 string_or_number 792 : string { $$ = $1; } 793 | LL_NUMBER { $$ = strdup(lexer->token_text->str); } 794 | LL_FLOAT { $$ = strdup(lexer->token_text->str); } 795 ; 796 797 path 798 : string 799 { 800 struct stat buffer; 801 int ret = stat($1, &buffer); 802 CHECK_ERROR((ret == 0), @1, "File \"%s\" not found: %s", $1, strerror(errno)); 803 $$ = $1; 804 } 805 ; 806 807 path_check 808 : path { cfg_path_track_file(configuration, $1, "path_check"); } 809 ; 810 811 path_secret 812 : path { cfg_path_track_file(configuration, $1, "path_secret"); } 813 ; 814 815 path_no_check 816 : string { cfg_path_track_file(configuration, $1, "path_no_check"); } 817 ; 818 819 normalized_flag 820 : string { $$ = normalize_flag($1); free($1); } 821 ; 822 823 string_list 824 : string_list_build { $$ = $1; } 825 ; 826 827 string_list_build 828 : string string_list_build { $$ = g_list_prepend($2, g_strdup($1)); free($1); } 829 | { $$ = NULL; } 830 ; 831 832 semicolons 833 : ';' 834 | ';' semicolons 835 ; 836 837 severity_string 838 : string 839 { 840 /* return the numeric value of the "level" */ 841 int n = syslog_name_lookup_severity_by_name($1); 842 CHECK_ERROR((n != -1), @1, "Unknown priority level\"%s\"", $1); 843 free($1); 844 $$ = n; 845 } 846 ; 847 848 facility_string 849 : string 850 { 851 /* return the numeric value of facility */ 852 int n = syslog_name_lookup_facility_by_name($1); 853 CHECK_ERROR((n != -1), @1, "Unknown facility \"%s\"", $1); 854 free($1); 855 $$ = n; 856 } 857 | KW_SYSLOG { $$ = LOG_SYSLOG; } 858 ; 859 860 parser_opt 861 : KW_TEMPLATE '(' string ')' { 862 LogTemplate *template; 863 GError *error = NULL; 864 865 template = cfg_tree_check_inline_template(&configuration->tree, $3, &error); 866 CHECK_ERROR_GERROR(template != NULL, @3, error, "Error compiling template"); 867 log_parser_set_template(last_parser, template); 868 free($3); 869 } 870 ; 871 872 driver_option 873 : KW_PERSIST_NAME '(' string ')' { log_pipe_set_persist_name(&last_driver->super, $3); free($3); } 874 ; 875 876 inner_source 877 : LL_IDENTIFIER 878 { 879 Plugin *p; 880 gint context = LL_CONTEXT_INNER_SRC; 881 gpointer value; 882 883 p = cfg_find_plugin(configuration, context, $1); 884 CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); 885 886 value = cfg_parse_plugin(configuration, p, &@1, last_driver); 887 888 free($1); 889 if (!value) 890 { 891 YYERROR; 892 } 893 if (!log_driver_add_plugin(last_driver, (LogDriverPlugin *) value)) 894 { 895 log_driver_plugin_free(value); 896 CHECK_ERROR(TRUE, @1, "Error while registering the plugin %s in this destination", $1); 897 } 898 } 899 ; 900 901 /* All source drivers should incorporate this rule, implies driver_option */ 902 source_driver_option 903 : inner_source 904 | driver_option 905 ; 906 907 inner_dest 908 : LL_IDENTIFIER 909 { 910 Plugin *p; 911 gint context = LL_CONTEXT_INNER_DEST; 912 gpointer value; 913 914 p = cfg_find_plugin(configuration, context, $1); 915 CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); 916 917 value = cfg_parse_plugin(configuration, p, &@1, last_driver); 918 919 free($1); 920 if (!value) 921 { 922 YYERROR; 923 } 924 if (!log_driver_add_plugin(last_driver, (LogDriverPlugin *) value)) 925 { 926 log_driver_plugin_free(value); 927 CHECK_ERROR(TRUE, @1, "Error while registering the plugin %s in this destination", $1); 928 } 929 } 930 ; 931 932 /* implies driver_option */ 933 dest_driver_option 934 /* NOTE: plugins need to set "last_driver" in order to incorporate this rule in their grammar */ 935 936 : KW_LOG_FIFO_SIZE '(' positive_integer ')' { ((LogDestDriver *) last_driver)->log_fifo_size = $3; } 937 | KW_THROTTLE '(' nonnegative_integer ')' { ((LogDestDriver *) last_driver)->throttle = $3; } 938 | inner_dest 939 | driver_option 940 ; 941 942 threaded_dest_driver_batch_option 943 : KW_BATCH_LINES '(' nonnegative_integer ')' { log_threaded_dest_driver_set_batch_lines(last_driver, $3); } 944 | KW_BATCH_TIMEOUT '(' positive_integer ')' { log_threaded_dest_driver_set_batch_timeout(last_driver, $3); } 945 ; 946 947 threaded_dest_driver_workers_option 948 : KW_WORKERS '(' positive_integer ')' { log_threaded_dest_driver_set_num_workers(last_driver, $3); } 949 ; 950 951 /* implies dest_driver_option */ 952 threaded_dest_driver_general_option 953 : KW_RETRIES '(' positive_integer ')' 954 { 955 log_threaded_dest_driver_set_max_retries_on_error(last_driver, $3); 956 } 957 | KW_TIME_REOPEN '(' positive_integer ')' { log_threaded_dest_driver_set_time_reopen(last_driver, $3); } 958 | dest_driver_option 959 ; 960 961 /* implies source_driver_option and source_option */ 962 threaded_source_driver_option 963 : KW_FORMAT '(' string ')' { log_threaded_source_driver_get_parse_options(last_driver)->format = g_strdup($3); free($3); } 964 | KW_FLAGS '(' threaded_source_driver_option_flags ')' 965 | { last_msg_format_options = log_threaded_source_driver_get_parse_options(last_driver); } msg_format_option 966 | { last_source_options = log_threaded_source_driver_get_source_options(last_driver); } source_option 967 | source_driver_option 968 ; 969 970 threaded_fetcher_driver_option 971 : KW_FETCH_NO_DATA_DELAY '(' nonnegative_float ')' { log_threaded_fetcher_driver_set_fetch_no_data_delay(last_driver, $3); } 972 | KW_TIME_REOPEN '(' positive_integer ')' { log_threaded_fetcher_driver_set_time_reopen(last_driver, $3); } 973 ; 974 975 threaded_source_driver_option_flags 976 : string threaded_source_driver_option_flags 977 { 978 CHECK_ERROR(msg_format_options_process_flag(log_threaded_source_driver_get_parse_options(last_driver), $1), @1, "Unknown flag \"%s\"", $1); 979 free($1); 980 } 981 | 982 ; 983 984 /* LogSource related options */ 985 source_option 986 /* NOTE: plugins need to set "last_source_options" in order to incorporate this rule in their grammar */ 987 : KW_LOG_IW_SIZE '(' positive_integer ')' { last_source_options->init_window_size = $3; } 988 | KW_CHAIN_HOSTNAMES '(' yesno ')' { last_source_options->chain_hostnames = $3; } 989 | KW_KEEP_HOSTNAME '(' yesno ')' { last_source_options->keep_hostname = $3; } 990 | KW_PROGRAM_OVERRIDE '(' string ')' { last_source_options->program_override = g_strdup($3); free($3); } 991 | KW_HOST_OVERRIDE '(' string ')' { last_source_options->host_override = g_strdup($3); free($3); } 992 | KW_LOG_PREFIX '(' string ')' { gchar *p = strrchr($3, ':'); if (p) *p = 0; last_source_options->program_override = g_strdup($3); free($3); } 993 | KW_KEEP_TIMESTAMP '(' yesno ')' { last_source_options->keep_timestamp = $3; } 994 | KW_READ_OLD_RECORDS '(' yesno ')' { last_source_options->read_old_records = $3; } 995 | KW_USE_SYSLOGNG_PID '(' yesno ')' { last_source_options->use_syslogng_pid = $3; } 996 | KW_TAGS '(' string_list ')' { log_source_options_set_tags(last_source_options, $3); } 997 | { last_host_resolve_options = &last_source_options->host_resolve_options; } host_resolve_option 998 ; 999 1000 /* LogReader related options, implies source_option */ 1001 source_reader_option 1002 /* NOTE: plugins need to set "last_reader_options" in order to incorporate this rule in their grammar */ 1003 1004 : KW_CHECK_HOSTNAME '(' yesno ')' { last_reader_options->check_hostname = $3; } 1005 | KW_FLAGS '(' source_reader_option_flags ')' 1006 | KW_LOG_FETCH_LIMIT '(' positive_integer ')' { last_reader_options->fetch_limit = $3; } 1007 | KW_FORMAT '(' string ')' { last_reader_options->parse_options.format = g_strdup($3); free($3); } 1008 | { last_source_options = &last_reader_options->super; } source_option 1009 | { last_proto_server_options = &last_reader_options->proto_options.super; } source_proto_option 1010 | { last_msg_format_options = &last_reader_options->parse_options; } msg_format_option 1011 ; 1012 1013 source_reader_option_flags 1014 : string source_reader_option_flags { CHECK_ERROR(log_reader_options_process_flag(last_reader_options, $1), @1, "Unknown flag \"%s\"", $1); free($1); } 1015 | KW_CHECK_HOSTNAME source_reader_option_flags { log_reader_options_process_flag(last_reader_options, "check-hostname"); } 1016 | 1017 ; 1018 1019 /* LogProtoSource related options */ 1020 source_proto_option 1021 : KW_ENCODING '(' string ')' 1022 { 1023 CHECK_ERROR(log_proto_server_options_set_encoding(last_proto_server_options, $3), 1024 @3, 1025 "unknown encoding \"%s\"", $3); 1026 free($3); 1027 } 1028 | KW_LOG_MSG_SIZE '(' positive_integer ')' { last_proto_server_options->max_msg_size = $3; } 1029 | KW_TRIM_LARGE_MESSAGES '(' yesno ')' { last_proto_server_options->trim_large_messages = $3; } 1030 ; 1031 1032 host_resolve_option 1033 : KW_USE_FQDN '(' yesno ')' { last_host_resolve_options->use_fqdn = $3; } 1034 | KW_USE_DNS '(' dnsmode ')' { last_host_resolve_options->use_dns = $3; } 1035 | KW_DNS_CACHE '(' yesno ')' { last_host_resolve_options->use_dns_cache = $3; } 1036 | KW_NORMALIZE_HOSTNAMES '(' yesno ')' { last_host_resolve_options->normalize_hostnames = $3; } 1037 ; 1038 1039 msg_format_option 1040 : KW_TIME_ZONE '(' string ')' { last_msg_format_options->recv_time_zone = g_strdup($3); free($3); } 1041 | KW_DEFAULT_SEVERITY '(' severity_string ')' 1042 { 1043 if (last_msg_format_options->default_pri == 0xFFFF) 1044 last_msg_format_options->default_pri = LOG_USER; 1045 last_msg_format_options->default_pri = (last_msg_format_options->default_pri & ~LOG_PRIMASK) | $3; 1046 } 1047 | KW_DEFAULT_FACILITY '(' facility_string ')' 1048 { 1049 if (last_msg_format_options->default_pri == 0xFFFF) 1050 last_msg_format_options->default_pri = LOG_NOTICE; 1051 last_msg_format_options->default_pri = (last_msg_format_options->default_pri & LOG_PRIMASK) | $3; 1052 } 1053 ; 1054 1055 dest_writer_options 1056 : dest_writer_option dest_writer_options 1057 | 1058 ; 1059 1060 dest_writer_option 1061 /* NOTE: plugins need to set "last_writer_options" in order to incorporate this rule in their grammar */ 1062 1063 : KW_FLAGS '(' dest_writer_options_flags ')' { last_writer_options->options = $3; } 1064 | KW_FLUSH_LINES '(' nonnegative_integer ')' { last_writer_options->flush_lines = $3; } 1065 | KW_FLUSH_TIMEOUT '(' positive_integer ')' { } 1066 | KW_SUPPRESS '(' nonnegative_integer ')' { last_writer_options->suppress = $3; } 1067 | KW_TEMPLATE '(' string ')' { 1068 GError *error = NULL; 1069 1070 last_writer_options->template = cfg_tree_check_inline_template(&configuration->tree, $3, &error); 1071 CHECK_ERROR_GERROR(last_writer_options->template != NULL, @3, error, "Error compiling template"); 1072 free($3); 1073 } 1074 | KW_TEMPLATE_ESCAPE '(' yesno ')' { log_writer_options_set_template_escape(last_writer_options, $3); } 1075 | KW_PAD_SIZE '(' nonnegative_integer ')' { last_writer_options->padding = $3; } 1076 | KW_TRUNCATE_SIZE '(' nonnegative_integer ')' { last_writer_options->truncate_size = $3; } 1077 | KW_MARK_FREQ '(' nonnegative_integer ')' { last_writer_options->mark_freq = $3; } 1078 | KW_MARK_MODE '(' KW_INTERNAL ')' { log_writer_options_set_mark_mode(last_writer_options, "internal"); } 1079 | KW_MARK_MODE '(' string ')' 1080 { 1081 CHECK_ERROR(cfg_lookup_mark_mode($3) != -1, @3, "illegal mark mode \"%s\"", $3); 1082 log_writer_options_set_mark_mode(last_writer_options, $3); 1083 free($3); 1084 } 1085 | KW_TIME_REOPEN '(' positive_integer ')' { last_writer_options->time_reopen = $3; } 1086 | { last_template_options = &last_writer_options->template_options; } template_option 1087 ; 1088 1089 dest_writer_options_flags 1090 : normalized_flag dest_writer_options_flags { $$ = log_writer_options_lookup_flag($1) | $2; free($1); } 1091 | { $$ = 0; } 1092 ; 1093 1094 file_perm_option 1095 : KW_OWNER '(' string_or_number ')' { file_perm_options_set_file_uid(last_file_perm_options, $3); free($3); } 1096 | KW_OWNER '(' ')' { file_perm_options_dont_change_file_uid(last_file_perm_options); } 1097 | KW_GROUP '(' string_or_number ')' { file_perm_options_set_file_gid(last_file_perm_options, $3); free($3); } 1098 | KW_GROUP '(' ')' { file_perm_options_dont_change_file_gid(last_file_perm_options); } 1099 | KW_PERM '(' LL_NUMBER ')' { file_perm_options_set_file_perm(last_file_perm_options, $3); } 1100 | KW_PERM '(' ')' { file_perm_options_dont_change_file_perm(last_file_perm_options); } 1101 | KW_DIR_OWNER '(' string_or_number ')' { file_perm_options_set_dir_uid(last_file_perm_options, $3); free($3); } 1102 | KW_DIR_OWNER '(' ')' { file_perm_options_dont_change_dir_uid(last_file_perm_options); } 1103 | KW_DIR_GROUP '(' string_or_number ')' { file_perm_options_set_dir_gid(last_file_perm_options, $3); free($3); } 1104 | KW_DIR_GROUP '(' ')' { file_perm_options_dont_change_dir_gid(last_file_perm_options); } 1105 | KW_DIR_PERM '(' LL_NUMBER ')' { file_perm_options_set_dir_perm(last_file_perm_options, $3); } 1106 | KW_DIR_PERM '(' ')' { file_perm_options_dont_change_dir_perm(last_file_perm_options); } 1107 ; 1108 1109 template_option 1110 : KW_TS_FORMAT '(' string ')' { last_template_options->ts_format = cfg_ts_format_value($3); free($3); } 1111 | KW_FRAC_DIGITS '(' nonnegative_integer ')' { last_template_options->frac_digits = $3; } 1112 | KW_TIME_ZONE '(' string ')' { last_template_options->time_zone[LTZ_SEND] = g_strdup($3); free($3); } 1113 | KW_SEND_TIME_ZONE '(' string ')' { last_template_options->time_zone[LTZ_SEND] = g_strdup($3); free($3); } 1114 | KW_LOCAL_TIME_ZONE '(' string ')' { last_template_options->time_zone[LTZ_LOCAL] = g_strdup($3); free($3); } 1115 | KW_ON_ERROR '(' string ')' 1116 { 1117 gint on_error; 1118 1119 CHECK_ERROR(log_template_on_error_parse($3, &on_error), @3, "Invalid on-error() setting \"%s\"", $3); 1120 free($3); 1121 1122 log_template_options_set_on_error(last_template_options, on_error); 1123 } 1124 ; 1125 1126 matcher_option 1127 : KW_TYPE '(' string ')' { CHECK_ERROR(log_matcher_options_set_type(last_matcher_options, $3), @3, "unknown matcher type \"%s\"", $3); free($3); } 1128 | KW_FLAGS '(' matcher_flags ')' 1129 ; 1130 1131 matcher_flags 1132 : string matcher_flags { CHECK_ERROR(log_matcher_options_process_flag(last_matcher_options, $1), @1, "unknown matcher flag \"%s\"", $1); free($1); } 1133 | 1134 ; 1135 1136 value_pair_option 1137 : KW_VALUE_PAIRS 1138 { 1139 last_value_pairs = value_pairs_new(); 1140 } 1141 '(' vp_options ')' 1142 { $$ = last_value_pairs; } 1143 ; 1144 1145 vp_options 1146 : vp_option vp_options 1147 | 1148 ; 1149 1150 vp_option 1151 : KW_PAIR '(' string ':' template_content ')' 1152 { 1153 value_pairs_add_pair(last_value_pairs, $3, $5); 1154 free($3); 1155 } 1156 | KW_PAIR '(' string template_content ')' 1157 { 1158 value_pairs_add_pair(last_value_pairs, $3, $4); 1159 free($3); 1160 } 1161 | KW_KEY '(' string KW_REKEY '(' 1162 { 1163 last_vp_transset = value_pairs_transform_set_new($3); 1164 value_pairs_add_glob_pattern(last_value_pairs, $3, TRUE); 1165 free($3); 1166 } 1167 vp_rekey_options ')' { value_pairs_add_transforms(last_value_pairs, last_vp_transset); } ')' 1168 | KW_KEY '(' string_list ')' { value_pairs_add_glob_patterns(last_value_pairs, $3, TRUE); } 1169 | KW_REKEY '(' string 1170 { 1171 last_vp_transset = value_pairs_transform_set_new($3); 1172 free($3); 1173 } 1174 vp_rekey_options ')' { value_pairs_add_transforms(last_value_pairs, last_vp_transset); } 1175 | KW_EXCLUDE '(' string_list ')' { value_pairs_add_glob_patterns(last_value_pairs, $3, FALSE); } 1176 | KW_SCOPE '(' vp_scope_list ')' 1177 ; 1178 1179 vp_scope_list 1180 : string vp_scope_list { value_pairs_add_scope(last_value_pairs, $1); free($1); } 1181 | 1182 ; 1183 1184 vp_rekey_options 1185 : vp_rekey_option vp_rekey_options 1186 | 1187 ; 1188 1189 vp_rekey_option 1190 : KW_SHIFT '(' positive_integer ')' { value_pairs_transform_set_add_func(last_vp_transset, value_pairs_new_transform_shift($3)); } 1191 | KW_SHIFT_LEVELS '(' positive_integer ')' { value_pairs_transform_set_add_func(last_vp_transset, value_pairs_new_transform_shift_levels($3)); } 1192 | KW_ADD_PREFIX '(' string ')' { value_pairs_transform_set_add_func(last_vp_transset, value_pairs_new_transform_add_prefix($3)); free($3); } 1193 | KW_REPLACE_PREFIX '(' string string ')' { value_pairs_transform_set_add_func(last_vp_transset, value_pairs_new_transform_replace_prefix($3, $4)); free($3); free($4); } 1194 ; 1195 1196 rewrite_expr_opt 1197 : KW_VALUE '(' string ')' 1198 { 1199 const gchar *p = $3; 1200 if (p[0] == '$') 1201 { 1202 msg_warning("Value references in rewrite rules should not use the '$' prefix, those are only needed in templates", 1203 evt_tag_str("value", $3), 1204 cfg_lexer_format_location_tag(lexer, &@3)); 1205 p++; 1206 } 1207 last_rewrite->value_handle = log_msg_get_value_handle(p); 1208 CHECK_ERROR(!log_msg_is_handle_macro(last_rewrite->value_handle), @3, "%s is read-only, it cannot be changed in rewrite rules", p); 1209 CHECK_ERROR(log_msg_is_value_name_valid(p), @3, "%s is not a valid name for a name-value pair, perhaps a misspelled .SDATA reference?", p); 1210 free($3); 1211 } 1212 | rewrite_condition_opt 1213 ; 1214 1215 rewrite_condition_opt 1216 : KW_CONDITION '(' 1217 { 1218 FilterExprNode *filter_expr; 1219 1220 CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&filter_expr_parser, lexer, (gpointer *) &filter_expr, NULL), @1); 1221 log_rewrite_set_condition(last_rewrite, filter_expr); 1222 } ')' 1223 ; 1224 1225 1226 1227 %% 1228