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