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