1/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> 2 3 This program is free software: you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation, either version 3 of the License, or 6 (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, see <https://www.gnu.org/licenses/>. 15 */ 16 17%%{ 18 machine zone_scanner; 19 20 # Comeback function to calling state machine. 21 action _ret { 22 fhold; fret; 23 } 24 25 # BEGIN - Blank space processing 26 action _newline { 27 s->line_counter++; 28 } 29 30 action _check_multiline_begin { 31 if (s->multiline == true) { 32 ERR(ZS_LEFT_PARENTHESIS); 33 fhold; fgoto err_line; 34 } 35 s->multiline = true; 36 } 37 action _check_multiline_end { 38 if (s->multiline == false) { 39 ERR(ZS_RIGHT_PARENTHESIS); 40 fhold; fgoto err_line; 41 } 42 s->multiline = false; 43 } 44 45 action _comment_init { 46 s->buffer_length = 0; 47 } 48 action _comment { 49 if (s->buffer_length < sizeof(s->buffer) - 1) { 50 s->buffer[s->buffer_length++] = fc; 51 } 52 } 53 action _comment_exit { 54 s->buffer[s->buffer_length++] = 0; 55 56 // Execute the comment callback. 57 if (s->process.automatic && s->process.comment != NULL) { 58 s->process.comment(s); 59 60 // Stop if required from the callback. 61 if (s->state == ZS_STATE_STOP) { 62 fbreak; 63 } 64 } 65 } 66 67 action _rest_init { 68 s->buffer[0] = 0; 69 s->buffer_length = 0; 70 } 71 action _rest_error { 72 WARN(ZS_BAD_REST); 73 fhold; fgoto err_line; 74 } 75 76 newline = '\n' $_newline; 77 comment = (';' . (^newline)* $_comment) >_comment_init %_comment_exit; 78 79 # White space separation. With respect to parentheses and included comments. 80 sep = ( [ \t] # Blank characters. 81 | (comment? . newline) when { s->multiline } # Comment in multiline. 82 | '(' $_check_multiline_begin # Start of multiline. 83 | ')' $_check_multiline_end # End of multiline. 84 )+; # Apply more times. 85 86 rest = (sep? :> comment?) >_rest_init $!_rest_error; # Comments. 87 88 # Artificial machines which are used for next state transition only! 89 all_wchar = [ \t\n;()]; 90 end_wchar = [\n;] when { !s->multiline }; # For noncontinuous ending tokens. 91 # END 92 93 # BEGIN - Error line processing 94 action _err_line_init { 95 s->buffer_length = 0; 96 } 97 action _err_line { 98 if (fc == '\r') { 99 ERR(ZS_DOS_NEWLINE); 100 } 101 102 if (s->buffer_length < sizeof(s->buffer) - 1) { 103 s->buffer[s->buffer_length++] = fc; 104 } 105 } 106 action _err_line_exit { 107 // Terminate the error context string. 108 s->buffer[s->buffer_length++] = 0; 109 110 // Error counter incrementation. 111 s->error.counter++; 112 113 // Initialize the fcall stack. 114 top = 0; 115 116 // Reset per-record contexts. 117 s->long_string = false; 118 s->comma_list = false; 119 120 s->state = ZS_STATE_ERROR; 121 122 // Execute the error callback. 123 if (s->process.automatic) { 124 fhold; 125 if (s->process.error != NULL) { 126 s->process.error(s); 127 128 // Stop if required from the callback. 129 if (s->state == ZS_STATE_STOP) { 130 fbreak; 131 } 132 } 133 134 // Stop the scanner if fatal error. 135 if (s->error.fatal) { 136 fbreak; 137 } 138 fgoto err_rest; 139 } else { 140 // Return if external processing. 141 fhold; fnext err_rest; fbreak; 142 } 143 } 144 145 # Consume rest lines of defective multiline record. 146 err_rest := ( (any - newline - ')') 147 | newline when { s->multiline } 148 | ')' when { s->multiline } $_check_multiline_end 149 )* %{ fhold; fcall main; } <: newline; 150 151 # Fill rest of the line to buffer and skip to main loop. 152 err_line := (^newline $_err_line)* >_err_line_init 153 %_err_line_exit . newline; 154 # END 155 156 # BEGIN - Domain name labels processing 157 action _label_init { 158 s->item_length = 0; 159 s->item_length_position = s->dname_tmp_length++; 160 } 161 action _label_char { 162 // Check for maximum dname label length. 163 if (s->item_length < ZS_MAX_LABEL_LENGTH) { 164 (s->dname)[s->dname_tmp_length++] = fc; 165 s->item_length++; 166 } else { 167 WARN(ZS_LABEL_OVERFLOW); 168 fhold; fgoto err_line; 169 } 170 } 171 action _label_exit { 172 // Check for maximum dname length overflow after each label. 173 // (at least the next label length must follow). 174 if (s->dname_tmp_length < ZS_MAX_DNAME_LENGTH) { 175 (s->dname)[s->item_length_position] = 176 (uint8_t)(s->item_length); 177 } else { 178 WARN(ZS_DNAME_OVERFLOW); 179 fhold; fgoto err_line; 180 } 181 } 182 183 action _label_dec_init { 184 if (s->item_length < ZS_MAX_LABEL_LENGTH) { 185 (s->dname)[s->dname_tmp_length] = 0; 186 s->item_length++; 187 } else { 188 WARN(ZS_LABEL_OVERFLOW); 189 fhold; fgoto err_line; 190 } 191 } 192 action _label_dec { 193 (s->dname)[s->dname_tmp_length] *= 10; 194 (s->dname)[s->dname_tmp_length] += digit_to_num[(uint8_t)fc]; 195 } 196 action _label_dec_exit { 197 s->dname_tmp_length++; 198 } 199 action _label_dec_error { 200 WARN(ZS_BAD_NUMBER); 201 fhold; fgoto err_line; 202 } 203 204 label_char = 205 ( (alnum | [*\-_/]) $_label_char # One common char. 206 | ('\\' . ^digit) @_label_char # One "\x" char. 207 | ('\\' %_label_dec_init # Initial "\" char. 208 . digit {3} $_label_dec %_label_dec_exit # "DDD" rest. 209 $!_label_dec_error 210 ) 211 ); 212 213 label = label_char+ >_label_init %_label_exit; 214 labels = (label . '.')* . label; 215 # END 216 217 # BEGIN - Domain name processing. 218 action _absolute_dname_exit { 219 // Enough room for the terminal label is guaranteed (_label_exit). 220 (s->dname)[s->dname_tmp_length++] = 0; 221 } 222 action _relative_dname_exit { 223 // Check for (relative + origin) dname length overflow. 224 if (s->dname_tmp_length + s->zone_origin_length <= ZS_MAX_DNAME_LENGTH) { 225 memcpy(s->dname + s->dname_tmp_length, 226 s->zone_origin, 227 s->zone_origin_length); 228 229 s->dname_tmp_length += s->zone_origin_length; 230 } else { 231 WARN(ZS_DNAME_OVERFLOW); 232 fhold; fgoto err_line; 233 } 234 } 235 action _origin_dname_exit { 236 // Copy already verified zone origin. 237 memcpy(s->dname, 238 s->zone_origin, 239 s->zone_origin_length); 240 241 s->dname_tmp_length = s->zone_origin_length; 242 } 243 244 action _dname_init { 245 s->item_length_position = 0; 246 s->dname_tmp_length = 0; 247 } 248 action _dname_error { 249 WARN(ZS_BAD_DNAME_CHAR); 250 fhold; fgoto err_line; 251 } 252 253 relative_dname = (labels ) >_dname_init %_relative_dname_exit; 254 absolute_dname = (labels? . '.') >_dname_init %_absolute_dname_exit; 255 256 dname_ := ( relative_dname 257 | absolute_dname 258 | '@' %_origin_dname_exit 259 ) $!_dname_error %_ret . all_wchar; 260 dname = (alnum | [\-_/\\] | [*.@]) ${ fhold; fcall dname_; }; 261 # END 262 263 # BEGIN - Common r_data item processing 264 action _item_length_init { 265 if (rdata_tail <= rdata_stop) { 266 s->item_length_location = rdata_tail++; 267 } else { 268 WARN(ZS_RDATA_OVERFLOW); 269 fhold; fgoto err_line; 270 } 271 } 272 action _item_length_exit { 273 s->item_length = rdata_tail - s->item_length_location - 1; 274 if (s->comma_list && s->item_length == 0) { 275 WARN(ZS_EMPTY_LIST_ITEM); 276 fhold; fgoto err_line; 277 } 278 if (s->item_length <= MAX_ITEM_LENGTH) { 279 *(s->item_length_location) = (uint8_t)(s->item_length); 280 } else { 281 WARN(ZS_ITEM_OVERFLOW); 282 fhold; fgoto err_line; 283 } 284 } 285 action _item_length2_init { 286 if (rdata_tail < rdata_stop) { 287 s->item_length2_location = rdata_tail; 288 rdata_tail += 2; 289 } else { 290 WARN(ZS_RDATA_OVERFLOW); 291 fhold; fgoto err_line; 292 } 293 } 294 action _item_length2_exit { 295 s->item_length = rdata_tail - s->item_length2_location - 2; 296 297 if (s->item_length <= MAX_ITEM_LENGTH2) { 298 uint16_t val = htons((uint16_t)(s->item_length)); 299 memcpy(s->item_length2_location, &val, 2); 300 } else { 301 WARN(ZS_ITEM_OVERFLOW); 302 fhold; fgoto err_line; 303 } 304 } 305 # END 306 307 # BEGIN - Owner processing 308 action _r_owner_init { 309 s->dname = s->r_owner; 310 s->r_owner_length = 0; 311 } 312 action _r_owner_exit { 313 s->r_owner_length = s->dname_tmp_length; 314 } 315 action _r_owner_empty_exit { 316 if (s->r_owner_length == 0) { 317 WARN(ZS_BAD_PREVIOUS_OWNER); 318 fhold; fgoto err_line; 319 } 320 } 321 action _r_owner_error { 322 s->r_owner_length = 0; 323 WARN(ZS_BAD_OWNER); 324 fhold; fgoto err_line; 325 } 326 327 r_owner = ( dname >_r_owner_init %_r_owner_exit 328 | zlen %_r_owner_empty_exit # Empty owner - use the previous one. 329 ) $!_r_owner_error; 330 # END 331 332 # BEGIN - domain name in record data processing 333 action _r_dname_init { 334 s->dname = rdata_tail; 335 } 336 action _r_dname_exit { 337 rdata_tail += s->dname_tmp_length; 338 } 339 340 r_dname = dname >_r_dname_init %_r_dname_exit; 341 # END 342 343 # BEGIN - Number processing 344 action _number_digit { 345 // Overflow check: 10*(s->number64) + fc - '0' <= UINT64_MAX 346 if ((s->number64 < (UINT64_MAX / 10)) || // Dominant fast check. 347 ((s->number64 == (UINT64_MAX / 10)) && // Marginal case. 348 ((uint8_t)fc <= (UINT64_MAX % 10) + '0') 349 ) 350 ) { 351 s->number64 *= 10; 352 s->number64 += digit_to_num[(uint8_t)fc]; 353 } else { 354 WARN(ZS_NUMBER64_OVERFLOW); 355 fhold; fgoto err_line; 356 } 357 } 358 359 number_digit = [0-9] $_number_digit; 360 361 action _number_init { 362 s->number64 = 0; 363 } 364 action _number_error { 365 WARN(ZS_BAD_NUMBER); 366 fhold; fgoto err_line; 367 } 368 369 # General integer number that cover all necessary integer ranges. 370 number = number_digit+ >_number_init; 371 372 action _float_init { 373 s->decimal_counter = 0; 374 } 375 action _decimal_init { 376 s->number64_tmp = s->number64; 377 } 378 action _decimal_digit { 379 s->decimal_counter++; 380 } 381 382 action _float_exit { 383 if (s->decimal_counter == 0 && s->number64 < UINT32_MAX) { 384 s->number64 *= pow(10, s->decimals); 385 } else if (s->decimal_counter <= s->decimals && 386 s->number64_tmp < UINT32_MAX) { 387 s->number64 *= pow(10, s->decimals - s->decimal_counter); 388 s->number64 += s->number64_tmp * pow(10, s->decimals); 389 } else { 390 WARN(ZS_FLOAT_OVERFLOW); 391 fhold; fgoto err_line; 392 } 393 } 394 395 # Next float can't be used directly (doesn't contain decimals init)! 396 float = (number . ('.' . number? >_decimal_init $_decimal_digit)?) 397 >_float_init %_float_exit; 398 399 action _float2_init { 400 s->decimals = 2; 401 } 402 action _float3_init { 403 s->decimals = 3; 404 } 405 406 # Float number (in hundredths)with 2 possible decimal digits. 407 float2 = float >_float2_init; 408 # Float number (in thousandths) with 3 possible decimal digits. 409 float3 = float >_float3_init; 410 411 action _num8_write { 412 if (s->number64 <= UINT8_MAX) { 413 *rdata_tail = (uint8_t)(s->number64); 414 rdata_tail += 1; 415 } else { 416 WARN(ZS_NUMBER8_OVERFLOW); 417 fhold; fgoto err_line; 418 } 419 } 420 action _num16_write { 421 if (s->number64 <= UINT16_MAX) { 422 uint16_t num16 = htons((uint16_t)s->number64); 423 memcpy(rdata_tail, &num16, 2); 424 rdata_tail += 2; 425 } else { 426 WARN(ZS_NUMBER16_OVERFLOW); 427 fhold; fgoto err_line; 428 } 429 } 430 action _num32_write { 431 if (s->number64 <= UINT32_MAX) { 432 uint32_t num32 = htonl((uint32_t)s->number64); 433 memcpy(rdata_tail, &num32, 4); 434 rdata_tail += 4; 435 } else { 436 WARN(ZS_NUMBER32_OVERFLOW); 437 fhold; fgoto err_line; 438 } 439 } 440 441 action _type_number_exit { 442 if (s->number64 <= UINT16_MAX) { 443 s->r_type = (uint16_t)(s->number64); 444 } else { 445 WARN(ZS_NUMBER16_OVERFLOW); 446 fhold; fgoto err_line; 447 } 448 } 449 450 action _length_number_exit { 451 if (s->number64 <= UINT16_MAX) { 452 s->r_data_length = (uint16_t)(s->number64); 453 } else { 454 WARN(ZS_NUMBER16_OVERFLOW); 455 fhold; fgoto err_line; 456 } 457 } 458 num8 = number %_num8_write $!_number_error; 459 num16 = number %_num16_write $!_number_error; 460 num32 = number %_num32_write $!_number_error; 461 462 type_number = number %_type_number_exit $!_number_error; 463 length_number = number %_length_number_exit $!_number_error; 464 # END 465 466 # BEGIN - Time processing 467 action _time_unit_error { 468 WARN(ZS_BAD_TIME_UNIT); 469 fhold; fgoto err_line; 470 } 471 472 time_unit = 473 ( 's'i 474 | 'm'i ${ if (s->number64 <= (UINT32_MAX / 60)) { 475 s->number64 *= 60; 476 } else { 477 WARN(ZS_NUMBER32_OVERFLOW); 478 fhold; fgoto err_line; 479 } 480 } 481 | 'h'i ${ if (s->number64 <= (UINT32_MAX / 3600)) { 482 s->number64 *= 3600; 483 } else { 484 WARN(ZS_NUMBER32_OVERFLOW); 485 fhold; fgoto err_line; 486 } 487 } 488 | 'd'i ${ if (s->number64 <= (UINT32_MAX / 86400)) { 489 s->number64 *= 86400; 490 } else { 491 WARN(ZS_NUMBER32_OVERFLOW); 492 fhold; fgoto err_line; 493 } 494 } 495 | 'w'i ${ if (s->number64 <= (UINT32_MAX / 604800)) { 496 s->number64 *= 604800; 497 } else { 498 WARN(ZS_NUMBER32_OVERFLOW); 499 fhold; fgoto err_line; 500 } 501 } 502 ) $!_time_unit_error; 503 504 505 action _time_block_init { 506 s->number64_tmp = s->number64; 507 } 508 action _time_block_exit { 509 if (s->number64 + s->number64_tmp < UINT32_MAX) { 510 s->number64 += s->number64_tmp; 511 } else { 512 WARN(ZS_NUMBER32_OVERFLOW); 513 fhold; fgoto err_line; 514 } 515 } 516 517 time_block = (number . time_unit) >_time_block_init %_time_block_exit; 518 519 # Time is either a number or a sequence of time blocks (1w1h1m). 520 time = (number . (time_unit . (time_block)*)?) $!_number_error; 521 522 time32 = time %_num32_write; 523 # END 524 525 # BEGIN - Timestamp processing 526 action _timestamp_init { 527 s->buffer_length = 0; 528 } 529 action _timestamp { 530 if (s->buffer_length < sizeof(s->buffer) - 1) { 531 s->buffer[s->buffer_length++] = fc; 532 } else { 533 WARN(ZS_RDATA_OVERFLOW); 534 fhold; fgoto err_line; 535 } 536 } 537 action _timestamp_exit { 538 s->buffer[s->buffer_length] = 0; 539 540 if (s->buffer_length == 14) { // Date; 14 = len("YYYYMMDDHHmmSS"). 541 uint32_t timestamp; 542 int ret = date_to_timestamp(s->buffer, ×tamp); 543 544 if (ret == ZS_OK) { 545 *((uint32_t *)rdata_tail) = htonl(timestamp); 546 rdata_tail += 4; 547 } else { 548 WARN(ret); 549 fhold; fgoto err_line; 550 } 551 } else if (s->buffer_length <= 10) { // Timestamp format. 552 char *end; 553 554 s->number64 = strtoull((char *)(s->buffer), &end, 10); 555 556 if (end == (char *)(s->buffer) || *end != '\0') { 557 WARN(ZS_BAD_TIMESTAMP); 558 fhold; fgoto err_line; 559 } 560 561 if (s->number64 <= UINT32_MAX) { 562 *((uint32_t *)rdata_tail) = htonl((uint32_t)s->number64); 563 rdata_tail += 4; 564 } else { 565 WARN(ZS_NUMBER32_OVERFLOW); 566 fhold; fgoto err_line; 567 } 568 } else { 569 WARN(ZS_BAD_TIMESTAMP_LENGTH); 570 fhold; fgoto err_line; 571 } 572 } 573 action _timestamp_error { 574 WARN(ZS_BAD_TIMESTAMP_CHAR); 575 fhold; fgoto err_line; 576 } 577 578 timestamp = digit+ >_timestamp_init $_timestamp 579 %_timestamp_exit $!_timestamp_error; 580 # END 581 582 # BEGIN - Text processing 583 action _text_char { 584 if (rdata_tail <= rdata_stop) { 585 // Split long string. 586 if (s->long_string && 587 rdata_tail - s->item_length_location == 1 + MAX_ITEM_LENGTH) { 588 // _item_length_exit equivalent. 589 *(s->item_length_location) = MAX_ITEM_LENGTH; 590 // _item_length_init equivalent. 591 s->item_length_location = rdata_tail++; 592 593 if (rdata_tail > rdata_stop) { 594 WARN(ZS_TEXT_OVERFLOW); 595 fhold; fgoto err_line; 596 } 597 } 598 599 *(rdata_tail++) = fc; 600 } else { 601 WARN(ZS_TEXT_OVERFLOW); 602 fhold; fgoto err_line; 603 } 604 } 605 action _text_char_error { 606 WARN(ZS_BAD_TEXT_CHAR); 607 fhold; fgoto err_line; 608 } 609 action _text_error { 610 WARN(ZS_BAD_TEXT); 611 fhold; fgoto err_line; 612 } 613 614 action _text_dec_init { 615 if (rdata_tail <= rdata_stop) { 616 // Split long string. 617 if (s->long_string && 618 rdata_tail - s->item_length_location == 1 + MAX_ITEM_LENGTH) { 619 // _item_length_exit equivalent. 620 *(s->item_length_location) = MAX_ITEM_LENGTH; 621 // _item_length_init equivalent. 622 s->item_length_location = rdata_tail++; 623 624 if (rdata_tail > rdata_stop) { 625 WARN(ZS_TEXT_OVERFLOW); 626 fhold; fgoto err_line; 627 } 628 } 629 630 *rdata_tail = 0; 631 s->item_length++; 632 } else { 633 WARN(ZS_TEXT_OVERFLOW); 634 fhold; fgoto err_line; 635 } 636 } 637 action _text_dec { 638 if ((*rdata_tail < (UINT8_MAX / 10)) || // Dominant fast check. 639 ((*rdata_tail == (UINT8_MAX / 10)) && // Marginal case. 640 (fc <= (UINT8_MAX % 10) + '0') 641 ) 642 ) { 643 *rdata_tail *= 10; 644 *rdata_tail += digit_to_num[(uint8_t)fc]; 645 } else { 646 WARN(ZS_NUMBER8_OVERFLOW); 647 fhold; fgoto err_line; 648 } 649 } 650 action _text_dec_exit { 651 rdata_tail++; 652 } 653 action _text_dec_error { 654 WARN(ZS_BAD_NUMBER); 655 fhold; fgoto err_line; 656 } 657 658 action _comma_list { 659 uint8_t *last_two = rdata_tail - 2; 660 uint16_t current_len = rdata_tail - s->item_length_location - 2; 661 if (s->comma_list) { 662 if (last_two[1] == ',') { 663 if (current_len <= 1) { 664 WARN(ZS_EMPTY_LIST_ITEM); 665 fhold; fgoto err_line; 666 } else if (last_two[0] != '\\') { // Start a new item. 667 *(s->item_length_location) = current_len; 668 s->item_length_location = rdata_tail - 1; 669 } else { // Remove backslash. 670 last_two[0] = ','; 671 rdata_tail--; 672 } 673 } else if (current_len > 1 && last_two[1] == '\\') { 674 if (last_two[0] == '\\') { // Remove backslash. 675 rdata_tail--; 676 } 677 } 678 } 679 } 680 681 text_char = 682 ( (33..126 - [\\;\"]) $_text_char # One printable char. 683 | ('\\' . (32..126 - digit)) @_text_char # One "\x" char. 684 | ('\\' %_text_dec_init # Initial "\" char. 685 . digit {3} $_text_dec %_text_dec_exit # "DDD" rest. 686 $!_text_dec_error 687 ) 688 ) %_comma_list $!_text_char_error; 689 690 quoted_text_char = 691 ( text_char 692 | ([ \t;] | [\n] when { s->multiline }) $_text_char 693 ) $!_text_char_error; 694 695 # Text string machine instantiation (for smaller code). 696 text_ := (('\"' . quoted_text_char* . '\"') | text_char+) 697 $!_text_error %_ret . all_wchar; 698 text = ^all_wchar ${ fhold; fcall text_; }; 699 700 # Text string with forward 1-byte length. 701 text_string = text >_item_length_init %_item_length_exit; 702 703 action _text_array_init { 704 s->long_string = true; 705 } 706 action _text_array_exit { 707 s->long_string = false; 708 } 709 710 # Text string array as one rdata item. 711 text_array = 712 ( (text_string . (sep . text_string)* . sep?) 713 ) >_text_array_init %_text_array_exit $!_text_array_exit; 714 # END 715 716 # BEGIN - TTL directive processing 717 action _default_ttl_exit { 718 if (s->number64 <= UINT32_MAX) { 719 s->default_ttl = (uint32_t)(s->number64); 720 } else { 721 ERR(ZS_NUMBER32_OVERFLOW); 722 fhold; fgoto err_line; 723 } 724 } 725 action _default_ttl_error { 726 ERR(ZS_BAD_TTL); 727 fhold; fgoto err_line; 728 } 729 730 default_ttl_ := (sep . time . rest) $!_default_ttl_error 731 %_default_ttl_exit %_ret . newline; 732 default_ttl = all_wchar ${ fhold; fcall default_ttl_; }; 733 # END 734 735 # BEGIN - ORIGIN directive processing 736 action _zone_origin_init { 737 s->dname = s->zone_origin; 738 } 739 action _zone_origin_exit { 740 s->zone_origin_length = s->dname_tmp_length; 741 } 742 action _zone_origin_error { 743 ERR(ZS_BAD_ORIGIN); 744 fhold; fgoto err_line; 745 } 746 747 zone_origin_ := (sep . absolute_dname >_zone_origin_init . rest) 748 $!_zone_origin_error %_zone_origin_exit %_ret . newline; 749 zone_origin = all_wchar ${ fhold; fcall zone_origin_; }; 750 # END 751 752 # BEGIN - INCLUDE directive processing 753 action _incl_filename_init { 754 rdata_tail = s->r_data; 755 } 756 action _incl_filename_exit { 757 size_t len = rdata_tail - s->r_data; 758 if (len >= sizeof(s->include_filename)) { 759 ERR(ZS_BAD_INCLUDE_FILENAME); 760 fhold; fgoto err_line; 761 } 762 763 // Store zero terminated include filename. 764 memcpy(s->include_filename, s->r_data, len); 765 s->include_filename[len] = '\0'; 766 767 // For detection whether origin is not present. 768 s->dname = NULL; 769 } 770 action _incl_filename_error { 771 ERR(ZS_BAD_INCLUDE_FILENAME); 772 fhold; fgoto err_line; 773 } 774 775 action _incl_origin_init { 776 s->dname = s->r_data; 777 } 778 action _incl_origin_exit { 779 s->r_data_length = s->dname_tmp_length; 780 } 781 action _incl_origin_error { 782 ERR(ZS_BAD_INCLUDE_ORIGIN); 783 fhold; fgoto err_line; 784 } 785 786 action _include_exit { 787 // Extend relative file path. 788 if (s->include_filename[0] != '/') { 789 int ret = snprintf((char *)(s->buffer), sizeof(s->buffer), 790 "%s/%s", s->path, s->include_filename); 791 if (ret <= 0 || ret >= sizeof(s->buffer)) { 792 ERR(ZS_BAD_INCLUDE_FILENAME); 793 fhold; fgoto err_line; 794 } 795 memcpy(s->include_filename, s->buffer, ret + 1); 796 } 797 798 // Origin conversion from wire to text form in \DDD notation. 799 if (s->dname == NULL) { // Use current origin. 800 wire_dname_to_str(s->zone_origin, 801 s->zone_origin_length, 802 (char *)s->buffer); 803 } else { // Use specified origin. 804 wire_dname_to_str(s->r_data, 805 s->r_data_length, 806 (char *)s->buffer); 807 } 808 809 // Let the caller to solve the include. 810 if (s->process.automatic) { 811 // Create new scanner for included zone file. 812 zs_scanner_t *ss = malloc(sizeof(zs_scanner_t)); 813 if (ss == NULL) { 814 ERR(ZS_UNPROCESSED_INCLUDE); 815 fhold; fgoto err_line; 816 } 817 818 // Parse included zone file. 819 if (zs_init(ss, (char *)s->buffer, s->default_class, 820 s->default_ttl) != 0 || 821 zs_set_input_file(ss, (char *)(s->include_filename)) != 0 || 822 zs_set_processing(ss, s->process.record, s->process.error, 823 s->process.data) != 0 || 824 zs_parse_all(ss) != 0) { 825 // File internal errors are handled by error callback. 826 if (ss->error.counter > 0) { 827 s->error.counter += ss->error.counter; 828 ERR(ZS_UNPROCESSED_INCLUDE); 829 // General include file error. 830 } else { 831 ERR(ss->error.code); 832 } 833 zs_deinit(ss); 834 free(ss); 835 fhold; fgoto err_line; 836 } 837 zs_deinit(ss); 838 free(ss); 839 } else { 840 s->state = ZS_STATE_INCLUDE; 841 fhold; fnext main; fbreak; 842 } 843 } 844 845 include_file_ := 846 (sep . text >_incl_filename_init %_incl_filename_exit 847 $!_incl_filename_error . 848 (sep . absolute_dname >_incl_origin_init %_incl_origin_exit 849 $!_incl_origin_error 850 )? . rest 851 ) %_include_exit %_ret newline; 852 include_file = all_wchar ${ fhold; fcall include_file_; }; 853 # END 854 855 # BEGIN - Directive switch 856 # Each error/warning in directive should stop processing. 857 # Some internal errors cause warning only. This causes stop processing. 858 action _directive_init { 859 ERR(ZS_OK); 860 } 861 # Remove stop processing flag. 862 action _directive_exit { 863 NOERR; 864 } 865 action _directive_error { 866 ERR(ZS_BAD_DIRECTIVE); 867 fhold; fgoto err_line; 868 } 869 870 directive = '$' . ( ("TTL"i . default_ttl) 871 | ("ORIGIN"i . zone_origin) 872 | ("INCLUDE"i . include_file) 873 ) >_directive_init %_directive_exit $!_directive_error; 874 # END 875 876 # BEGIN - RRecord class and ttl processing 877 action _default_r_class_exit { 878 s->r_class = s->default_class; 879 } 880 881 action _default_r_ttl_exit { 882 s->r_ttl = s->default_ttl; 883 } 884 885 action _r_class_in_exit { 886 s->r_class = KNOT_CLASS_IN; 887 } 888 889 action _r_ttl_exit { 890 if (s->number64 <= UINT32_MAX) { 891 s->r_ttl = (uint32_t)(s->number64); 892 } else { 893 WARN(ZS_NUMBER32_OVERFLOW); 894 fhold; fgoto err_line; 895 } 896 } 897 898 r_class = "IN"i %_r_class_in_exit; 899 900 r_ttl = time %_r_ttl_exit; 901 # END 902 903 # BEGIN - IPv4 and IPv6 address processing 904 action _addr_init { 905 s->buffer_length = 0; 906 } 907 action _addr { 908 if (s->buffer_length < sizeof(s->buffer) - 1) { 909 s->buffer[s->buffer_length++] = fc; 910 } else { 911 WARN(ZS_RDATA_OVERFLOW); 912 fhold; fgoto err_line; 913 } 914 } 915 action _addr_error { 916 WARN(ZS_BAD_ADDRESS_CHAR); 917 fhold; fgoto err_line; 918 } 919 920 action _ipv4_addr_exit { 921 s->buffer[s->buffer_length] = 0; 922 923 if (inet_pton(AF_INET, (char *)s->buffer, s->addr) <= 0) { 924 WARN(ZS_BAD_IPV4); 925 fhold; fgoto err_line; 926 } 927 } 928 action _ipv4_addr_write { 929 if (rdata_tail + ZS_INET4_ADDR_LENGTH > rdata_stop + 1) { 930 WARN(ZS_RDATA_OVERFLOW); 931 fhold; fgoto err_line; 932 } 933 memcpy(rdata_tail, s->addr, ZS_INET4_ADDR_LENGTH); 934 rdata_tail += ZS_INET4_ADDR_LENGTH; 935 } 936 937 action _ipv6_addr_exit { 938 s->buffer[s->buffer_length] = 0; 939 940 if (inet_pton(AF_INET6, (char *)s->buffer, s->addr) <= 0) { 941 WARN(ZS_BAD_IPV6); 942 fhold; fgoto err_line; 943 } 944 } 945 action _ipv6_addr_write { 946 if (rdata_tail + ZS_INET6_ADDR_LENGTH > rdata_stop + 1) { 947 WARN(ZS_RDATA_OVERFLOW); 948 fhold; fgoto err_line; 949 } 950 memcpy(rdata_tail, s->addr, ZS_INET6_ADDR_LENGTH); 951 rdata_tail += ZS_INET6_ADDR_LENGTH; 952 } 953 954 # Address parsers only. 955 ipv4_addr = (digit | '.')+ >_addr_init $_addr %_ipv4_addr_exit 956 $!_addr_error; 957 ipv6_addr = (xdigit | [.:])+ >_addr_init $_addr %_ipv6_addr_exit 958 $!_addr_error; 959 960 # Write parsed address to r_data. 961 ipv4_addr_write = ipv4_addr %_ipv4_addr_write; 962 ipv6_addr_write = ipv6_addr %_ipv6_addr_write; 963 # END 964 965 # BEGIN - apl record processing 966 action _apl_init { 967 memset(&(s->apl), 0, sizeof(s->apl)); 968 } 969 action _apl_excl_flag { 970 s->apl.excl_flag = 128; // dec 128 = bin 10000000. 971 } 972 action _apl_addr_1 { 973 s->apl.addr_family = 1; 974 } 975 action _apl_addr_2 { 976 s->apl.addr_family = 2; 977 } 978 action _apl_prefix_length { 979 if ((s->apl.addr_family == 1 && s->number64 <= 32) || 980 (s->apl.addr_family == 2 && s->number64 <= 128)) { 981 s->apl.prefix_length = (uint8_t)(s->number64); 982 } else { 983 WARN(ZS_BAD_APL); 984 fhold; fgoto err_line; 985 } 986 } 987 action _apl_exit { 988 // Copy address to buffer. 989 uint8_t len; 990 switch (s->apl.addr_family) { 991 case 1: 992 len = ZS_INET4_ADDR_LENGTH; 993 memcpy(s->buffer, s->addr, len); 994 break; 995 case 2: 996 len = ZS_INET6_ADDR_LENGTH; 997 memcpy(s->buffer, s->addr, len); 998 break; 999 default: 1000 WARN(ZS_BAD_APL); 1001 fhold; fgoto err_line; 1002 } 1003 // Find prefix without trailing zeroes. 1004 while (len > 0) { 1005 if ((s->buffer[len - 1] & 255) != 0) { 1006 break; 1007 } 1008 len--; 1009 } 1010 // Check for rdata overflow. 1011 if (rdata_tail + 4 + len > rdata_stop + 1) { 1012 WARN(ZS_RDATA_OVERFLOW); 1013 fhold; fgoto err_line; 1014 } 1015 // Write address family. 1016 uint16_t af = htons(s->apl.addr_family); 1017 memcpy(rdata_tail, &af, sizeof(af)); 1018 rdata_tail += 2; 1019 // Write prefix length in bits. 1020 *(rdata_tail) = s->apl.prefix_length; 1021 rdata_tail += 1; 1022 // Write negation flag + prefix length in bytes. 1023 *(rdata_tail) = len + s->apl.excl_flag; 1024 rdata_tail += 1; 1025 // Write address prefix non-null data. 1026 memcpy(rdata_tail, s->buffer, len); 1027 rdata_tail += len; 1028 } 1029 action _apl_error { 1030 WARN(ZS_BAD_APL); 1031 fhold; fgoto err_line; 1032 } 1033 1034 apl = ('!'? $_apl_excl_flag . 1035 ( ('1' $_apl_addr_1 . ':' . ipv4_addr . '/' . number 1036 %_apl_prefix_length) 1037 | ('2' $_apl_addr_2 . ':' . ipv6_addr . '/' . number 1038 %_apl_prefix_length) 1039 ) 1040 ) >_apl_init %_apl_exit $!_apl_error; 1041 1042 # Array of APL records (can be empty). 1043 apl_array = apl? . (sep . apl)* . sep?; 1044 # END 1045 1046 # BEGIN - Hexadecimal string array processing 1047 action _first_hex_char { 1048 if (rdata_tail <= rdata_stop) { 1049 *rdata_tail = first_hex_to_num[(uint8_t)fc]; 1050 } else { 1051 WARN(ZS_RDATA_OVERFLOW); 1052 fhold; fgoto err_line; 1053 } 1054 } 1055 action _second_hex_char { 1056 *rdata_tail += second_hex_to_num[(uint8_t)fc]; 1057 rdata_tail++; 1058 } 1059 action _hex_char_error { 1060 WARN(ZS_BAD_HEX_CHAR); 1061 fhold; fgoto err_line; 1062 } 1063 1064 hex_char = (xdigit $_first_hex_char . xdigit $_second_hex_char); 1065 1066 # Hex array with possibility of inside white spaces and multiline. 1067 hex_array = (hex_char+ . sep?)+ $!_hex_char_error; 1068 1069 # Continuous hex array (or "-") with forward length processing. 1070 salt = (hex_char+ | '-') >_item_length_init %_item_length_exit 1071 $!_hex_char_error; 1072 1073 action _type_data_exit { 1074 if ((rdata_tail - s->r_data) != s->r_data_length) { 1075 WARN(ZS_BAD_RDATA_LENGTH); 1076 fhold; fgoto err_line; 1077 } 1078 } 1079 1080 action _type_data_error { 1081 WARN(ZS_BAD_HEX_RDATA); 1082 fhold; fgoto err_line; 1083 } 1084 1085 # Hex array with control to forward length statement. 1086 type_data = hex_array %_type_data_exit $!_type_data_error; 1087 # END 1088 1089 # BEGIN - Base64 processing (RFC 4648) 1090 action _first_base64_char { 1091 if (rdata_tail <= rdata_stop) { 1092 *rdata_tail = first_base64_to_num[(uint8_t)fc]; 1093 } else { 1094 WARN(ZS_RDATA_OVERFLOW); 1095 fhold; fgoto err_line; 1096 } 1097 } 1098 action _second_base64_char { 1099 *(rdata_tail++) += second_left_base64_to_num[(uint8_t)fc]; 1100 1101 if (rdata_tail <= rdata_stop) { 1102 *rdata_tail = second_right_base64_to_num[(uint8_t)fc]; 1103 } else { 1104 WARN(ZS_RDATA_OVERFLOW); 1105 fhold; fgoto err_line; 1106 } 1107 } 1108 action _third_base64_char { 1109 *(rdata_tail++) += third_left_base64_to_num[(uint8_t)fc]; 1110 1111 if (rdata_tail <= rdata_stop) { 1112 *rdata_tail = third_right_base64_to_num[(uint8_t)fc]; 1113 } else { 1114 WARN(ZS_RDATA_OVERFLOW); 1115 fhold; fgoto err_line; 1116 } 1117 } 1118 action _fourth_base64_char { 1119 *(rdata_tail++) += fourth_base64_to_num[(uint8_t)fc]; 1120 } 1121 1122 action _base64_char_error { 1123 WARN(ZS_BAD_BASE64_CHAR); 1124 fhold; fgoto err_line; 1125 } 1126 1127 base64_char = alnum | [+/]; 1128 base64_padd = '='; 1129 base64_quartet = 1130 ( base64_char $_first_base64_char . # A 1131 base64_char $_second_base64_char . # AB 1132 ( ( base64_char $_third_base64_char . # ABC 1133 ( base64_char $_fourth_base64_char # ABCD 1134 | base64_padd{1} # ABC= 1135 ) 1136 ) 1137 | base64_padd{2} # AB== 1138 ) 1139 ); 1140 1141 # Base64 array with possibility of inside white spaces and multiline. 1142 base64_ := (base64_quartet+ . sep?)+ $!_base64_char_error 1143 %_ret . end_wchar; 1144 base64 = base64_char ${ fhold; fcall base64_; }; 1145 # END 1146 1147 # BEGIN - Base32hex processing (RFC 4648) 1148 action _first_base32hex_char { 1149 if (rdata_tail <= rdata_stop) { 1150 *rdata_tail = first_base32hex_to_num[(uint8_t)fc]; 1151 } else { 1152 WARN(ZS_RDATA_OVERFLOW); 1153 fhold; fgoto err_line; 1154 } 1155 } 1156 action _second_base32hex_char { 1157 *(rdata_tail++) += second_left_base32hex_to_num[(uint8_t)fc]; 1158 1159 if (rdata_tail <= rdata_stop) { 1160 *rdata_tail = second_right_base32hex_to_num[(uint8_t)fc]; 1161 } else { 1162 WARN(ZS_RDATA_OVERFLOW); 1163 fhold; fgoto err_line; 1164 } 1165 } 1166 action _third_base32hex_char { 1167 *rdata_tail += third_base32hex_to_num[(uint8_t)fc]; 1168 } 1169 action _fourth_base32hex_char { 1170 *(rdata_tail++) += fourth_left_base32hex_to_num[(uint8_t)fc]; 1171 1172 if (rdata_tail <= rdata_stop) { 1173 *rdata_tail = fourth_right_base32hex_to_num[(uint8_t)fc]; 1174 } else { 1175 WARN(ZS_RDATA_OVERFLOW); 1176 fhold; fgoto err_line; 1177 } 1178 } 1179 action _fifth_base32hex_char { 1180 *(rdata_tail++) += fifth_left_base32hex_to_num[(uint8_t)fc]; 1181 1182 if (rdata_tail <= rdata_stop) { 1183 *rdata_tail = fifth_right_base32hex_to_num[(uint8_t)fc]; 1184 } else { 1185 WARN(ZS_RDATA_OVERFLOW); 1186 fhold; fgoto err_line; 1187 } 1188 } 1189 action _sixth_base32hex_char { 1190 *rdata_tail += sixth_base32hex_to_num[(uint8_t)fc]; 1191 } 1192 action _seventh_base32hex_char { 1193 *(rdata_tail++) += seventh_left_base32hex_to_num[(uint8_t)fc]; 1194 1195 if (rdata_tail <= rdata_stop) { 1196 *rdata_tail = seventh_right_base32hex_to_num[(uint8_t)fc]; 1197 } else { 1198 WARN(ZS_RDATA_OVERFLOW); 1199 fhold; fgoto err_line; 1200 } 1201 } 1202 action _eighth_base32hex_char { 1203 *(rdata_tail++) += eighth_base32hex_to_num[(uint8_t)fc]; 1204 } 1205 1206 action _base32hex_char_error { 1207 WARN(ZS_BAD_BASE32HEX_CHAR); 1208 fhold; fgoto err_line; 1209 } 1210 1211 base32hex_char = [0-9a-vA-V]; 1212 base32hex_padd = '='; 1213 base32hex_octet = 1214 ( base32hex_char $_first_base32hex_char . # A 1215 base32hex_char $_second_base32hex_char . # AB 1216 ( ( base32hex_char $_third_base32hex_char . # ABC 1217 base32hex_char $_fourth_base32hex_char . # ABCD 1218 ( ( base32hex_char $_fifth_base32hex_char . # ABCDE 1219 ( ( base32hex_char $_sixth_base32hex_char . # ABCDEF 1220 base32hex_char $_seventh_base32hex_char . # ABCDEFG 1221 ( base32hex_char $_eighth_base32hex_char # ABCDEFGH 1222 | base32hex_padd{1} # ABCDEFG= 1223 ) 1224 ) 1225 | base32hex_padd{3} # ABCDE=== 1226 ) 1227 ) 1228 | base32hex_padd{4} # ABCD==== 1229 ) 1230 ) 1231 | base32hex_padd{6} # AB====== 1232 ) 1233 ); 1234 1235 # Continuous base32hex (with padding!) array with forward length processing. 1236 hash = base32hex_octet+ >_item_length_init %_item_length_exit 1237 $!_base32hex_char_error; 1238 # END 1239 1240 # BEGIN - Simple number write functions. 1241 action _write8_0 { 1242 *(rdata_tail++) = 0; 1243 } 1244 action _write8_1 { 1245 *(rdata_tail++) = 1; 1246 } 1247 action _write8_2 { 1248 *(rdata_tail++) = 2; 1249 } 1250 action _write8_3 { 1251 *(rdata_tail++) = 3; 1252 } 1253 action _write8_5 { 1254 *(rdata_tail++) = 5; 1255 } 1256 action _write8_6 { 1257 *(rdata_tail++) = 6; 1258 } 1259 action _write8_7 { 1260 *(rdata_tail++) = 7; 1261 } 1262 action _write8_8 { 1263 *(rdata_tail++) = 8; 1264 } 1265 action _write8_10 { 1266 *(rdata_tail++) = 10; 1267 } 1268 action _write8_12 { 1269 *(rdata_tail++) = 12; 1270 } 1271 action _write8_13 { 1272 *(rdata_tail++) = 13; 1273 } 1274 action _write8_14 { 1275 *(rdata_tail++) = 14; 1276 } 1277 action _write8_15 { 1278 *(rdata_tail++) = 15; 1279 } 1280 action _write8_16 { 1281 *(rdata_tail++) = 16; 1282 } 1283 action _write8_252 { 1284 *(rdata_tail++) = 252; 1285 } 1286 action _write8_253 { 1287 *(rdata_tail++) = 253; 1288 } 1289 action _write8_254 { 1290 *(rdata_tail++) = 254; 1291 } 1292 1293 action _write16_0 { 1294 uint16_t val = htons(0); 1295 memcpy(rdata_tail, &val, 2); 1296 rdata_tail += 2; 1297 } 1298 action _write16_1 { 1299 uint16_t val = htons(1); 1300 memcpy(rdata_tail, &val, 2); 1301 rdata_tail += 2; 1302 } 1303 action _write16_2 { 1304 uint16_t val = htons(2); 1305 memcpy(rdata_tail, &val, 2); 1306 rdata_tail += 2; 1307 } 1308 action _write16_3 { 1309 uint16_t val = htons(3); 1310 memcpy(rdata_tail, &val, 2); 1311 rdata_tail += 2; 1312 } 1313 action _write16_4 { 1314 uint16_t val = htons(4); 1315 memcpy(rdata_tail, &val, 2); 1316 rdata_tail += 2; 1317 } 1318 action _write16_5 { 1319 uint16_t val = htons(5); 1320 memcpy(rdata_tail, &val, 2); 1321 rdata_tail += 2; 1322 } 1323 action _write16_6 { 1324 uint16_t val = htons(6); 1325 memcpy(rdata_tail, &val, 2); 1326 rdata_tail += 2; 1327 } 1328 action _write16_7 { 1329 uint16_t val = htons(7); 1330 memcpy(rdata_tail, &val, 2); 1331 rdata_tail += 2; 1332 } 1333 action _write16_8 { 1334 uint16_t val = htons(8); 1335 memcpy(rdata_tail, &val, 2); 1336 rdata_tail += 2; 1337 } 1338 action _write16_253 { 1339 uint16_t val = htons(253); 1340 memcpy(rdata_tail, &val, 2); 1341 rdata_tail += 2; 1342 } 1343 action _write16_254 { 1344 uint16_t val = htons(254); 1345 memcpy(rdata_tail, &val, 2); 1346 rdata_tail += 2; 1347 } 1348 # END 1349 1350 # BEGIN - Gateway 1351 action _gateway_error { 1352 WARN(ZS_BAD_GATEWAY); 1353 fhold; fgoto err_line; 1354 } 1355 action _gateway_key_error { 1356 WARN(ZS_BAD_GATEWAY_KEY); 1357 fhold; fgoto err_line; 1358 } 1359 1360 gateway = (( ('0' $_write8_0 . sep . num8 . sep . '.') 1361 | ('1' $_write8_1 . sep . num8 . sep . ipv4_addr_write) 1362 | ('2' $_write8_2 . sep . num8 . sep . ipv6_addr_write) 1363 | ('3' $_write8_3 . sep . num8 . sep . r_dname) 1364 ) $!_gateway_error . 1365 # If algorithm is 0 then key isn't present and vice versa. 1366 ( ((sep . base64) when { s->number64 != 0 }) 1367 | ((sep?) when { s->number64 == 0 }) # remove blank space 1368 ) $!_gateway_key_error 1369 ); 1370 # END 1371 1372 # BEGIN - Type processing 1373 action _type_error { 1374 WARN(ZS_UNSUPPORTED_TYPE); 1375 fhold; fgoto err_line; 1376 } 1377 1378 type_num = 1379 ( "A"i %{ type_num(KNOT_RRTYPE_A, &rdata_tail); } 1380 | "NS"i %{ type_num(KNOT_RRTYPE_NS, &rdata_tail); } 1381 | "CNAME"i %{ type_num(KNOT_RRTYPE_CNAME, &rdata_tail); } 1382 | "SOA"i %{ type_num(KNOT_RRTYPE_SOA, &rdata_tail); } 1383 | "PTR"i %{ type_num(KNOT_RRTYPE_PTR, &rdata_tail); } 1384 | "HINFO"i %{ type_num(KNOT_RRTYPE_HINFO, &rdata_tail); } 1385 | "MINFO"i %{ type_num(KNOT_RRTYPE_MINFO, &rdata_tail); } 1386 | "MX"i %{ type_num(KNOT_RRTYPE_MX, &rdata_tail); } 1387 | "TXT"i %{ type_num(KNOT_RRTYPE_TXT, &rdata_tail); } 1388 | "RP"i %{ type_num(KNOT_RRTYPE_RP, &rdata_tail); } 1389 | "AFSDB"i %{ type_num(KNOT_RRTYPE_AFSDB, &rdata_tail); } 1390 | "RT"i %{ type_num(KNOT_RRTYPE_RT, &rdata_tail); } 1391 | "KEY"i %{ type_num(KNOT_RRTYPE_KEY, &rdata_tail); } 1392 | "AAAA"i %{ type_num(KNOT_RRTYPE_AAAA, &rdata_tail); } 1393 | "LOC"i %{ type_num(KNOT_RRTYPE_LOC, &rdata_tail); } 1394 | "SRV"i %{ type_num(KNOT_RRTYPE_SRV, &rdata_tail); } 1395 | "NAPTR"i %{ type_num(KNOT_RRTYPE_NAPTR, &rdata_tail); } 1396 | "KX"i %{ type_num(KNOT_RRTYPE_KX, &rdata_tail); } 1397 | "CERT"i %{ type_num(KNOT_RRTYPE_CERT, &rdata_tail); } 1398 | "DNAME"i %{ type_num(KNOT_RRTYPE_DNAME, &rdata_tail); } 1399 | "APL"i %{ type_num(KNOT_RRTYPE_APL, &rdata_tail); } 1400 | "DS"i %{ type_num(KNOT_RRTYPE_DS, &rdata_tail); } 1401 | "SSHFP"i %{ type_num(KNOT_RRTYPE_SSHFP, &rdata_tail); } 1402 | "IPSECKEY"i %{ type_num(KNOT_RRTYPE_IPSECKEY, &rdata_tail); } 1403 | "RRSIG"i %{ type_num(KNOT_RRTYPE_RRSIG, &rdata_tail); } 1404 | "NSEC"i %{ type_num(KNOT_RRTYPE_NSEC, &rdata_tail); } 1405 | "DNSKEY"i %{ type_num(KNOT_RRTYPE_DNSKEY, &rdata_tail); } 1406 | "DHCID"i %{ type_num(KNOT_RRTYPE_DHCID, &rdata_tail); } 1407 | "NSEC3"i %{ type_num(KNOT_RRTYPE_NSEC3, &rdata_tail); } 1408 | "NSEC3PARAM"i %{ type_num(KNOT_RRTYPE_NSEC3PARAM, &rdata_tail); } 1409 | "TLSA"i %{ type_num(KNOT_RRTYPE_TLSA, &rdata_tail); } 1410 | "SMIMEA"i %{ type_num(KNOT_RRTYPE_SMIMEA, &rdata_tail); } 1411 | "CDS"i %{ type_num(KNOT_RRTYPE_CDS, &rdata_tail); } 1412 | "CDNSKEY"i %{ type_num(KNOT_RRTYPE_CDNSKEY, &rdata_tail); } 1413 | "OPENPGPKEY"i %{ type_num(KNOT_RRTYPE_OPENPGPKEY, &rdata_tail); } 1414 | "CSYNC"i %{ type_num(KNOT_RRTYPE_CSYNC, &rdata_tail); } 1415 | "ZONEMD"i %{ type_num(KNOT_RRTYPE_ZONEMD, &rdata_tail); } 1416 | "SPF"i %{ type_num(KNOT_RRTYPE_SPF, &rdata_tail); } 1417 | "NID"i %{ type_num(KNOT_RRTYPE_NID, &rdata_tail); } 1418 | "L32"i %{ type_num(KNOT_RRTYPE_L32, &rdata_tail); } 1419 | "L64"i %{ type_num(KNOT_RRTYPE_L64, &rdata_tail); } 1420 | "LP"i %{ type_num(KNOT_RRTYPE_LP, &rdata_tail); } 1421 | "EUI48"i %{ type_num(KNOT_RRTYPE_EUI48, &rdata_tail); } 1422 | "EUI64"i %{ type_num(KNOT_RRTYPE_EUI64, &rdata_tail); } 1423 | "URI"i %{ type_num(KNOT_RRTYPE_URI, &rdata_tail); } 1424 | "CAA"i %{ type_num(KNOT_RRTYPE_CAA, &rdata_tail); } 1425 | "SVCB"i %{ type_num(KNOT_RRTYPE_SVCB, &rdata_tail); } 1426 | "HTTPS"i %{ type_num(KNOT_RRTYPE_HTTPS, &rdata_tail); } 1427 | "TYPE"i . num16 # TYPE0-TYPE65535. 1428 ) $!_type_error; 1429 # END 1430 1431 # BEGIN - Bitmap processing 1432 action _type_bitmap_exit { 1433 if (s->number64 <= UINT16_MAX) { 1434 window_add_bit(s->number64, s); 1435 } else { 1436 WARN(ZS_NUMBER16_OVERFLOW); 1437 fhold; fgoto err_line; 1438 } 1439 } 1440 1441 # TYPE0-TYPE65535. 1442 type_bitmap = number %_type_bitmap_exit; 1443 1444 type_bit = 1445 ( "A"i %{ window_add_bit(KNOT_RRTYPE_A, s); } 1446 | "NS"i %{ window_add_bit(KNOT_RRTYPE_NS, s); } 1447 | "CNAME"i %{ window_add_bit(KNOT_RRTYPE_CNAME, s); } 1448 | "SOA"i %{ window_add_bit(KNOT_RRTYPE_SOA, s); } 1449 | "PTR"i %{ window_add_bit(KNOT_RRTYPE_PTR, s); } 1450 | "HINFO"i %{ window_add_bit(KNOT_RRTYPE_HINFO, s); } 1451 | "MINFO"i %{ window_add_bit(KNOT_RRTYPE_MINFO, s); } 1452 | "MX"i %{ window_add_bit(KNOT_RRTYPE_MX, s); } 1453 | "TXT"i %{ window_add_bit(KNOT_RRTYPE_TXT, s); } 1454 | "RP"i %{ window_add_bit(KNOT_RRTYPE_RP, s); } 1455 | "AFSDB"i %{ window_add_bit(KNOT_RRTYPE_AFSDB, s); } 1456 | "RT"i %{ window_add_bit(KNOT_RRTYPE_RT, s); } 1457 | "KEY"i %{ window_add_bit(KNOT_RRTYPE_KEY, s); } 1458 | "AAAA"i %{ window_add_bit(KNOT_RRTYPE_AAAA, s); } 1459 | "LOC"i %{ window_add_bit(KNOT_RRTYPE_LOC, s); } 1460 | "SRV"i %{ window_add_bit(KNOT_RRTYPE_SRV, s); } 1461 | "NAPTR"i %{ window_add_bit(KNOT_RRTYPE_NAPTR, s); } 1462 | "KX"i %{ window_add_bit(KNOT_RRTYPE_KX, s); } 1463 | "CERT"i %{ window_add_bit(KNOT_RRTYPE_CERT, s); } 1464 | "DNAME"i %{ window_add_bit(KNOT_RRTYPE_DNAME, s); } 1465 | "APL"i %{ window_add_bit(KNOT_RRTYPE_APL, s); } 1466 | "DS"i %{ window_add_bit(KNOT_RRTYPE_DS, s); } 1467 | "SSHFP"i %{ window_add_bit(KNOT_RRTYPE_SSHFP, s); } 1468 | "IPSECKEY"i %{ window_add_bit(KNOT_RRTYPE_IPSECKEY, s); } 1469 | "RRSIG"i %{ window_add_bit(KNOT_RRTYPE_RRSIG, s); } 1470 | "NSEC"i %{ window_add_bit(KNOT_RRTYPE_NSEC, s); } 1471 | "DNSKEY"i %{ window_add_bit(KNOT_RRTYPE_DNSKEY, s); } 1472 | "DHCID"i %{ window_add_bit(KNOT_RRTYPE_DHCID, s); } 1473 | "NSEC3"i %{ window_add_bit(KNOT_RRTYPE_NSEC3, s); } 1474 | "NSEC3PARAM"i %{ window_add_bit(KNOT_RRTYPE_NSEC3PARAM, s); } 1475 | "TLSA"i %{ window_add_bit(KNOT_RRTYPE_TLSA, s); } 1476 | "SMIMEA"i %{ window_add_bit(KNOT_RRTYPE_SMIMEA, s); } 1477 | "CDS"i %{ window_add_bit(KNOT_RRTYPE_CDS, s); } 1478 | "CDNSKEY"i %{ window_add_bit(KNOT_RRTYPE_CDNSKEY, s); } 1479 | "OPENPGPKEY"i %{ window_add_bit(KNOT_RRTYPE_OPENPGPKEY, s); } 1480 | "CSYNC"i %{ window_add_bit(KNOT_RRTYPE_CSYNC, s); } 1481 | "ZONEMD"i %{ window_add_bit(KNOT_RRTYPE_ZONEMD, s); } 1482 | "SPF"i %{ window_add_bit(KNOT_RRTYPE_SPF, s); } 1483 | "NID"i %{ window_add_bit(KNOT_RRTYPE_NID, s); } 1484 | "L32"i %{ window_add_bit(KNOT_RRTYPE_L32, s); } 1485 | "L64"i %{ window_add_bit(KNOT_RRTYPE_L64, s); } 1486 | "LP"i %{ window_add_bit(KNOT_RRTYPE_LP, s); } 1487 | "EUI48"i %{ window_add_bit(KNOT_RRTYPE_EUI48, s); } 1488 | "EUI64"i %{ window_add_bit(KNOT_RRTYPE_EUI64, s); } 1489 | "URI"i %{ window_add_bit(KNOT_RRTYPE_URI, s); } 1490 | "CAA"i %{ window_add_bit(KNOT_RRTYPE_CAA, s); } 1491 | "SVCB"i %{ window_add_bit(KNOT_RRTYPE_SVCB, s); } 1492 | "HTTPS"i %{ window_add_bit(KNOT_RRTYPE_HTTPS, s); } 1493 | "TYPE"i . type_bitmap # TYPE0-TYPE65535. 1494 ); 1495 1496 action _bitmap_init { 1497 memset(s->windows, 0, sizeof(s->windows)); 1498 s->last_window = -1; 1499 } 1500 action _bitmap_exit { 1501 for (uint16_t window = 0; window <= s->last_window; window++) { 1502 if ((s->windows[window]).length > 0) { 1503 if (rdata_tail + 2 + (s->windows[window]).length <= rdata_stop) 1504 { 1505 // Window number. 1506 *rdata_tail = (uint8_t)window; 1507 rdata_tail += 1; 1508 // Bitmap length. 1509 *rdata_tail = (s->windows[window]).length; 1510 rdata_tail += 1; 1511 // Copying bitmap. 1512 memcpy(rdata_tail, 1513 (s->windows[window]).bitmap, 1514 (s->windows[window]).length); 1515 rdata_tail += (s->windows[window]).length; 1516 } else { 1517 WARN(ZS_RDATA_OVERFLOW); 1518 fhold; fgoto err_line; 1519 } 1520 } 1521 } 1522 } 1523 action _bitmap_error { 1524 WARN(ZS_BAD_BITMAP); 1525 fhold; fgoto err_line; 1526 } 1527 1528 # Blank bitmap is allowed too. 1529 bitmap_ := ((sep . type_bit)* . sep?) >_bitmap_init 1530 %_bitmap_exit %_ret $!_bitmap_error . end_wchar; 1531 bitmap = all_wchar ${ fhold; fcall bitmap_; }; 1532 # END 1533 1534 # BEGIN - Location processing 1535 action _d1_exit { 1536 if (s->number64 <= 90) { 1537 s->loc.d1 = (uint32_t)(s->number64); 1538 } else { 1539 WARN(ZS_BAD_NUMBER); 1540 fhold; fgoto err_line; 1541 } 1542 } 1543 action _d2_exit { 1544 if (s->number64 <= 180) { 1545 s->loc.d2 = (uint32_t)(s->number64); 1546 } else { 1547 WARN(ZS_BAD_NUMBER); 1548 fhold; fgoto err_line; 1549 } 1550 } 1551 action _m1_exit { 1552 if (s->number64 <= 59) { 1553 s->loc.m1 = (uint32_t)(s->number64); 1554 } else { 1555 WARN(ZS_BAD_NUMBER); 1556 fhold; fgoto err_line; 1557 } 1558 } 1559 action _m2_exit { 1560 if (s->number64 <= 59) { 1561 s->loc.m2 = (uint32_t)(s->number64); 1562 } else { 1563 WARN(ZS_BAD_NUMBER); 1564 fhold; fgoto err_line; 1565 } 1566 } 1567 action _s1_exit { 1568 if (s->number64 <= 59999) { 1569 s->loc.s1 = (uint32_t)(s->number64); 1570 } else { 1571 WARN(ZS_BAD_NUMBER); 1572 fhold; fgoto err_line; 1573 } 1574 } 1575 action _s2_exit { 1576 if (s->number64 <= 59999) { 1577 s->loc.s2 = (uint32_t)(s->number64); 1578 } else { 1579 WARN(ZS_BAD_NUMBER); 1580 fhold; fgoto err_line; 1581 } 1582 } 1583 action _alt_exit { 1584 if ((s->loc.alt_sign == 1 && s->number64 <= 4284967295) || 1585 (s->loc.alt_sign == -1 && s->number64 <= 10000000)) 1586 { 1587 s->loc.alt = (uint32_t)(s->number64); 1588 } else { 1589 WARN(ZS_BAD_NUMBER); 1590 fhold; fgoto err_line; 1591 } 1592 } 1593 action _siz_exit { 1594 if (s->number64 <= 9000000000ULL) { 1595 s->loc.siz = s->number64; 1596 } else { 1597 WARN(ZS_BAD_NUMBER); 1598 fhold; fgoto err_line; 1599 } 1600 } 1601 action _hp_exit { 1602 if (s->number64 <= 9000000000ULL) { 1603 s->loc.hp = s->number64; 1604 } else { 1605 WARN(ZS_BAD_NUMBER); 1606 fhold; fgoto err_line; 1607 } 1608 } 1609 action _vp_exit { 1610 if (s->number64 <= 9000000000ULL) { 1611 s->loc.vp = s->number64; 1612 } else { 1613 WARN(ZS_BAD_NUMBER); 1614 fhold; fgoto err_line; 1615 } 1616 } 1617 action _lat_sign { 1618 s->loc.lat_sign = -1; 1619 } 1620 action _long_sign { 1621 s->loc.long_sign = -1; 1622 } 1623 action _alt_sign { 1624 s->loc.alt_sign = -1; 1625 } 1626 1627 d1 = number %_d1_exit; 1628 d2 = number %_d2_exit; 1629 m1 = number %_m1_exit; 1630 m2 = number %_m2_exit; 1631 s1 = float3 %_s1_exit; 1632 s2 = float3 %_s2_exit; 1633 siz = float2 %_siz_exit; 1634 hp = float2 %_hp_exit; 1635 vp = float2 %_vp_exit; 1636 alt = ('-' %_alt_sign)? . float2 %_alt_exit; 1637 lat_sign = 'N' | 'S' %_lat_sign; 1638 long_sign = 'E' | 'W' %_long_sign; 1639 1640 action _loc_init { 1641 memset(&(s->loc), 0, sizeof(s->loc)); 1642 // Defaults. 1643 s->loc.siz = 100; 1644 s->loc.vp = 1000; 1645 s->loc.hp = 1000000; 1646 s->loc.lat_sign = 1; 1647 s->loc.long_sign = 1; 1648 s->loc.alt_sign = 1; 1649 } 1650 action _loc_exit { 1651 // Write version. 1652 *(rdata_tail) = 0; 1653 rdata_tail += 1; 1654 // Write size. 1655 *(rdata_tail) = loc64to8(s->loc.siz); 1656 rdata_tail += 1; 1657 // Write horizontal precision. 1658 *(rdata_tail) = loc64to8(s->loc.hp); 1659 rdata_tail += 1; 1660 // Write vertical precision. 1661 *(rdata_tail) = loc64to8(s->loc.vp); 1662 rdata_tail += 1; 1663 // Write latitude. 1664 *((uint32_t *)rdata_tail) = htonl(LOC_LAT_ZERO + s->loc.lat_sign * 1665 (3600000 * s->loc.d1 + 60000 * s->loc.m1 + s->loc.s1)); 1666 rdata_tail += 4; 1667 // Write longitude. 1668 *((uint32_t *)rdata_tail) = htonl(LOC_LONG_ZERO + s->loc.long_sign * 1669 (3600000 * s->loc.d2 + 60000 * s->loc.m2 + s->loc.s2)); 1670 rdata_tail += 4; 1671 // Write altitude. 1672 *((uint32_t *)rdata_tail) = htonl(LOC_ALT_ZERO + s->loc.alt_sign * 1673 (s->loc.alt)); 1674 rdata_tail += 4; 1675 } 1676 action _loc_error { 1677 WARN(ZS_BAD_LOC_DATA); 1678 fhold; fgoto err_line; 1679 } 1680 1681 loc = (d1 . sep . (m1 . sep . (s1 . sep)?)? . lat_sign . sep . 1682 d2 . sep . (m2 . sep . (s2 . sep)?)? . long_sign . sep . 1683 alt 'm'? . (sep . siz 'm'? . (sep . hp 'm'? . (sep . vp 'm'?)?)?)? . 1684 sep? 1685 ) >_loc_init %_loc_exit $!_loc_error; 1686 # END 1687 1688 # BEGIN - Hexadecimal rdata processing 1689 action _hex_r_data_error { 1690 WARN(ZS_BAD_HEX_RDATA); 1691 fhold; fgoto err_line; 1692 } 1693 1694 nonempty_hex_r_data := 1695 (sep . length_number . sep . type_data) 1696 $!_hex_r_data_error %_ret . end_wchar; 1697 1698 hex_r_data := 1699 (sep . 1700 ( ('0' %_ret . all_wchar) 1701 | (length_number . sep . type_data %_ret . end_wchar) 1702 ) 1703 ) $!_hex_r_data_error; 1704 # END 1705 1706 # BEGIN - EUI processing 1707 action _eui_init { 1708 s->item_length = 0; 1709 } 1710 action _eui_count { 1711 s->item_length++; 1712 } 1713 action _eui48_exit { 1714 if (s->item_length != 6) { 1715 WARN(ZS_BAD_EUI_LENGTH); 1716 fhold; fgoto err_line; 1717 } 1718 } 1719 action _eui64_exit { 1720 if (s->item_length != 8) { 1721 WARN(ZS_BAD_EUI_LENGTH); 1722 fhold; fgoto err_line; 1723 } 1724 } 1725 action _eui_sep_error { 1726 WARN(ZS_BAD_CHAR_DASH); 1727 fhold; fgoto err_line; 1728 } 1729 1730 eui48 = (hex_char %_eui_count . 1731 ('-' >!_eui_sep_error . hex_char %_eui_count)+ 1732 ) $!_hex_char_error >_eui_init %_eui48_exit; 1733 1734 eui64 = (hex_char %_eui_count . 1735 ('-' >!_eui_sep_error . hex_char %_eui_count)+ 1736 ) $!_hex_char_error >_eui_init %_eui64_exit; 1737 # END 1738 1739 # BEGIN - ILNP processing 1740 action _l64_init { 1741 s->item_length = 0; 1742 } 1743 action _l64_count { 1744 s->item_length++; 1745 } 1746 action _l64_exit { 1747 if (s->item_length != 4) { 1748 WARN(ZS_BAD_L64_LENGTH); 1749 fhold; fgoto err_line; 1750 } 1751 } 1752 action _l64_sep_error { 1753 WARN(ZS_BAD_CHAR_COLON); 1754 fhold; fgoto err_line; 1755 } 1756 1757 l64_label = (hex_char . hex_char) $!_hex_char_error %_l64_count; 1758 l64 = (l64_label . (':' >!_l64_sep_error . l64_label)+ 1759 ) $!_hex_char_error >_l64_init %_l64_exit; 1760 1761 l32 = ipv4_addr %_ipv4_addr_write; 1762 # END 1763 1764 # BEGIN - SvcParams processing (SVCB/HTTPS records) 1765 action _svcb_params_init { 1766 s->svcb.params_position = rdata_tail; 1767 s->svcb.last_key = -1; 1768 } 1769 action _svcb_params_exit { 1770 int ret = svcb_check(s, rdata_tail); 1771 if (ret != ZS_OK) { 1772 WARN(ret); 1773 fhold; fgoto err_line; 1774 } 1775 } 1776 action _svcb_params_error { 1777 WARN(ZS_BAD_SVCB_PARAM); 1778 fhold; fgoto err_line; 1779 } 1780 1781 action _mandat_value_error { 1782 WARN(ZS_BAD_SVCB_MANDATORY); 1783 fhold; fgoto err_line; 1784 } 1785 1786 action _svcb_param_init { 1787 if (rdata_tail + 4 > rdata_stop + 1) { // key_len + val_len 1788 WARN(ZS_RDATA_OVERFLOW); 1789 fhold; fgoto err_line; 1790 } 1791 s->svcb.param_position = rdata_tail; 1792 } 1793 action _svcb_param_exit { 1794 int ret = svcb_sort(s, rdata_tail); 1795 if (ret != ZS_OK) { 1796 WARN(ret); 1797 fhold; fgoto err_line; 1798 } 1799 } 1800 1801 action _alpnl_init { 1802 s->comma_list = true; 1803 } 1804 action _alpnl_exit { 1805 s->comma_list = false; 1806 } 1807 1808 action _mandatory_init { 1809 s->svcb.mandatory_position = rdata_tail + 2; // Skip 2-B prefix. 1810 } 1811 action _mandatory_exit { 1812 svcb_mandatory_sort(s->svcb.mandatory_position, rdata_tail); 1813 } 1814 1815 action _rdata_2B_check { 1816 if (rdata_tail + 2 > rdata_stop + 1) { 1817 WARN(ZS_RDATA_OVERFLOW); 1818 fhold; fgoto err_line; 1819 } 1820 } 1821 1822 svcb_key_generic = ("key" . num16); 1823 svcb_key_mandatory = ("mandatory" %_write16_0); 1824 svcb_key_alpn = ("alpn" %_write16_1); 1825 svcb_key_ndalpn = ("no-default-alpn" %_write16_2); 1826 svcb_key_port = ("port" %_write16_3); 1827 svcb_key_ipv4hint = ("ipv4hint" %_write16_4); 1828 svcb_key_ech = ("ech" %_write16_5); 1829 svcb_key_ipv6hint = ("ipv6hint" %_write16_6); 1830 1831 mandat_value_ := 1832 (svcb_key_generic | svcb_key_alpn | svcb_key_ndalpn | svcb_key_port | 1833 svcb_key_ipv4hint | svcb_key_ech | svcb_key_ipv6hint 1834 ) >_rdata_2B_check $!_mandat_value_error %_ret . ([,\"] | all_wchar); 1835 mandat_value = alpha ${ fhold; fcall mandat_value_; }; 1836 1837 svcb_empty = zlen %_write16_0; 1838 svcb_generic_ = (text >_item_length2_init %_item_length2_exit); 1839 svcb_generic = ("=" . svcb_generic_) | svcb_empty; 1840 svcb_mandat_ = ((mandat_value . ("," . mandat_value)*) >_item_length2_init %_item_length2_exit); 1841 svcb_mandat = svcb_mandat_ >_mandatory_init %_mandatory_exit; 1842 svcb_alpn = (text_string >_alpnl_init %_alpnl_exit >_item_length2_init %_item_length2_exit); 1843 svcb_port = num16 >_write16_2 >_rdata_2B_check; 1844 svcb_ipv4 = ((ipv4_addr_write . ("," . ipv4_addr_write)*) >_item_length2_init %_item_length2_exit); 1845 svcb_ech = (base64_quartet+ >_item_length2_init %_item_length2_exit); 1846 svcb_ipv6 = ((ipv6_addr_write . ("," . ipv6_addr_write)*) >_item_length2_init %_item_length2_exit); 1847 1848 svcb_param_generic = (svcb_key_generic . svcb_generic); 1849 svcb_param_mandatory = (svcb_key_mandatory . "=" . (svcb_mandat | ('\"' . svcb_mandat . '\"'))); 1850 svcb_param_alpn = (svcb_key_alpn . "=" . (svcb_alpn | ('\"' . svcb_alpn . '\"'))); 1851 svcb_param_ndalpn = (svcb_key_ndalpn . svcb_empty); 1852 svcb_param_port = (svcb_key_port . "=" . (svcb_port | ('\"' . svcb_port . '\"'))); 1853 svcb_param_ipv4hint = (svcb_key_ipv4hint . "=" . (svcb_ipv4 | ('\"' . svcb_ipv4 . '\"'))); 1854 svcb_param_ech = (svcb_key_ech . "=" . (svcb_ech | ('\"' . svcb_ech . '\"'))); 1855 svcb_param_ipv6hint = (svcb_key_ipv6hint . "=" . (svcb_ipv6 | ('\"' . svcb_ipv6 . '\"'))); 1856 1857 svcb_param_any = 1858 (svcb_param_generic | svcb_param_mandatory | svcb_param_alpn | 1859 svcb_param_ndalpn | svcb_param_port | svcb_param_ipv4hint | 1860 svcb_param_ech | svcb_param_ipv6hint 1861 ) >_svcb_param_init %_svcb_param_exit; 1862 svcb_params_ := 1863 ((sep . svcb_param_any)* . sep?) >_svcb_params_init 1864 %_svcb_params_exit $!_svcb_params_error %_ret . end_wchar; 1865 svcb_params = all_wchar ${ fhold; fcall svcb_params_; }; 1866 # END 1867 1868 # BEGIN - Mnemomic names processing 1869 action _dns_alg_error { 1870 WARN(ZS_BAD_ALGORITHM); 1871 fhold; fgoto err_line; 1872 } 1873 action _cert_type_error { 1874 WARN(ZS_BAD_CERT_TYPE); 1875 fhold; fgoto err_line; 1876 } 1877 1878 dns_alg_ := 1879 ( number %_num8_write 1880 | "RSAMD5"i %_write8_1 1881 | "DH"i %_write8_2 1882 | "DSA"i %_write8_3 1883 | "RSASHA1"i %_write8_5 1884 | "DSA-NSEC3-SHA1"i %_write8_6 1885 | "RSASHA1-NSEC3-SHA1"i %_write8_7 1886 | "RSASHA256"i %_write8_8 1887 | "RSASHA512"i %_write8_10 1888 | "ECC-GOST"i %_write8_12 1889 | "ECDSAP256SHA256"i %_write8_13 1890 | "ECDSAP384SHA384"i %_write8_14 1891 | "ED25519"i %_write8_15 1892 | "ED448"i %_write8_16 1893 | "INDIRECT"i %_write8_252 1894 | "PRIVATEDNS"i %_write8_253 1895 | "PRIVATEOID"i %_write8_254 1896 ) $!_dns_alg_error %_ret . all_wchar; 1897 dns_alg = alnum ${ fhold; fcall dns_alg_; }; 1898 1899 cert_type_ := 1900 ( number %_num16_write 1901 | "PKIX"i %_write16_1 1902 | "SPKI"i %_write16_2 1903 | "PGP"i %_write16_3 1904 | "IPKIX"i %_write16_4 1905 | "ISPKI"i %_write16_5 1906 | "IPGP"i %_write16_6 1907 | "ACPKIX"i %_write16_7 1908 | "IACPKIX"i %_write16_8 1909 | "URI"i %_write16_253 1910 | "OID"i %_write16_254 1911 ) $!_cert_type_error %_ret . all_wchar; 1912 cert_type = alnum ${ fhold; fcall cert_type_; }; 1913 # END 1914 1915 # BEGIN - Rdata processing 1916 action _r_data_init { 1917 rdata_tail = s->r_data; 1918 } 1919 action _r_data_error { 1920 WARN(ZS_BAD_RDATA); 1921 fhold; fgoto err_line; 1922 } 1923 1924 r_data_a := 1925 (ipv4_addr_write) 1926 $!_r_data_error %_ret . all_wchar; 1927 1928 r_data_ns := 1929 (r_dname) 1930 $!_r_data_error %_ret . all_wchar; 1931 1932 r_data_soa := 1933 (r_dname . sep . r_dname . sep . num32 . sep . time32 . 1934 sep . time32 . sep . time32 . sep . time32) 1935 $!_r_data_error %_ret . all_wchar; 1936 1937 r_data_hinfo := 1938 (text_string . sep . text_string) 1939 $!_r_data_error %_ret . all_wchar; 1940 1941 r_data_minfo := 1942 (r_dname . sep . r_dname) 1943 $!_r_data_error %_ret . all_wchar; 1944 1945 r_data_mx := 1946 (num16 . sep . r_dname) 1947 $!_r_data_error %_ret . all_wchar; 1948 1949 r_data_txt := 1950 (text_array) 1951 $!_r_data_error %_ret . end_wchar; 1952 1953 r_data_aaaa := 1954 (ipv6_addr_write) 1955 $!_r_data_error %_ret . all_wchar; 1956 1957 r_data_loc := 1958 (loc) 1959 $!_r_data_error %_ret . end_wchar; 1960 1961 r_data_srv := 1962 (num16 . sep . num16 . sep . num16 . sep . r_dname) 1963 $!_r_data_error %_ret . all_wchar; 1964 1965 r_data_naptr := 1966 (num16 . sep . num16 . sep . text_string . sep . text_string . 1967 sep . text_string . sep . r_dname) 1968 $!_r_data_error %_ret . all_wchar; 1969 1970 r_data_cert := 1971 (cert_type . sep . num16 . sep . dns_alg . sep . base64) 1972 $!_r_data_error %_ret . end_wchar; 1973 1974 r_data_apl := 1975 (apl_array) 1976 $!_r_data_error %_ret . end_wchar; 1977 1978 r_data_ds := 1979 (num16 . sep . dns_alg . sep . num8 . sep . hex_array) 1980 $!_r_data_error %_ret . end_wchar; 1981 1982 r_data_sshfp := 1983 (num8 . sep . num8 . sep . hex_array) 1984 $!_r_data_error %_ret . end_wchar; 1985 1986 r_data_ipseckey := 1987 (num8 . sep . gateway) 1988 $!_r_data_error %_ret . end_wchar; 1989 1990 r_data_rrsig := 1991 (type_num . sep . dns_alg . sep . num8 . sep . num32 . sep . 1992 timestamp . sep . timestamp . sep . num16 . sep . r_dname . 1993 sep . base64) 1994 $!_r_data_error %_ret . end_wchar; 1995 1996 r_data_nsec := 1997 (r_dname . bitmap) 1998 $!_r_data_error %_ret . all_wchar; 1999 2000 r_data_dnskey := 2001 (num16 . sep . num8 . sep . dns_alg . sep . base64) 2002 $!_r_data_error %_ret . end_wchar; 2003 2004 r_data_dhcid := 2005 (base64) 2006 $!_r_data_error %_ret . end_wchar; 2007 2008 r_data_nsec3 := 2009 (num8 . sep . num8 . sep . num16 . sep . salt . sep . 2010 hash . bitmap) 2011 $!_r_data_error %_ret . all_wchar; 2012 2013 r_data_nsec3param := 2014 (num8 . sep . num8 . sep . num16 . sep . salt) 2015 $!_r_data_error %_ret . all_wchar; 2016 2017 r_data_tlsa := 2018 (num8 . sep . num8 . sep . num8 . sep . hex_array) 2019 $!_r_data_error %_ret . end_wchar; 2020 2021 r_data_csync := 2022 (num32 . sep . num16 . bitmap) 2023 $!_r_data_error %_ret . all_wchar; 2024 2025 r_data_zonemd := 2026 (num32 . sep . num8 . sep . num8 . sep . hex_array) 2027 $!_r_data_error %_ret . end_wchar; 2028 2029 r_data_l32 := 2030 (num16 . sep . l32) 2031 $!_r_data_error %_ret . all_wchar; 2032 2033 r_data_l64 := 2034 (num16 . sep . l64) 2035 $!_r_data_error %_ret . all_wchar; 2036 2037 r_data_eui48 := 2038 (eui48) 2039 $!_r_data_error %_ret . all_wchar; 2040 2041 r_data_eui64 := 2042 (eui64) 2043 $!_r_data_error %_ret . all_wchar; 2044 2045 r_data_uri := 2046 (num16 . sep . num16 . sep . text) 2047 $!_r_data_error %_ret . all_wchar; 2048 2049 r_data_caa := 2050 (num8 . sep . text_string . sep . text) 2051 $!_r_data_error %_ret . all_wchar; 2052 2053 r_data_svcb := 2054 (num16 . sep . r_dname . svcb_params) 2055 $!_r_data_error %_ret . all_wchar; 2056 2057 action _text_r_data { 2058 fhold; 2059 switch (s->r_type) { 2060 case KNOT_RRTYPE_A: 2061 fcall r_data_a; 2062 case KNOT_RRTYPE_NS: 2063 case KNOT_RRTYPE_CNAME: 2064 case KNOT_RRTYPE_PTR: 2065 case KNOT_RRTYPE_DNAME: 2066 fcall r_data_ns; 2067 case KNOT_RRTYPE_SOA: 2068 fcall r_data_soa; 2069 case KNOT_RRTYPE_HINFO: 2070 fcall r_data_hinfo; 2071 case KNOT_RRTYPE_MINFO: 2072 case KNOT_RRTYPE_RP: 2073 fcall r_data_minfo; 2074 case KNOT_RRTYPE_MX: 2075 case KNOT_RRTYPE_AFSDB: 2076 case KNOT_RRTYPE_RT: 2077 case KNOT_RRTYPE_KX: 2078 case KNOT_RRTYPE_LP: 2079 fcall r_data_mx; 2080 case KNOT_RRTYPE_TXT: 2081 case KNOT_RRTYPE_SPF: 2082 fcall r_data_txt; 2083 case KNOT_RRTYPE_AAAA: 2084 fcall r_data_aaaa; 2085 case KNOT_RRTYPE_LOC: 2086 fcall r_data_loc; 2087 case KNOT_RRTYPE_SRV: 2088 fcall r_data_srv; 2089 case KNOT_RRTYPE_NAPTR: 2090 fcall r_data_naptr; 2091 case KNOT_RRTYPE_CERT: 2092 fcall r_data_cert; 2093 case KNOT_RRTYPE_APL: 2094 fcall r_data_apl; 2095 case KNOT_RRTYPE_DS: 2096 case KNOT_RRTYPE_CDS: 2097 fcall r_data_ds; 2098 case KNOT_RRTYPE_SSHFP: 2099 fcall r_data_sshfp; 2100 case KNOT_RRTYPE_IPSECKEY: 2101 fcall r_data_ipseckey; 2102 case KNOT_RRTYPE_RRSIG: 2103 fcall r_data_rrsig; 2104 case KNOT_RRTYPE_NSEC: 2105 fcall r_data_nsec; 2106 case KNOT_RRTYPE_KEY: 2107 case KNOT_RRTYPE_DNSKEY: 2108 case KNOT_RRTYPE_CDNSKEY: 2109 fcall r_data_dnskey; 2110 case KNOT_RRTYPE_DHCID: 2111 case KNOT_RRTYPE_OPENPGPKEY: 2112 fcall r_data_dhcid; 2113 case KNOT_RRTYPE_NSEC3: 2114 fcall r_data_nsec3; 2115 case KNOT_RRTYPE_NSEC3PARAM: 2116 fcall r_data_nsec3param; 2117 case KNOT_RRTYPE_TLSA: 2118 case KNOT_RRTYPE_SMIMEA: 2119 fcall r_data_tlsa; 2120 case KNOT_RRTYPE_CSYNC: 2121 fcall r_data_csync; 2122 case KNOT_RRTYPE_ZONEMD: 2123 fcall r_data_zonemd; 2124 case KNOT_RRTYPE_NID: 2125 case KNOT_RRTYPE_L64: 2126 fcall r_data_l64; 2127 case KNOT_RRTYPE_L32: 2128 fcall r_data_l32; 2129 case KNOT_RRTYPE_EUI48: 2130 fcall r_data_eui48; 2131 case KNOT_RRTYPE_EUI64: 2132 fcall r_data_eui64; 2133 case KNOT_RRTYPE_URI: 2134 fcall r_data_uri; 2135 case KNOT_RRTYPE_CAA: 2136 fcall r_data_caa; 2137 case KNOT_RRTYPE_SVCB: 2138 case KNOT_RRTYPE_HTTPS: 2139 fcall r_data_svcb; 2140 default: 2141 WARN(ZS_CANNOT_TEXT_DATA); 2142 fgoto err_line; 2143 } 2144 } 2145 action _hex_r_data { 2146 switch (s->r_type) { 2147 // Next types must not have empty rdata. 2148 case KNOT_RRTYPE_A: 2149 case KNOT_RRTYPE_NS: 2150 case KNOT_RRTYPE_CNAME: 2151 case KNOT_RRTYPE_PTR: 2152 case KNOT_RRTYPE_DNAME: 2153 case KNOT_RRTYPE_SOA: 2154 case KNOT_RRTYPE_HINFO: 2155 case KNOT_RRTYPE_MINFO: 2156 case KNOT_RRTYPE_MX: 2157 case KNOT_RRTYPE_AFSDB: 2158 case KNOT_RRTYPE_RT: 2159 case KNOT_RRTYPE_KX: 2160 case KNOT_RRTYPE_TXT: 2161 case KNOT_RRTYPE_SPF: 2162 case KNOT_RRTYPE_RP: 2163 case KNOT_RRTYPE_AAAA: 2164 case KNOT_RRTYPE_LOC: 2165 case KNOT_RRTYPE_SRV: 2166 case KNOT_RRTYPE_NAPTR: 2167 case KNOT_RRTYPE_CERT: 2168 case KNOT_RRTYPE_DS: 2169 case KNOT_RRTYPE_SSHFP: 2170 case KNOT_RRTYPE_IPSECKEY: 2171 case KNOT_RRTYPE_RRSIG: 2172 case KNOT_RRTYPE_NSEC: 2173 case KNOT_RRTYPE_KEY: 2174 case KNOT_RRTYPE_DNSKEY: 2175 case KNOT_RRTYPE_DHCID: 2176 case KNOT_RRTYPE_NSEC3: 2177 case KNOT_RRTYPE_NSEC3PARAM: 2178 case KNOT_RRTYPE_TLSA: 2179 case KNOT_RRTYPE_SMIMEA: 2180 case KNOT_RRTYPE_CDS: 2181 case KNOT_RRTYPE_CDNSKEY: 2182 case KNOT_RRTYPE_OPENPGPKEY: 2183 case KNOT_RRTYPE_CSYNC: 2184 case KNOT_RRTYPE_ZONEMD: 2185 case KNOT_RRTYPE_NID: 2186 case KNOT_RRTYPE_L32: 2187 case KNOT_RRTYPE_L64: 2188 case KNOT_RRTYPE_LP: 2189 case KNOT_RRTYPE_EUI48: 2190 case KNOT_RRTYPE_EUI64: 2191 case KNOT_RRTYPE_URI: 2192 case KNOT_RRTYPE_CAA: 2193 case KNOT_RRTYPE_SVCB: 2194 case KNOT_RRTYPE_HTTPS: 2195 fcall nonempty_hex_r_data; 2196 // Next types can have empty rdata. 2197 case KNOT_RRTYPE_APL: 2198 default: 2199 fcall hex_r_data; 2200 } 2201 } 2202 2203 # Avoidance of multiple fhold at the input block end. 2204 action _wrap_in { 2205 if (pe - p == 1) { 2206 *wrap = WRAP_DETECTED; 2207 } 2208 } 2209 action _wrap_out { 2210 if (*wrap == WRAP_NONE) { 2211 fhold; 2212 } 2213 } 2214 2215 # rdata can be in text or hex format with leading "\#" string. 2216 r_data = 2217 ( sep . ^('\\' | all_wchar) $_text_r_data 2218 | sep . '\\' $_wrap_in . ^'#' $_wrap_out $_text_r_data 2219 | sep . '\\' . '#' $_hex_r_data # Hex format. 2220 | sep? . end_wchar $_text_r_data # Empty rdata. 2221 ) >_r_data_init $!_r_data_error; 2222 # END 2223 2224 # BEGIN - Record type processing 2225 action _r_type_error { 2226 WARN(ZS_UNSUPPORTED_TYPE); 2227 fhold; fgoto err_line; 2228 } 2229 2230 r_type = 2231 ( "A"i %{ s->r_type = KNOT_RRTYPE_A; } 2232 | "NS"i %{ s->r_type = KNOT_RRTYPE_NS; } 2233 | "CNAME"i %{ s->r_type = KNOT_RRTYPE_CNAME; } 2234 | "SOA"i %{ s->r_type = KNOT_RRTYPE_SOA; } 2235 | "PTR"i %{ s->r_type = KNOT_RRTYPE_PTR; } 2236 | "HINFO"i %{ s->r_type = KNOT_RRTYPE_HINFO; } 2237 | "MINFO"i %{ s->r_type = KNOT_RRTYPE_MINFO; } 2238 | "MX"i %{ s->r_type = KNOT_RRTYPE_MX; } 2239 | "TXT"i %{ s->r_type = KNOT_RRTYPE_TXT; } 2240 | "RP"i %{ s->r_type = KNOT_RRTYPE_RP; } 2241 | "AFSDB"i %{ s->r_type = KNOT_RRTYPE_AFSDB; } 2242 | "RT"i %{ s->r_type = KNOT_RRTYPE_RT; } 2243 | "KEY"i %{ s->r_type = KNOT_RRTYPE_KEY; } 2244 | "AAAA"i %{ s->r_type = KNOT_RRTYPE_AAAA; } 2245 | "LOC"i %{ s->r_type = KNOT_RRTYPE_LOC; } 2246 | "SRV"i %{ s->r_type = KNOT_RRTYPE_SRV; } 2247 | "NAPTR"i %{ s->r_type = KNOT_RRTYPE_NAPTR; } 2248 | "KX"i %{ s->r_type = KNOT_RRTYPE_KX; } 2249 | "CERT"i %{ s->r_type = KNOT_RRTYPE_CERT; } 2250 | "DNAME"i %{ s->r_type = KNOT_RRTYPE_DNAME; } 2251 | "APL"i %{ s->r_type = KNOT_RRTYPE_APL; } 2252 | "DS"i %{ s->r_type = KNOT_RRTYPE_DS; } 2253 | "SSHFP"i %{ s->r_type = KNOT_RRTYPE_SSHFP; } 2254 | "IPSECKEY"i %{ s->r_type = KNOT_RRTYPE_IPSECKEY; } 2255 | "RRSIG"i %{ s->r_type = KNOT_RRTYPE_RRSIG; } 2256 | "NSEC"i %{ s->r_type = KNOT_RRTYPE_NSEC; } 2257 | "DNSKEY"i %{ s->r_type = KNOT_RRTYPE_DNSKEY; } 2258 | "DHCID"i %{ s->r_type = KNOT_RRTYPE_DHCID; } 2259 | "NSEC3"i %{ s->r_type = KNOT_RRTYPE_NSEC3; } 2260 | "NSEC3PARAM"i %{ s->r_type = KNOT_RRTYPE_NSEC3PARAM; } 2261 | "TLSA"i %{ s->r_type = KNOT_RRTYPE_TLSA; } 2262 | "SMIMEA"i %{ s->r_type = KNOT_RRTYPE_SMIMEA; } 2263 | "CDS"i %{ s->r_type = KNOT_RRTYPE_CDS; } 2264 | "CDNSKEY"i %{ s->r_type = KNOT_RRTYPE_CDNSKEY; } 2265 | "OPENPGPKEY"i %{ s->r_type = KNOT_RRTYPE_OPENPGPKEY; } 2266 | "CSYNC"i %{ s->r_type = KNOT_RRTYPE_CSYNC; } 2267 | "ZONEMD"i %{ s->r_type = KNOT_RRTYPE_ZONEMD; } 2268 | "SPF"i %{ s->r_type = KNOT_RRTYPE_SPF; } 2269 | "NID"i %{ s->r_type = KNOT_RRTYPE_NID; } 2270 | "L32"i %{ s->r_type = KNOT_RRTYPE_L32; } 2271 | "L64"i %{ s->r_type = KNOT_RRTYPE_L64; } 2272 | "LP"i %{ s->r_type = KNOT_RRTYPE_LP; } 2273 | "EUI48"i %{ s->r_type = KNOT_RRTYPE_EUI48; } 2274 | "EUI64"i %{ s->r_type = KNOT_RRTYPE_EUI64; } 2275 | "URI"i %{ s->r_type = KNOT_RRTYPE_URI; } 2276 | "CAA"i %{ s->r_type = KNOT_RRTYPE_CAA; } 2277 | "SVCB"i %{ s->r_type = KNOT_RRTYPE_SVCB; } 2278 | "HTTPS"i %{ s->r_type = KNOT_RRTYPE_HTTPS; } 2279 | "TYPE"i . type_number 2280 ) $!_r_type_error; 2281 # END 2282 2283 # BEGIN - The highest level processing 2284 action _record_exit { 2285 if (rdata_tail - s->r_data > UINT16_MAX) { 2286 WARN(ZS_RDATA_OVERFLOW); 2287 fhold; fgoto err_line; 2288 } 2289 s->r_data_length = rdata_tail - s->r_data; 2290 2291 s->state = ZS_STATE_DATA; 2292 2293 // Execute the record callback. 2294 if (s->process.automatic) { 2295 if (s->process.record != NULL) { 2296 s->process.record(s); 2297 2298 // Stop if required from the callback. 2299 if (s->state == ZS_STATE_STOP) { 2300 fbreak; 2301 } 2302 } 2303 } else { 2304 // Return if external processing. 2305 fhold; fbreak; 2306 } 2307 } 2308 2309 # Resource record. 2310 record = 2311 r_owner . sep . 2312 ( (r_class . sep . ((r_ttl . sep) | (zlen %_default_r_ttl_exit ))) 2313 | (r_ttl . sep . ((r_class . sep) | (zlen %_default_r_class_exit))) 2314 | zlen %_default_r_class_exit %_default_r_ttl_exit 2315 ) $!_r_type_error . 2316 r_type . r_data . 2317 rest %_record_exit . 2318 newline; 2319 2320 # Blank spaces with comments. 2321 blank = rest . newline; 2322 2323 # Main processing loop. 2324 main := (record | directive | blank)*; 2325 # END 2326}%% 2327