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