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