1 /* 2 * Copyright (c) 2002-2011 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 #pragma GCC diagnostic ignored "-Wswitch-default" 28 29 #include "pragma-parser.h" 30 #include "plugin.h" 31 #include "cfg.h" 32 #include "messages.h" 33 34 #include <string.h> 35 36 } 37 38 %define api.prefix {pragma_} 39 %lex-param {CfgLexer *lexer} 40 %parse-param {CfgLexer *lexer} 41 %parse-param {gpointer *result} 42 %parse-param {gpointer arg} 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_VERSION 392 %token KW_VERSION_CURRENT 393 %token KW_DEFINE 394 %token KW_MODULE 395 %token KW_REQUIRES 396 397 %code { 398 399 #include <stdlib.h> 400 401 #define PRAGMA_BEGIN() ({ lexer->tokenize_eol++; }) 402 #define PRAGMA_END() ({ lexer->tokenize_eol--; }) 403 #define PRAGMA_ERROR() ({ PRAGMA_END(); YYERROR; }) 404 405 CfgArgs *last_module_args = NULL; 406 407 } 408 409 %type <cptr> requires_message 410 411 %% 412 413 414 start 415 : { PRAGMA_BEGIN(); } 416 stmt { if (yychar != PRAGMA_EMPTY) { cfg_lexer_unput_token(lexer, &yylval); } PRAGMA_END(); YYACCEPT; } 417 418 stmt 419 : stmt_without_eol LL_EOL 420 | stmt_with_eol 421 ; 422 423 stmt_without_eol 424 : version_stmt 425 | define_stmt 426 | module_stmt 427 ; 428 429 /* LL_EOL as a token needs to be consumed by the rules below, as they can 430 * change the lexer buffer by the time they return to the grammar. */ 431 stmt_with_eol 432 : include_stmt 433 | requires_stmt 434 ; 435 436 version_stmt 437 : KW_VERSION ':' KW_VERSION_CURRENT 438 { 439 if (!cfg_set_current_version(configuration)) 440 PRAGMA_ERROR(); 441 } 442 | KW_VERSION ':' string_or_number 443 { 444 guint parsed_version = process_version_string($3); 445 free($3); 446 if (parsed_version == 0) 447 PRAGMA_ERROR(); 448 if (!cfg_set_version(configuration, parsed_version)) 449 PRAGMA_ERROR(); 450 } 451 452 define_stmt 453 : KW_DEFINE LL_IDENTIFIER string_or_number 454 { 455 msg_debug("Global value changed", 456 evt_tag_str("define", $2), 457 evt_tag_str("value", $3)); 458 cfg_args_set(configuration->globals, $2, $3); 459 free($2); 460 free($3); 461 } 462 463 module_stmt 464 : KW_MODULE string { last_module_args = cfg_args_new(); } module_params 465 { 466 gboolean success = cfg_load_module_with_args(configuration, $2, last_module_args); 467 free($2); 468 469 cfg_args_unref(last_module_args); 470 last_module_args = NULL; 471 472 if (!success) 473 PRAGMA_ERROR(); 474 } 475 ; 476 477 module_params 478 : module_param module_params 479 | 480 ; 481 482 module_param 483 : LL_IDENTIFIER '(' string_or_number ')' { cfg_args_set(last_module_args, $1, $3); free($1); free($3); } 484 ; 485 486 include_stmt 487 : KW_INCLUDE string LL_EOL 488 { 489 CHECK_ERROR(cfg_lexer_include_file(lexer, $2), @2, "Error including %s", $2); 490 free($2); 491 } 492 ; 493 494 requires_stmt 495 : KW_REQUIRES string requires_message LL_EOL 496 { 497 if (!cfg_is_module_available(configuration, $2)) 498 { 499 if (0 == lexer->include_depth || $3) 500 { 501 msg_error("Cannot load required module", 502 evt_tag_str("module", $2), 503 evt_tag_str("details", $3 ? : "none"), 504 cfg_lexer_format_location_tag(lexer,&@1)); 505 free($2); 506 PRAGMA_ERROR(); 507 } 508 else 509 { 510 msg_debug("Included file was skipped because of a missing module", 511 evt_tag_str("module", $2), 512 cfg_lexer_format_location_tag(lexer,&@1)); 513 cfg_lexer_start_next_include(lexer); 514 } 515 } 516 free($2); 517 } 518 ; 519 520 requires_message 521 : string { $$ = $1; } 522 | { $$ = NULL; } 523 ; 524 525 526 source_content 527 : 528 { cfg_lexer_push_context(lexer, LL_CONTEXT_SOURCE, NULL, "source statement"); } 529 source_items 530 { cfg_lexer_pop_context(lexer); } 531 { 532 $$ = log_expr_node_new_junction($2, &@$); 533 } 534 ; 535 536 source_items 537 : source_item semicolons source_items { $$ = log_expr_node_append_tail(log_expr_node_new_pipe($1, &@1), $3); } 538 | log_fork semicolons source_items { $$ = log_expr_node_append_tail($1, $3); } 539 | { $$ = NULL; } 540 ; 541 542 source_item 543 : source_afinter { $$ = $1; } 544 | source_plugin { $$ = $1; } 545 ; 546 547 source_plugin 548 : LL_IDENTIFIER 549 { 550 Plugin *p; 551 gint context = LL_CONTEXT_SOURCE; 552 553 p = cfg_find_plugin(configuration, context, $1); 554 CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); 555 556 last_driver = (LogDriver *) cfg_parse_plugin(configuration, p, &@1, NULL); 557 free($1); 558 if (!last_driver) 559 { 560 YYERROR; 561 } 562 $$ = last_driver; 563 } 564 ; 565 566 source_afinter 567 : KW_INTERNAL '(' source_afinter_params ')' { $$ = $3; } 568 ; 569 570 source_afinter_params 571 : { 572 last_driver = afinter_sd_new(configuration); 573 last_source_options = &((AFInterSourceDriver *) last_driver)->source_options.super; 574 } 575 source_afinter_options { $$ = last_driver; } 576 ; 577 578 source_afinter_options 579 : source_afinter_option source_afinter_options 580 | 581 ; 582 583 source_afinter_option 584 : KW_LOG_FIFO_SIZE '(' positive_integer ')' { ((AFInterSourceOptions *) last_source_options)->queue_capacity = $3; } 585 | source_option 586 ; 587 588 589 filter_content 590 : { 591 FilterExprNode *last_filter_expr = NULL; 592 593 CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&filter_expr_parser, lexer, (gpointer *) &last_filter_expr, NULL), @$); 594 595 $$ = log_expr_node_new_pipe(log_filter_pipe_new(last_filter_expr, configuration), &@$); 596 } 597 ; 598 599 parser_content 600 : 601 { 602 LogExprNode *last_parser_expr = NULL; 603 604 CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&parser_expr_parser, lexer, (gpointer *) &last_parser_expr, NULL), @$); 605 $$ = last_parser_expr; 606 } 607 ; 608 609 rewrite_content 610 : 611 { 612 LogExprNode *last_rewrite_expr = NULL; 613 614 CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&rewrite_expr_parser, lexer, (gpointer *) &last_rewrite_expr, NULL), @$); 615 $$ = last_rewrite_expr; 616 } 617 ; 618 619 dest_content 620 : { cfg_lexer_push_context(lexer, LL_CONTEXT_DESTINATION, NULL, "destination statement"); } 621 dest_items 622 { cfg_lexer_pop_context(lexer); } 623 { 624 $$ = log_expr_node_new_junction($2, &@$); 625 } 626 ; 627 628 629 dest_items 630 /* all destination drivers are added as an independent branch in a junction*/ 631 : dest_item semicolons dest_items { $$ = log_expr_node_append_tail(log_expr_node_new_pipe($1, &@1), $3); } 632 | log_fork semicolons dest_items { $$ = log_expr_node_append_tail($1, $3); } 633 | { $$ = NULL; } 634 ; 635 636 dest_item 637 : dest_plugin { $$ = $1; } 638 ; 639 640 dest_plugin 641 : LL_IDENTIFIER 642 { 643 Plugin *p; 644 gint context = LL_CONTEXT_DESTINATION; 645 646 p = cfg_find_plugin(configuration, context, $1); 647 CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); 648 649 last_driver = (LogDriver *) cfg_parse_plugin(configuration, p, &@1, NULL); 650 free($1); 651 if (!last_driver) 652 { 653 YYERROR; 654 } 655 $$ = last_driver; 656 } 657 ; 658 659 log_items 660 : log_item semicolons log_items { log_expr_node_append_tail($1, $3); $$ = $1; } 661 | { $$ = NULL; } 662 ; 663 664 log_item 665 : KW_SOURCE '(' string ')' { $$ = log_expr_node_new_source_reference($3, &@$); free($3); } 666 | KW_SOURCE '{' source_content '}' { $$ = log_expr_node_new_source(NULL, $3, &@$); } 667 | KW_FILTER '(' string ')' { $$ = log_expr_node_new_filter_reference($3, &@$); free($3); } 668 | KW_FILTER '{' filter_content '}' { $$ = log_expr_node_new_filter(NULL, $3, &@$); } 669 | KW_PARSER '(' string ')' { $$ = log_expr_node_new_parser_reference($3, &@$); free($3); } 670 | KW_PARSER '{' parser_content '}' { $$ = log_expr_node_new_parser(NULL, $3, &@$); } 671 | KW_REWRITE '(' string ')' { $$ = log_expr_node_new_rewrite_reference($3, &@$); free($3); } 672 | KW_REWRITE '{' rewrite_content '}' { $$ = log_expr_node_new_rewrite(NULL, $3, &@$); } 673 | KW_DESTINATION '(' string ')' { $$ = log_expr_node_new_destination_reference($3, &@$); free($3); } 674 | KW_DESTINATION '{' dest_content '}' { $$ = log_expr_node_new_destination(NULL, $3, &@$); } 675 | log_conditional { $$ = $1; } 676 | log_junction { $$ = $1; } 677 ; 678 679 log_junction 680 : KW_JUNCTION '{' log_forks '}' { $$ = log_expr_node_new_junction($3, &@$); } 681 ; 682 683 log_last_junction 684 685 /* this rule matches the last set of embedded log {} 686 * statements at the end of the log {} block. 687 * It is the final junction and was the only form of creating 688 * a processing tree before syslog-ng 3.4. 689 * 690 * We emulate if the user was writing junction {} explicitly. 691 */ 692 : log_forks { $$ = $1 ? log_expr_node_new_junction($1, &@1) : NULL; } 693 ; 694 695 696 log_forks 697 : log_fork semicolons log_forks { log_expr_node_append_tail($1, $3); $$ = $1; } 698 | { $$ = NULL; } 699 ; 700 701 log_fork 702 : KW_LOG '{' log_content '}' { $$ = $3; } 703 | KW_CHANNEL '{' log_content '}' { $$ = $3; } 704 ; 705 706 log_conditional 707 : log_if { $$ = $1; } 708 | log_if KW_ELSE '{' log_content '}' 709 { 710 log_expr_node_conditional_set_false_branch_of_the_last_if($1, $4); 711 $$ = $1; 712 } 713 ; 714 715 log_if 716 : KW_IF '(' filter_content ')' '{' log_content '}' 717 { 718 $$ = log_expr_node_new_conditional_with_filter($3, $6, &@$); 719 } 720 | KW_IF '{' log_content '}' 721 { 722 $$ = log_expr_node_new_conditional_with_block($3, &@$); 723 } 724 | log_if KW_ELIF '(' filter_content ')' '{' log_content '}' 725 { 726 LogExprNode *false_branch; 727 728 false_branch = log_expr_node_new_conditional_with_filter($4, $7, &@$); 729 log_expr_node_conditional_set_false_branch_of_the_last_if($1, false_branch); 730 $$ = $1; 731 } 732 | log_if KW_ELIF '{' log_content '}' 733 { 734 LogExprNode *false_branch; 735 736 false_branch = log_expr_node_new_conditional_with_block($4, &@$); 737 log_expr_node_conditional_set_false_branch_of_the_last_if($1, false_branch); 738 $$ = $1; 739 } 740 ; 741 742 log_content 743 : log_items log_last_junction log_flags { $$ = log_expr_node_new_log(log_expr_node_append_tail($1, $2), $3, &@$); } 744 ; 745 746 log_flags 747 : KW_FLAGS '(' log_flags_items ')' semicolons { $$ = $3; } 748 | { $$ = 0; } 749 ; 750 751 log_flags_items 752 : normalized_flag log_flags_items { $$ = log_expr_node_lookup_flag($1) | $2; free($1); } 753 | { $$ = 0; } 754 ; 755 756 757 template_content_inner 758 : string 759 { 760 GError *error = NULL; 761 762 CHECK_ERROR_GERROR(log_template_compile(last_template, $1, &error), @1, error, "Error compiling template"); 763 free($1); 764 } 765 | LL_IDENTIFIER '(' string ')' 766 { 767 GError *error = NULL; 768 769 CHECK_ERROR_GERROR(log_template_compile(last_template, $3, &error), @3, error, "Error compiling template"); 770 free($3); 771 772 CHECK_ERROR_GERROR(log_template_set_type_hint(last_template, $1, &error), @1, error, "Error setting the template type-hint \"%s\"", $1); 773 free($1); 774 } 775 ; 776 777 template_content 778 : { last_template = log_template_new(configuration, NULL); } template_content_inner { $$ = last_template; } 779 ; 780 781 template_content_list 782 : template_content template_content_list { $$ = g_list_prepend($2, $1); } 783 | { $$ = NULL; } 784 ; 785 786 787 788 string 789 : LL_IDENTIFIER 790 | LL_STRING 791 ; 792 793 yesno 794 : KW_YES { $$ = 1; } 795 | KW_NO { $$ = 0; } 796 | LL_NUMBER { $$ = $1; } 797 ; 798 799 dnsmode 800 : yesno { $$ = $1; } 801 | KW_PERSIST_ONLY { $$ = 2; } 802 ; 803 804 nonnegative_integer64 805 : LL_NUMBER 806 { 807 CHECK_ERROR(($1 >= 0), @1, "It cannot be negative"); 808 } 809 ; 810 811 nonnegative_integer 812 : nonnegative_integer64 813 { 814 CHECK_ERROR(($1 <= G_MAXINT32), @1, "Must be smaller than 2^31"); 815 } 816 ; 817 818 positive_integer64 819 : LL_NUMBER 820 { 821 CHECK_ERROR(($1 > 0), @1, "Must be positive"); 822 } 823 ; 824 825 positive_integer 826 : positive_integer64 827 { 828 CHECK_ERROR(($1 <= G_MAXINT32), @1, "Must be smaller than 2^31"); 829 } 830 ; 831 832 nonnegative_float 833 : LL_FLOAT 834 { 835 CHECK_ERROR(($1 >= 0), @1, "It cannot be negative"); 836 } 837 | nonnegative_integer 838 { 839 $$ = (double) $1; 840 } 841 ; 842 843 positive_float 844 : LL_FLOAT 845 { 846 CHECK_ERROR(($1 > 0), @1, "Must be positive"); 847 } 848 | positive_integer 849 { 850 $$ = (double) $1; 851 } 852 ; 853 854 string_or_number 855 : string { $$ = $1; } 856 | LL_NUMBER { $$ = strdup(lexer->token_text->str); } 857 | LL_FLOAT { $$ = strdup(lexer->token_text->str); } 858 ; 859 860 path 861 : string 862 { 863 struct stat buffer; 864 int ret = stat($1, &buffer); 865 CHECK_ERROR((ret == 0), @1, "File \"%s\" not found: %s", $1, strerror(errno)); 866 $$ = $1; 867 } 868 ; 869 870 path_check 871 : path { cfg_path_track_file(configuration, $1, "path_check"); } 872 ; 873 874 path_secret 875 : path { cfg_path_track_file(configuration, $1, "path_secret"); } 876 ; 877 878 path_no_check 879 : string { cfg_path_track_file(configuration, $1, "path_no_check"); } 880 ; 881 882 normalized_flag 883 : string { $$ = normalize_flag($1); free($1); } 884 ; 885 886 string_list 887 : string_list_build { $$ = $1; } 888 ; 889 890 string_list_build 891 : string string_list_build { $$ = g_list_prepend($2, g_strdup($1)); free($1); } 892 | { $$ = NULL; } 893 ; 894 895 semicolons 896 : ';' 897 | ';' semicolons 898 ; 899 900 severity_string 901 : string 902 { 903 /* return the numeric value of the "level" */ 904 int n = syslog_name_lookup_severity_by_name($1); 905 CHECK_ERROR((n != -1), @1, "Unknown priority level\"%s\"", $1); 906 free($1); 907 $$ = n; 908 } 909 ; 910 911 facility_string 912 : string 913 { 914 /* return the numeric value of facility */ 915 int n = syslog_name_lookup_facility_by_name($1); 916 CHECK_ERROR((n != -1), @1, "Unknown facility \"%s\"", $1); 917 free($1); 918 $$ = n; 919 } 920 | KW_SYSLOG { $$ = LOG_SYSLOG; } 921 ; 922 923 parser_opt 924 : KW_TEMPLATE '(' string ')' { 925 LogTemplate *template; 926 GError *error = NULL; 927 928 template = cfg_tree_check_inline_template(&configuration->tree, $3, &error); 929 CHECK_ERROR_GERROR(template != NULL, @3, error, "Error compiling template"); 930 log_parser_set_template(last_parser, template); 931 free($3); 932 } 933 ; 934 935 driver_option 936 : KW_PERSIST_NAME '(' string ')' { log_pipe_set_persist_name(&last_driver->super, $3); free($3); } 937 ; 938 939 inner_source 940 : LL_IDENTIFIER 941 { 942 Plugin *p; 943 gint context = LL_CONTEXT_INNER_SRC; 944 gpointer value; 945 946 p = cfg_find_plugin(configuration, context, $1); 947 CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); 948 949 value = cfg_parse_plugin(configuration, p, &@1, last_driver); 950 951 free($1); 952 if (!value) 953 { 954 YYERROR; 955 } 956 if (!log_driver_add_plugin(last_driver, (LogDriverPlugin *) value)) 957 { 958 log_driver_plugin_free(value); 959 CHECK_ERROR(TRUE, @1, "Error while registering the plugin %s in this destination", $1); 960 } 961 } 962 ; 963 964 /* All source drivers should incorporate this rule, implies driver_option */ 965 source_driver_option 966 : inner_source 967 | driver_option 968 ; 969 970 inner_dest 971 : LL_IDENTIFIER 972 { 973 Plugin *p; 974 gint context = LL_CONTEXT_INNER_DEST; 975 gpointer value; 976 977 p = cfg_find_plugin(configuration, context, $1); 978 CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); 979 980 value = cfg_parse_plugin(configuration, p, &@1, last_driver); 981 982 free($1); 983 if (!value) 984 { 985 YYERROR; 986 } 987 if (!log_driver_add_plugin(last_driver, (LogDriverPlugin *) value)) 988 { 989 log_driver_plugin_free(value); 990 CHECK_ERROR(TRUE, @1, "Error while registering the plugin %s in this destination", $1); 991 } 992 } 993 ; 994 995 /* implies driver_option */ 996 dest_driver_option 997 /* NOTE: plugins need to set "last_driver" in order to incorporate this rule in their grammar */ 998 999 : KW_LOG_FIFO_SIZE '(' positive_integer ')' { ((LogDestDriver *) last_driver)->log_fifo_size = $3; } 1000 | KW_THROTTLE '(' nonnegative_integer ')' { ((LogDestDriver *) last_driver)->throttle = $3; } 1001 | inner_dest 1002 | driver_option 1003 ; 1004 1005 threaded_dest_driver_batch_option 1006 : KW_BATCH_LINES '(' nonnegative_integer ')' { log_threaded_dest_driver_set_batch_lines(last_driver, $3); } 1007 | KW_BATCH_TIMEOUT '(' positive_integer ')' { log_threaded_dest_driver_set_batch_timeout(last_driver, $3); } 1008 ; 1009 1010 threaded_dest_driver_workers_option 1011 : KW_WORKERS '(' positive_integer ')' { log_threaded_dest_driver_set_num_workers(last_driver, $3); } 1012 ; 1013 1014 /* implies dest_driver_option */ 1015 threaded_dest_driver_general_option 1016 : KW_RETRIES '(' positive_integer ')' 1017 { 1018 log_threaded_dest_driver_set_max_retries_on_error(last_driver, $3); 1019 } 1020 | KW_TIME_REOPEN '(' positive_integer ')' { log_threaded_dest_driver_set_time_reopen(last_driver, $3); } 1021 | dest_driver_option 1022 ; 1023 1024 /* implies source_driver_option and source_option */ 1025 threaded_source_driver_option 1026 : KW_FORMAT '(' string ')' { log_threaded_source_driver_get_parse_options(last_driver)->format = g_strdup($3); free($3); } 1027 | KW_FLAGS '(' threaded_source_driver_option_flags ')' 1028 | { last_msg_format_options = log_threaded_source_driver_get_parse_options(last_driver); } msg_format_option 1029 | { last_source_options = log_threaded_source_driver_get_source_options(last_driver); } source_option 1030 | source_driver_option 1031 ; 1032 1033 threaded_fetcher_driver_option 1034 : KW_FETCH_NO_DATA_DELAY '(' nonnegative_float ')' { log_threaded_fetcher_driver_set_fetch_no_data_delay(last_driver, $3); } 1035 | KW_TIME_REOPEN '(' positive_integer ')' { log_threaded_fetcher_driver_set_time_reopen(last_driver, $3); } 1036 ; 1037 1038 threaded_source_driver_option_flags 1039 : string threaded_source_driver_option_flags 1040 { 1041 CHECK_ERROR(msg_format_options_process_flag(log_threaded_source_driver_get_parse_options(last_driver), $1), @1, "Unknown flag \"%s\"", $1); 1042 free($1); 1043 } 1044 | 1045 ; 1046 1047 /* LogSource related options */ 1048 source_option 1049 /* NOTE: plugins need to set "last_source_options" in order to incorporate this rule in their grammar */ 1050 : KW_LOG_IW_SIZE '(' positive_integer ')' { last_source_options->init_window_size = $3; } 1051 | KW_CHAIN_HOSTNAMES '(' yesno ')' { last_source_options->chain_hostnames = $3; } 1052 | KW_KEEP_HOSTNAME '(' yesno ')' { last_source_options->keep_hostname = $3; } 1053 | KW_PROGRAM_OVERRIDE '(' string ')' { last_source_options->program_override = g_strdup($3); free($3); } 1054 | KW_HOST_OVERRIDE '(' string ')' { last_source_options->host_override = g_strdup($3); free($3); } 1055 | KW_LOG_PREFIX '(' string ')' { gchar *p = strrchr($3, ':'); if (p) *p = 0; last_source_options->program_override = g_strdup($3); free($3); } 1056 | KW_KEEP_TIMESTAMP '(' yesno ')' { last_source_options->keep_timestamp = $3; } 1057 | KW_READ_OLD_RECORDS '(' yesno ')' { last_source_options->read_old_records = $3; } 1058 | KW_USE_SYSLOGNG_PID '(' yesno ')' { last_source_options->use_syslogng_pid = $3; } 1059 | KW_TAGS '(' string_list ')' { log_source_options_set_tags(last_source_options, $3); } 1060 | { last_host_resolve_options = &last_source_options->host_resolve_options; } host_resolve_option 1061 ; 1062 1063 /* LogReader related options, implies source_option */ 1064 source_reader_option 1065 /* NOTE: plugins need to set "last_reader_options" in order to incorporate this rule in their grammar */ 1066 1067 : KW_CHECK_HOSTNAME '(' yesno ')' { last_reader_options->check_hostname = $3; } 1068 | KW_FLAGS '(' source_reader_option_flags ')' 1069 | KW_LOG_FETCH_LIMIT '(' positive_integer ')' { last_reader_options->fetch_limit = $3; } 1070 | KW_FORMAT '(' string ')' { last_reader_options->parse_options.format = g_strdup($3); free($3); } 1071 | { last_source_options = &last_reader_options->super; } source_option 1072 | { last_proto_server_options = &last_reader_options->proto_options.super; } source_proto_option 1073 | { last_msg_format_options = &last_reader_options->parse_options; } msg_format_option 1074 ; 1075 1076 source_reader_option_flags 1077 : string source_reader_option_flags { CHECK_ERROR(log_reader_options_process_flag(last_reader_options, $1), @1, "Unknown flag \"%s\"", $1); free($1); } 1078 | KW_CHECK_HOSTNAME source_reader_option_flags { log_reader_options_process_flag(last_reader_options, "check-hostname"); } 1079 | 1080 ; 1081 1082 /* LogProtoSource related options */ 1083 source_proto_option 1084 : KW_ENCODING '(' string ')' 1085 { 1086 CHECK_ERROR(log_proto_server_options_set_encoding(last_proto_server_options, $3), 1087 @3, 1088 "unknown encoding \"%s\"", $3); 1089 free($3); 1090 } 1091 | KW_LOG_MSG_SIZE '(' positive_integer ')' { last_proto_server_options->max_msg_size = $3; } 1092 | KW_TRIM_LARGE_MESSAGES '(' yesno ')' { last_proto_server_options->trim_large_messages = $3; } 1093 ; 1094 1095 host_resolve_option 1096 : KW_USE_FQDN '(' yesno ')' { last_host_resolve_options->use_fqdn = $3; } 1097 | KW_USE_DNS '(' dnsmode ')' { last_host_resolve_options->use_dns = $3; } 1098 | KW_DNS_CACHE '(' yesno ')' { last_host_resolve_options->use_dns_cache = $3; } 1099 | KW_NORMALIZE_HOSTNAMES '(' yesno ')' { last_host_resolve_options->normalize_hostnames = $3; } 1100 ; 1101 1102 msg_format_option 1103 : KW_TIME_ZONE '(' string ')' { last_msg_format_options->recv_time_zone = g_strdup($3); free($3); } 1104 | KW_DEFAULT_SEVERITY '(' severity_string ')' 1105 { 1106 if (last_msg_format_options->default_pri == 0xFFFF) 1107 last_msg_format_options->default_pri = LOG_USER; 1108 last_msg_format_options->default_pri = (last_msg_format_options->default_pri & ~LOG_PRIMASK) | $3; 1109 } 1110 | KW_DEFAULT_FACILITY '(' facility_string ')' 1111 { 1112 if (last_msg_format_options->default_pri == 0xFFFF) 1113 last_msg_format_options->default_pri = LOG_NOTICE; 1114 last_msg_format_options->default_pri = (last_msg_format_options->default_pri & LOG_PRIMASK) | $3; 1115 } 1116 ; 1117 1118 dest_writer_options 1119 : dest_writer_option dest_writer_options 1120 | 1121 ; 1122 1123 dest_writer_option 1124 /* NOTE: plugins need to set "last_writer_options" in order to incorporate this rule in their grammar */ 1125 1126 : KW_FLAGS '(' dest_writer_options_flags ')' { last_writer_options->options = $3; } 1127 | KW_FLUSH_LINES '(' nonnegative_integer ')' { last_writer_options->flush_lines = $3; } 1128 | KW_FLUSH_TIMEOUT '(' positive_integer ')' { } 1129 | KW_SUPPRESS '(' nonnegative_integer ')' { last_writer_options->suppress = $3; } 1130 | KW_TEMPLATE '(' string ')' { 1131 GError *error = NULL; 1132 1133 last_writer_options->template = cfg_tree_check_inline_template(&configuration->tree, $3, &error); 1134 CHECK_ERROR_GERROR(last_writer_options->template != NULL, @3, error, "Error compiling template"); 1135 free($3); 1136 } 1137 | KW_TEMPLATE_ESCAPE '(' yesno ')' { log_writer_options_set_template_escape(last_writer_options, $3); } 1138 | KW_PAD_SIZE '(' nonnegative_integer ')' { last_writer_options->padding = $3; } 1139 | KW_TRUNCATE_SIZE '(' nonnegative_integer ')' { last_writer_options->truncate_size = $3; } 1140 | KW_MARK_FREQ '(' nonnegative_integer ')' { last_writer_options->mark_freq = $3; } 1141 | KW_MARK_MODE '(' KW_INTERNAL ')' { log_writer_options_set_mark_mode(last_writer_options, "internal"); } 1142 | KW_MARK_MODE '(' string ')' 1143 { 1144 CHECK_ERROR(cfg_lookup_mark_mode($3) != -1, @3, "illegal mark mode \"%s\"", $3); 1145 log_writer_options_set_mark_mode(last_writer_options, $3); 1146 free($3); 1147 } 1148 | KW_TIME_REOPEN '(' positive_integer ')' { last_writer_options->time_reopen = $3; } 1149 | { last_template_options = &last_writer_options->template_options; } template_option 1150 ; 1151 1152 dest_writer_options_flags 1153 : normalized_flag dest_writer_options_flags { $$ = log_writer_options_lookup_flag($1) | $2; free($1); } 1154 | { $$ = 0; } 1155 ; 1156 1157 file_perm_option 1158 : KW_OWNER '(' string_or_number ')' { file_perm_options_set_file_uid(last_file_perm_options, $3); free($3); } 1159 | KW_OWNER '(' ')' { file_perm_options_dont_change_file_uid(last_file_perm_options); } 1160 | KW_GROUP '(' string_or_number ')' { file_perm_options_set_file_gid(last_file_perm_options, $3); free($3); } 1161 | KW_GROUP '(' ')' { file_perm_options_dont_change_file_gid(last_file_perm_options); } 1162 | KW_PERM '(' LL_NUMBER ')' { file_perm_options_set_file_perm(last_file_perm_options, $3); } 1163 | KW_PERM '(' ')' { file_perm_options_dont_change_file_perm(last_file_perm_options); } 1164 | KW_DIR_OWNER '(' string_or_number ')' { file_perm_options_set_dir_uid(last_file_perm_options, $3); free($3); } 1165 | KW_DIR_OWNER '(' ')' { file_perm_options_dont_change_dir_uid(last_file_perm_options); } 1166 | KW_DIR_GROUP '(' string_or_number ')' { file_perm_options_set_dir_gid(last_file_perm_options, $3); free($3); } 1167 | KW_DIR_GROUP '(' ')' { file_perm_options_dont_change_dir_gid(last_file_perm_options); } 1168 | KW_DIR_PERM '(' LL_NUMBER ')' { file_perm_options_set_dir_perm(last_file_perm_options, $3); } 1169 | KW_DIR_PERM '(' ')' { file_perm_options_dont_change_dir_perm(last_file_perm_options); } 1170 ; 1171 1172 template_option 1173 : KW_TS_FORMAT '(' string ')' { last_template_options->ts_format = cfg_ts_format_value($3); free($3); } 1174 | KW_FRAC_DIGITS '(' nonnegative_integer ')' { last_template_options->frac_digits = $3; } 1175 | KW_TIME_ZONE '(' string ')' { last_template_options->time_zone[LTZ_SEND] = g_strdup($3); free($3); } 1176 | KW_SEND_TIME_ZONE '(' string ')' { last_template_options->time_zone[LTZ_SEND] = g_strdup($3); free($3); } 1177 | KW_LOCAL_TIME_ZONE '(' string ')' { last_template_options->time_zone[LTZ_LOCAL] = g_strdup($3); free($3); } 1178 | KW_ON_ERROR '(' string ')' 1179 { 1180 gint on_error; 1181 1182 CHECK_ERROR(log_template_on_error_parse($3, &on_error), @3, "Invalid on-error() setting \"%s\"", $3); 1183 free($3); 1184 1185 log_template_options_set_on_error(last_template_options, on_error); 1186 } 1187 ; 1188 1189 matcher_option 1190 : KW_TYPE '(' string ')' { CHECK_ERROR(log_matcher_options_set_type(last_matcher_options, $3), @3, "unknown matcher type \"%s\"", $3); free($3); } 1191 | KW_FLAGS '(' matcher_flags ')' 1192 ; 1193 1194 matcher_flags 1195 : string matcher_flags { CHECK_ERROR(log_matcher_options_process_flag(last_matcher_options, $1), @1, "unknown matcher flag \"%s\"", $1); free($1); } 1196 | 1197 ; 1198 1199 value_pair_option 1200 : KW_VALUE_PAIRS 1201 { 1202 last_value_pairs = value_pairs_new(); 1203 } 1204 '(' vp_options ')' 1205 { $$ = last_value_pairs; } 1206 ; 1207 1208 vp_options 1209 : vp_option vp_options 1210 | 1211 ; 1212 1213 vp_option 1214 : KW_PAIR '(' string ':' template_content ')' 1215 { 1216 value_pairs_add_pair(last_value_pairs, $3, $5); 1217 free($3); 1218 } 1219 | KW_PAIR '(' string template_content ')' 1220 { 1221 value_pairs_add_pair(last_value_pairs, $3, $4); 1222 free($3); 1223 } 1224 | KW_KEY '(' string KW_REKEY '(' 1225 { 1226 last_vp_transset = value_pairs_transform_set_new($3); 1227 value_pairs_add_glob_pattern(last_value_pairs, $3, TRUE); 1228 free($3); 1229 } 1230 vp_rekey_options ')' { value_pairs_add_transforms(last_value_pairs, last_vp_transset); } ')' 1231 | KW_KEY '(' string_list ')' { value_pairs_add_glob_patterns(last_value_pairs, $3, TRUE); } 1232 | KW_REKEY '(' string 1233 { 1234 last_vp_transset = value_pairs_transform_set_new($3); 1235 free($3); 1236 } 1237 vp_rekey_options ')' { value_pairs_add_transforms(last_value_pairs, last_vp_transset); } 1238 | KW_EXCLUDE '(' string_list ')' { value_pairs_add_glob_patterns(last_value_pairs, $3, FALSE); } 1239 | KW_SCOPE '(' vp_scope_list ')' 1240 ; 1241 1242 vp_scope_list 1243 : string vp_scope_list { value_pairs_add_scope(last_value_pairs, $1); free($1); } 1244 | 1245 ; 1246 1247 vp_rekey_options 1248 : vp_rekey_option vp_rekey_options 1249 | 1250 ; 1251 1252 vp_rekey_option 1253 : KW_SHIFT '(' positive_integer ')' { value_pairs_transform_set_add_func(last_vp_transset, value_pairs_new_transform_shift($3)); } 1254 | KW_SHIFT_LEVELS '(' positive_integer ')' { value_pairs_transform_set_add_func(last_vp_transset, value_pairs_new_transform_shift_levels($3)); } 1255 | KW_ADD_PREFIX '(' string ')' { value_pairs_transform_set_add_func(last_vp_transset, value_pairs_new_transform_add_prefix($3)); free($3); } 1256 | 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); } 1257 ; 1258 1259 rewrite_expr_opt 1260 : KW_VALUE '(' string ')' 1261 { 1262 const gchar *p = $3; 1263 if (p[0] == '$') 1264 { 1265 msg_warning("Value references in rewrite rules should not use the '$' prefix, those are only needed in templates", 1266 evt_tag_str("value", $3), 1267 cfg_lexer_format_location_tag(lexer, &@3)); 1268 p++; 1269 } 1270 last_rewrite->value_handle = log_msg_get_value_handle(p); 1271 CHECK_ERROR(!log_msg_is_handle_macro(last_rewrite->value_handle), @3, "%s is read-only, it cannot be changed in rewrite rules", p); 1272 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); 1273 free($3); 1274 } 1275 | rewrite_condition_opt 1276 ; 1277 1278 rewrite_condition_opt 1279 : KW_CONDITION '(' 1280 { 1281 FilterExprNode *filter_expr; 1282 1283 CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&filter_expr_parser, lexer, (gpointer *) &filter_expr, NULL), @1); 1284 log_rewrite_set_condition(last_rewrite, filter_expr); 1285 } ')' 1286 ; 1287 1288 1289 1290 %% 1291