1 /* 2 * configparser.y -- yacc grammar for NSD configuration files 3 * 4 * Copyright (c) 2001-2019, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 %{ 11 #include "config.h" 12 13 #include <assert.h> 14 #include <errno.h> 15 #include <stdio.h> 16 #include <string.h> 17 18 #include "options.h" 19 #include "util.h" 20 #include "dname.h" 21 #include "tsig.h" 22 #include "rrl.h" 23 #include "configyyrename.h" 24 25 int yylex(void); 26 27 #ifdef __cplusplus 28 extern "C" 29 #endif 30 31 /* these need to be global, otherwise they cannot be used inside yacc */ 32 extern config_parser_state_type *cfg_parser; 33 34 static void append_acl(struct acl_options **list, struct acl_options *acl); 35 static int parse_boolean(const char *str, int *bln); 36 static int parse_expire_expr(const char *str, long long *num, uint8_t *expr); 37 static int parse_number(const char *str, long long *num); 38 static int parse_range(const char *str, long long *low, long long *high); 39 %} 40 41 %union { 42 char *str; 43 long long llng; 44 int bln; 45 struct ip_address_option *ip; 46 struct range_option *range; 47 struct cpu_option *cpu; 48 } 49 50 %token <str> STRING 51 %type <llng> number 52 %type <bln> boolean 53 %type <ip> ip_address 54 %type <llng> service_cpu_affinity 55 %type <cpu> cpus 56 57 /* server */ 58 %token VAR_SERVER 59 %token VAR_SERVER_COUNT 60 %token VAR_IP_ADDRESS 61 %token VAR_IP_TRANSPARENT 62 %token VAR_IP_FREEBIND 63 %token VAR_REUSEPORT 64 %token VAR_SEND_BUFFER_SIZE 65 %token VAR_RECEIVE_BUFFER_SIZE 66 %token VAR_DEBUG_MODE 67 %token VAR_IP4_ONLY 68 %token VAR_IP6_ONLY 69 %token VAR_DO_IP4 70 %token VAR_DO_IP6 71 %token VAR_PORT 72 %token VAR_USE_SYSTEMD 73 %token VAR_VERBOSITY 74 %token VAR_USERNAME 75 %token VAR_CHROOT 76 %token VAR_ZONESDIR 77 %token VAR_ZONELISTFILE 78 %token VAR_DATABASE 79 %token VAR_LOGFILE 80 %token VAR_LOG_ONLY_SYSLOG 81 %token VAR_PIDFILE 82 %token VAR_DIFFFILE 83 %token VAR_XFRDFILE 84 %token VAR_XFRDIR 85 %token VAR_HIDE_VERSION 86 %token VAR_HIDE_IDENTITY 87 %token VAR_VERSION 88 %token VAR_IDENTITY 89 %token VAR_NSID 90 %token VAR_TCP_COUNT 91 %token VAR_TCP_REJECT_OVERFLOW 92 %token VAR_TCP_QUERY_COUNT 93 %token VAR_TCP_TIMEOUT 94 %token VAR_TCP_MSS 95 %token VAR_OUTGOING_TCP_MSS 96 %token VAR_IPV4_EDNS_SIZE 97 %token VAR_IPV6_EDNS_SIZE 98 %token VAR_STATISTICS 99 %token VAR_XFRD_RELOAD_TIMEOUT 100 %token VAR_LOG_TIME_ASCII 101 %token VAR_ROUND_ROBIN 102 %token VAR_MINIMAL_RESPONSES 103 %token VAR_CONFINE_TO_ZONE 104 %token VAR_REFUSE_ANY 105 %token VAR_ZONEFILES_CHECK 106 %token VAR_ZONEFILES_WRITE 107 %token VAR_RRL_SIZE 108 %token VAR_RRL_RATELIMIT 109 %token VAR_RRL_SLIP 110 %token VAR_RRL_IPV4_PREFIX_LENGTH 111 %token VAR_RRL_IPV6_PREFIX_LENGTH 112 %token VAR_RRL_WHITELIST_RATELIMIT 113 %token VAR_TLS_SERVICE_KEY 114 %token VAR_TLS_SERVICE_PEM 115 %token VAR_TLS_SERVICE_OCSP 116 %token VAR_TLS_PORT 117 %token VAR_CPU_AFFINITY 118 %token VAR_XFRD_CPU_AFFINITY 119 %token <llng> VAR_SERVER_CPU_AFFINITY 120 %token VAR_DROP_UPDATES 121 122 /* dnstap */ 123 %token VAR_DNSTAP 124 %token VAR_DNSTAP_ENABLE 125 %token VAR_DNSTAP_SOCKET_PATH 126 %token VAR_DNSTAP_SEND_IDENTITY 127 %token VAR_DNSTAP_SEND_VERSION 128 %token VAR_DNSTAP_IDENTITY 129 %token VAR_DNSTAP_VERSION 130 %token VAR_DNSTAP_LOG_AUTH_QUERY_MESSAGES 131 %token VAR_DNSTAP_LOG_AUTH_RESPONSE_MESSAGES 132 133 /* remote-control */ 134 %token VAR_REMOTE_CONTROL 135 %token VAR_CONTROL_ENABLE 136 %token VAR_CONTROL_INTERFACE 137 %token VAR_CONTROL_PORT 138 %token VAR_SERVER_KEY_FILE 139 %token VAR_SERVER_CERT_FILE 140 %token VAR_CONTROL_KEY_FILE 141 %token VAR_CONTROL_CERT_FILE 142 143 /* key */ 144 %token VAR_KEY 145 %token VAR_ALGORITHM 146 %token VAR_SECRET 147 148 /* pattern */ 149 %token VAR_PATTERN 150 %token VAR_NAME 151 %token VAR_ZONEFILE 152 %token VAR_NOTIFY 153 %token VAR_PROVIDE_XFR 154 %token VAR_AXFR 155 %token VAR_UDP 156 %token VAR_NOTIFY_RETRY 157 %token VAR_ALLOW_NOTIFY 158 %token VAR_REQUEST_XFR 159 %token VAR_ALLOW_AXFR_FALLBACK 160 %token VAR_OUTGOING_INTERFACE 161 %token VAR_MAX_REFRESH_TIME 162 %token VAR_MIN_REFRESH_TIME 163 %token VAR_MAX_RETRY_TIME 164 %token VAR_MIN_RETRY_TIME 165 %token VAR_MIN_EXPIRE_TIME 166 %token VAR_MULTI_MASTER_CHECK 167 %token VAR_SIZE_LIMIT_XFR 168 %token VAR_ZONESTATS 169 %token VAR_INCLUDE_PATTERN 170 171 /* zone */ 172 %token VAR_ZONE 173 %token VAR_RRL_WHITELIST 174 175 /* socket options */ 176 %token VAR_SERVERS 177 %token VAR_BINDTODEVICE 178 %token VAR_SETFIB 179 180 %% 181 182 blocks: 183 /* may be empty */ 184 | blocks block ; 185 186 block: 187 server 188 | dnstap 189 | remote_control 190 | key 191 | pattern 192 | zone ; 193 194 server: 195 VAR_SERVER server_block ; 196 197 server_block: 198 server_block server_option | ; 199 200 server_option: 201 VAR_IP_ADDRESS ip_address 202 { 203 struct ip_address_option *ip = cfg_parser->opt->ip_addresses; 204 205 if(ip == NULL) { 206 cfg_parser->opt->ip_addresses = $2; 207 } else { 208 while(ip->next) { ip = ip->next; } 209 ip->next = $2; 210 } 211 212 cfg_parser->ip = $2; 213 } 214 socket_options 215 { 216 cfg_parser->ip = NULL; 217 } 218 | VAR_SERVER_COUNT number 219 { 220 if ($2 > 0) { 221 cfg_parser->opt->server_count = (int)$2; 222 } else { 223 yyerror("expected a number greater than zero"); 224 } 225 } 226 | VAR_IP_TRANSPARENT boolean 227 { cfg_parser->opt->ip_transparent = $2; } 228 | VAR_IP_FREEBIND boolean 229 { cfg_parser->opt->ip_freebind = $2; } 230 | VAR_SEND_BUFFER_SIZE number 231 { cfg_parser->opt->send_buffer_size = (int)$2; } 232 | VAR_RECEIVE_BUFFER_SIZE number 233 { cfg_parser->opt->receive_buffer_size = (int)$2; } 234 | VAR_DEBUG_MODE boolean 235 { cfg_parser->opt->debug_mode = $2; } 236 | VAR_USE_SYSTEMD boolean 237 { /* ignored, deprecated */ } 238 | VAR_HIDE_VERSION boolean 239 { cfg_parser->opt->hide_version = $2; } 240 | VAR_HIDE_IDENTITY boolean 241 { cfg_parser->opt->hide_identity = $2; } 242 | VAR_DROP_UPDATES boolean 243 { cfg_parser->opt->drop_updates = $2; } 244 | VAR_IP4_ONLY boolean 245 { if($2) { cfg_parser->opt->do_ip4 = 1; cfg_parser->opt->do_ip6 = 0; } } 246 | VAR_IP6_ONLY boolean 247 { if($2) { cfg_parser->opt->do_ip4 = 0; cfg_parser->opt->do_ip6 = 1; } } 248 | VAR_DO_IP4 boolean 249 { cfg_parser->opt->do_ip4 = $2; } 250 | VAR_DO_IP6 boolean 251 { cfg_parser->opt->do_ip6 = $2; } 252 | VAR_DATABASE STRING 253 { 254 cfg_parser->opt->database = region_strdup(cfg_parser->opt->region, $2); 255 if(cfg_parser->opt->database[0] == 0 && 256 cfg_parser->opt->zonefiles_write == 0) 257 { 258 cfg_parser->opt->zonefiles_write = ZONEFILES_WRITE_INTERVAL; 259 } 260 } 261 | VAR_IDENTITY STRING 262 { cfg_parser->opt->identity = region_strdup(cfg_parser->opt->region, $2); } 263 | VAR_VERSION STRING 264 { cfg_parser->opt->version = region_strdup(cfg_parser->opt->region, $2); } 265 | VAR_NSID STRING 266 { 267 unsigned char* nsid = 0; 268 size_t nsid_len = strlen($2); 269 270 if (strncasecmp($2, "ascii_", 6) == 0) { 271 nsid_len -= 6; /* discard "ascii_" */ 272 if(nsid_len < 65535) { 273 cfg_parser->opt->nsid = region_alloc(cfg_parser->opt->region, nsid_len*2+1); 274 hex_ntop((uint8_t*)$2+6, nsid_len, (char*)cfg_parser->opt->nsid, nsid_len*2+1); 275 } else { 276 yyerror("NSID too long"); 277 } 278 } else if (nsid_len % 2 != 0) { 279 yyerror("the NSID must be a hex string of an even length."); 280 } else { 281 nsid_len = nsid_len / 2; 282 if(nsid_len < 65535) { 283 nsid = xalloc(nsid_len); 284 if (hex_pton($2, nsid, nsid_len) == -1) { 285 yyerror("hex string cannot be parsed in NSID."); 286 } else { 287 cfg_parser->opt->nsid = region_strdup(cfg_parser->opt->region, $2); 288 } 289 free(nsid); 290 } else { 291 yyerror("NSID too long"); 292 } 293 } 294 } 295 | VAR_LOGFILE STRING 296 { cfg_parser->opt->logfile = region_strdup(cfg_parser->opt->region, $2); } 297 | VAR_LOG_ONLY_SYSLOG boolean 298 { cfg_parser->opt->log_only_syslog = $2; } 299 | VAR_TCP_COUNT number 300 { 301 if ($2 > 0) { 302 cfg_parser->opt->tcp_count = (int)$2; 303 } else { 304 yyerror("expected a number greater than zero"); 305 } 306 } 307 | VAR_TCP_REJECT_OVERFLOW boolean 308 { cfg_parser->opt->tcp_reject_overflow = $2; } 309 | VAR_TCP_QUERY_COUNT number 310 { cfg_parser->opt->tcp_query_count = (int)$2; } 311 | VAR_TCP_TIMEOUT number 312 { cfg_parser->opt->tcp_timeout = (int)$2; } 313 | VAR_TCP_MSS number 314 { cfg_parser->opt->tcp_mss = (int)$2; } 315 | VAR_OUTGOING_TCP_MSS number 316 { cfg_parser->opt->outgoing_tcp_mss = (int)$2; } 317 | VAR_IPV4_EDNS_SIZE number 318 { cfg_parser->opt->ipv4_edns_size = (size_t)$2; } 319 | VAR_IPV6_EDNS_SIZE number 320 { cfg_parser->opt->ipv6_edns_size = (size_t)$2; } 321 | VAR_PIDFILE STRING 322 { cfg_parser->opt->pidfile = region_strdup(cfg_parser->opt->region, $2); } 323 | VAR_PORT number 324 { 325 /* port number, stored as a string */ 326 char buf[16]; 327 (void)snprintf(buf, sizeof(buf), "%lld", $2); 328 cfg_parser->opt->port = region_strdup(cfg_parser->opt->region, buf); 329 } 330 | VAR_REUSEPORT boolean 331 { cfg_parser->opt->reuseport = $2; } 332 | VAR_STATISTICS number 333 { cfg_parser->opt->statistics = (int)$2; } 334 | VAR_CHROOT STRING 335 { cfg_parser->opt->chroot = region_strdup(cfg_parser->opt->region, $2); } 336 | VAR_USERNAME STRING 337 { cfg_parser->opt->username = region_strdup(cfg_parser->opt->region, $2); } 338 | VAR_ZONESDIR STRING 339 { cfg_parser->opt->zonesdir = region_strdup(cfg_parser->opt->region, $2); } 340 | VAR_ZONELISTFILE STRING 341 { cfg_parser->opt->zonelistfile = region_strdup(cfg_parser->opt->region, $2); } 342 | VAR_DIFFFILE STRING 343 { /* ignored, deprecated */ } 344 | VAR_XFRDFILE STRING 345 { cfg_parser->opt->xfrdfile = region_strdup(cfg_parser->opt->region, $2); } 346 | VAR_XFRDIR STRING 347 { cfg_parser->opt->xfrdir = region_strdup(cfg_parser->opt->region, $2); } 348 | VAR_XFRD_RELOAD_TIMEOUT number 349 { cfg_parser->opt->xfrd_reload_timeout = (int)$2; } 350 | VAR_VERBOSITY number 351 { cfg_parser->opt->verbosity = (int)$2; } 352 | VAR_RRL_SIZE number 353 { 354 #ifdef RATELIMIT 355 if ($2 > 0) { 356 cfg_parser->opt->rrl_size = (size_t)$2; 357 } else { 358 yyerror("expected a number greater than zero"); 359 } 360 #endif 361 } 362 | VAR_RRL_RATELIMIT number 363 { 364 #ifdef RATELIMIT 365 cfg_parser->opt->rrl_ratelimit = (size_t)$2; 366 #endif 367 } 368 | VAR_RRL_SLIP number 369 { 370 #ifdef RATELIMIT 371 cfg_parser->opt->rrl_slip = (size_t)$2; 372 #endif 373 } 374 | VAR_RRL_IPV4_PREFIX_LENGTH number 375 { 376 #ifdef RATELIMIT 377 if ($2 > 32) { 378 yyerror("invalid IPv4 prefix length"); 379 } else { 380 cfg_parser->opt->rrl_ipv4_prefix_length = (size_t)$2; 381 } 382 #endif 383 } 384 | VAR_RRL_IPV6_PREFIX_LENGTH number 385 { 386 #ifdef RATELIMIT 387 if ($2 > 64) { 388 yyerror("invalid IPv6 prefix length"); 389 } else { 390 cfg_parser->opt->rrl_ipv6_prefix_length = (size_t)$2; 391 } 392 #endif 393 } 394 | VAR_RRL_WHITELIST_RATELIMIT number 395 { 396 #ifdef RATELIMIT 397 cfg_parser->opt->rrl_whitelist_ratelimit = (size_t)$2; 398 #endif 399 } 400 | VAR_ZONEFILES_CHECK boolean 401 { cfg_parser->opt->zonefiles_check = $2; } 402 | VAR_ZONEFILES_WRITE number 403 { cfg_parser->opt->zonefiles_write = (int)$2; } 404 | VAR_LOG_TIME_ASCII boolean 405 { 406 cfg_parser->opt->log_time_ascii = $2; 407 log_time_asc = cfg_parser->opt->log_time_ascii; 408 } 409 | VAR_ROUND_ROBIN boolean 410 { 411 cfg_parser->opt->round_robin = $2; 412 round_robin = cfg_parser->opt->round_robin; 413 } 414 | VAR_MINIMAL_RESPONSES boolean 415 { 416 cfg_parser->opt->minimal_responses = $2; 417 minimal_responses = cfg_parser->opt->minimal_responses; 418 } 419 | VAR_CONFINE_TO_ZONE boolean 420 { cfg_parser->opt->confine_to_zone = $2; } 421 | VAR_REFUSE_ANY boolean 422 { cfg_parser->opt->refuse_any = $2; } 423 | VAR_TLS_SERVICE_KEY STRING 424 { cfg_parser->opt->tls_service_key = region_strdup(cfg_parser->opt->region, $2); } 425 | VAR_TLS_SERVICE_OCSP STRING 426 { cfg_parser->opt->tls_service_ocsp = region_strdup(cfg_parser->opt->region, $2); } 427 | VAR_TLS_SERVICE_PEM STRING 428 { cfg_parser->opt->tls_service_pem = region_strdup(cfg_parser->opt->region, $2); } 429 | VAR_TLS_PORT number 430 { 431 /* port number, stored as string */ 432 char buf[16]; 433 (void)snprintf(buf, sizeof(buf), "%lld", $2); 434 cfg_parser->opt->tls_port = region_strdup(cfg_parser->opt->region, buf); 435 } 436 | VAR_CPU_AFFINITY cpus 437 { 438 cfg_parser->opt->cpu_affinity = $2; 439 } 440 | service_cpu_affinity number 441 { 442 if($2 < 0) { 443 yyerror("expected a non-negative number"); 444 YYABORT; 445 } else { 446 struct cpu_map_option *opt, *tail; 447 448 opt = cfg_parser->opt->service_cpu_affinity; 449 while(opt && opt->service != $1) { opt = opt->next; } 450 451 if(opt) { 452 opt->cpu = $2; 453 } else { 454 opt = region_alloc_zero(cfg_parser->opt->region, sizeof(*opt)); 455 opt->service = (int)$1; 456 opt->cpu = (int)$2; 457 458 tail = cfg_parser->opt->service_cpu_affinity; 459 if(tail) { 460 while(tail->next) { tail = tail->next; } 461 tail->next = opt; 462 } else { 463 cfg_parser->opt->service_cpu_affinity = opt; 464 } 465 } 466 } 467 } 468 ; 469 470 socket_options: 471 | socket_options socket_option ; 472 473 socket_option: 474 VAR_SERVERS STRING 475 { 476 char *tok, *ptr, *str; 477 struct range_option *servers = NULL; 478 long long first, last; 479 480 /* user may specify "0 1", "0" "1", 0 1 or a combination thereof */ 481 for(str = $2; (tok = strtok_r(str, " \t", &ptr)); str = NULL) { 482 struct range_option *opt = 483 region_alloc(cfg_parser->opt->region, sizeof(*opt)); 484 first = last = 0; 485 if(!parse_range(tok, &first, &last)) { 486 yyerror("invalid server range '%s'", tok); 487 YYABORT; 488 } 489 assert(first >= 0); 490 assert(last >= 0); 491 opt->next = NULL; 492 opt->first = (int)first; 493 opt->last = (int)last; 494 if(servers) { 495 servers = servers->next = opt; 496 } else { 497 servers = cfg_parser->ip->servers = opt; 498 } 499 } 500 } 501 | VAR_BINDTODEVICE boolean 502 { cfg_parser->ip->dev = $2; } 503 | VAR_SETFIB number 504 { cfg_parser->ip->fib = $2; } 505 ; 506 507 cpus: 508 { $$ = NULL; } 509 | cpus STRING 510 { 511 char *tok, *ptr, *str; 512 struct cpu_option *tail; 513 long long cpu; 514 515 str = $2; 516 $$ = tail = $1; 517 if(tail) { 518 while(tail->next) { tail = tail->next; } 519 } 520 521 /* Users may specify "0 1", "0" "1", 0 1 or a combination thereof. */ 522 for(str = $2; (tok = strtok_r(str, " \t", &ptr)); str = NULL) { 523 struct cpu_option *opt = 524 region_alloc(cfg_parser->opt->region, sizeof(*opt)); 525 cpu = 0; 526 if(!parse_number(tok, &cpu) || opt->cpu < 0) { 527 yyerror("expected a positive number"); 528 YYABORT; 529 } 530 assert(cpu >=0); 531 opt->cpu = (int)cpu; 532 if(tail) { 533 tail->next = opt; 534 tail = opt; 535 } else { 536 $$ = tail = opt; 537 } 538 } 539 } 540 ; 541 542 service_cpu_affinity: 543 VAR_XFRD_CPU_AFFINITY 544 { $$ = -1; } 545 | VAR_SERVER_CPU_AFFINITY 546 { 547 if($1 <= 0) { 548 yyerror("invalid server identifier"); 549 YYABORT; 550 } 551 $$ = $1; 552 } 553 ; 554 555 dnstap: 556 VAR_DNSTAP dnstap_block ; 557 558 dnstap_block: 559 dnstap_block dnstap_option | ; 560 561 dnstap_option: 562 VAR_DNSTAP_ENABLE boolean 563 { cfg_parser->opt->dnstap_enable = $2; } 564 | VAR_DNSTAP_SOCKET_PATH STRING 565 { cfg_parser->opt->dnstap_socket_path = region_strdup(cfg_parser->opt->region, $2); } 566 | VAR_DNSTAP_SEND_IDENTITY boolean 567 { cfg_parser->opt->dnstap_send_identity = $2; } 568 | VAR_DNSTAP_SEND_VERSION boolean 569 { cfg_parser->opt->dnstap_send_version = $2; } 570 | VAR_DNSTAP_IDENTITY STRING 571 { cfg_parser->opt->dnstap_identity = region_strdup(cfg_parser->opt->region, $2); } 572 | VAR_DNSTAP_VERSION STRING 573 { cfg_parser->opt->dnstap_version = region_strdup(cfg_parser->opt->region, $2); } 574 | VAR_DNSTAP_LOG_AUTH_QUERY_MESSAGES boolean 575 { cfg_parser->opt->dnstap_log_auth_query_messages = $2; } 576 | VAR_DNSTAP_LOG_AUTH_RESPONSE_MESSAGES boolean 577 { cfg_parser->opt->dnstap_log_auth_response_messages = $2; } 578 ; 579 580 remote_control: 581 VAR_REMOTE_CONTROL remote_control_block ; 582 583 remote_control_block: 584 remote_control_block remote_control_option | ; 585 586 remote_control_option: 587 VAR_CONTROL_ENABLE boolean 588 { cfg_parser->opt->control_enable = $2; } 589 | VAR_CONTROL_INTERFACE ip_address 590 { 591 struct ip_address_option *ip = cfg_parser->opt->control_interface; 592 if(ip == NULL) { 593 cfg_parser->opt->control_interface = $2; 594 } else { 595 while(ip->next != NULL) { ip = ip->next; } 596 ip->next = $2; 597 } 598 } 599 | VAR_CONTROL_PORT number 600 { 601 if($2 == 0) { 602 yyerror("control port number expected"); 603 } else { 604 cfg_parser->opt->control_port = (int)$2; 605 } 606 } 607 | VAR_SERVER_KEY_FILE STRING 608 { cfg_parser->opt->server_key_file = region_strdup(cfg_parser->opt->region, $2); } 609 | VAR_SERVER_CERT_FILE STRING 610 { cfg_parser->opt->server_cert_file = region_strdup(cfg_parser->opt->region, $2); } 611 | VAR_CONTROL_KEY_FILE STRING 612 { cfg_parser->opt->control_key_file = region_strdup(cfg_parser->opt->region, $2); } 613 | VAR_CONTROL_CERT_FILE STRING 614 { cfg_parser->opt->control_cert_file = region_strdup(cfg_parser->opt->region, $2); } 615 ; 616 617 key: 618 VAR_KEY 619 { 620 key_options_type *key = key_options_create(cfg_parser->opt->region); 621 key->algorithm = region_strdup(cfg_parser->opt->region, "sha256"); 622 assert(cfg_parser->key == NULL); 623 cfg_parser->key = key; 624 } 625 key_block 626 { 627 struct key_options *key = cfg_parser->key; 628 if(key->name == NULL) { 629 yyerror("tsig key has no name"); 630 } else if(key->algorithm == NULL) { 631 yyerror("tsig key %s has no algorithm", key->name); 632 } else if(key->secret == NULL) { 633 yyerror("tsig key %s has no secret blob", key->name); 634 } else if(key_options_find(cfg_parser->opt, key->name)) { 635 yyerror("duplicate tsig key %s", key->name); 636 } else { 637 key_options_insert(cfg_parser->opt, key); 638 cfg_parser->key = NULL; 639 } 640 } ; 641 642 key_block: 643 key_block key_option | ; 644 645 key_option: 646 VAR_NAME STRING 647 { 648 dname_type *dname; 649 650 dname = (dname_type *)dname_parse(cfg_parser->opt->region, $2); 651 cfg_parser->key->name = region_strdup(cfg_parser->opt->region, $2); 652 if(dname == NULL) { 653 yyerror("bad tsig key name %s", $2); 654 } else { 655 region_recycle(cfg_parser->opt->region, dname, dname_total_size(dname)); 656 } 657 } 658 | VAR_ALGORITHM STRING 659 { 660 if(tsig_get_algorithm_by_name($2) == NULL) { 661 yyerror("bad tsig key algorithm %s", $2); 662 } else { 663 cfg_parser->key->algorithm = region_strdup(cfg_parser->opt->region, $2); 664 } 665 } 666 | VAR_SECRET STRING 667 { 668 uint8_t data[16384]; 669 int size; 670 671 cfg_parser->key->secret = region_strdup(cfg_parser->opt->region, $2); 672 size = __b64_pton($2, data, sizeof(data)); 673 if(size == -1) { 674 yyerror("cannot base64 decode tsig secret %s", 675 cfg_parser->key->name? 676 cfg_parser->key->name:""); 677 } else if(size != 0) { 678 memset(data, 0xdd, size); /* wipe secret */ 679 } 680 } ; 681 682 683 zone: 684 VAR_ZONE 685 { 686 assert(cfg_parser->pattern == NULL); 687 assert(cfg_parser->zone == NULL); 688 cfg_parser->zone = zone_options_create(cfg_parser->opt->region); 689 cfg_parser->zone->part_of_config = 1; 690 cfg_parser->zone->pattern = cfg_parser->pattern = 691 pattern_options_create(cfg_parser->opt->region); 692 cfg_parser->zone->pattern->implicit = 1; 693 } 694 zone_block 695 { 696 assert(cfg_parser->zone != NULL); 697 if(cfg_parser->zone->name == NULL) { 698 yyerror("zone has no name"); 699 } else if(!nsd_options_insert_zone(cfg_parser->opt, cfg_parser->zone)) { 700 yyerror("duplicate zone %s", cfg_parser->zone->name); 701 } else if(!nsd_options_insert_pattern(cfg_parser->opt, cfg_parser->zone->pattern)) { 702 yyerror("duplicate pattern %s", cfg_parser->zone->pattern->pname); 703 } 704 cfg_parser->pattern = NULL; 705 cfg_parser->zone = NULL; 706 } ; 707 708 zone_block: 709 zone_block zone_option | ; 710 711 zone_option: 712 VAR_NAME STRING 713 { 714 const char *marker = PATTERN_IMPLICIT_MARKER; 715 char *pname = region_alloc(cfg_parser->opt->region, strlen($2) + strlen(marker) + 1); 716 memmove(pname, marker, strlen(marker)); 717 memmove(pname + strlen(marker), $2, strlen($2) + 1); 718 cfg_parser->zone->pattern->pname = pname; 719 cfg_parser->zone->name = region_strdup(cfg_parser->opt->region, $2); 720 if(pattern_options_find(cfg_parser->opt, pname)) { 721 yyerror("zone %s cannot be created because implicit pattern %s " 722 "already exists", $2, pname); 723 } 724 } 725 | pattern_or_zone_option ; 726 727 pattern: 728 VAR_PATTERN 729 { 730 assert(cfg_parser->pattern == NULL); 731 cfg_parser->pattern = pattern_options_create(cfg_parser->opt->region); 732 } 733 pattern_block 734 { 735 pattern_options_type *pattern = cfg_parser->pattern; 736 if(pattern->pname == NULL) { 737 yyerror("pattern has no name"); 738 } else if(!nsd_options_insert_pattern(cfg_parser->opt, pattern)) { 739 yyerror("duplicate pattern %s", pattern->pname); 740 } 741 cfg_parser->pattern = NULL; 742 } ; 743 744 pattern_block: 745 pattern_block pattern_option | ; 746 747 pattern_option: 748 VAR_NAME STRING 749 { 750 if(strchr($2, ' ')) { 751 yyerror("space is not allowed in pattern name: '%s'", $2); 752 } 753 cfg_parser->pattern->pname = region_strdup(cfg_parser->opt->region, $2); 754 } 755 | pattern_or_zone_option ; 756 757 pattern_or_zone_option: 758 VAR_RRL_WHITELIST STRING 759 { 760 #ifdef RATELIMIT 761 cfg_parser->pattern->rrl_whitelist |= rrlstr2type($2); 762 #endif 763 } 764 | VAR_ZONEFILE STRING 765 { cfg_parser->pattern->zonefile = region_strdup(cfg_parser->opt->region, $2); } 766 | VAR_ZONESTATS STRING 767 { cfg_parser->pattern->zonestats = region_strdup(cfg_parser->opt->region, $2); } 768 | VAR_SIZE_LIMIT_XFR number 769 { 770 if($2 > 0) { 771 cfg_parser->pattern->size_limit_xfr = (int)$2; 772 } else { 773 yyerror("expected a number greater than zero"); 774 } 775 } 776 | VAR_MULTI_MASTER_CHECK boolean 777 { cfg_parser->pattern->multi_master_check = (int)$2; } 778 | VAR_INCLUDE_PATTERN STRING 779 { config_apply_pattern(cfg_parser->pattern, $2); } 780 | VAR_REQUEST_XFR STRING STRING 781 { 782 acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, $3); 783 if(acl->blocked) 784 yyerror("blocked address used for request-xfr"); 785 if(acl->rangetype != acl_range_single) 786 yyerror("address range used for request-xfr"); 787 append_acl(&cfg_parser->pattern->request_xfr, acl); 788 } 789 | VAR_REQUEST_XFR VAR_AXFR STRING STRING 790 { 791 acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $3, $4); 792 acl->use_axfr_only = 1; 793 if(acl->blocked) 794 yyerror("blocked address used for request-xfr"); 795 if(acl->rangetype != acl_range_single) 796 yyerror("address range used for request-xfr"); 797 append_acl(&cfg_parser->pattern->request_xfr, acl); 798 } 799 | VAR_REQUEST_XFR VAR_UDP STRING STRING 800 { 801 acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $3, $4); 802 acl->allow_udp = 1; 803 if(acl->blocked) 804 yyerror("blocked address used for request-xfr"); 805 if(acl->rangetype != acl_range_single) 806 yyerror("address range used for request-xfr"); 807 append_acl(&cfg_parser->pattern->request_xfr, acl); 808 } 809 | VAR_ALLOW_NOTIFY STRING STRING 810 { 811 acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, $3); 812 append_acl(&cfg_parser->pattern->allow_notify, acl); 813 } 814 | VAR_NOTIFY STRING STRING 815 { 816 acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, $3); 817 if(acl->blocked) 818 yyerror("blocked address used for notify"); 819 if(acl->rangetype != acl_range_single) 820 yyerror("address range used for notify"); 821 append_acl(&cfg_parser->pattern->notify, acl); 822 } 823 | VAR_PROVIDE_XFR STRING STRING 824 { 825 acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, $3); 826 append_acl(&cfg_parser->pattern->provide_xfr, acl); 827 } 828 | VAR_OUTGOING_INTERFACE STRING 829 { 830 acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, "NOKEY"); 831 append_acl(&cfg_parser->pattern->outgoing_interface, acl); 832 } 833 | VAR_ALLOW_AXFR_FALLBACK boolean 834 { 835 cfg_parser->pattern->allow_axfr_fallback = $2; 836 cfg_parser->pattern->allow_axfr_fallback_is_default = 0; 837 } 838 | VAR_NOTIFY_RETRY number 839 { 840 cfg_parser->pattern->notify_retry = $2; 841 cfg_parser->pattern->notify_retry_is_default = 0; 842 } 843 | VAR_MAX_REFRESH_TIME number 844 { 845 cfg_parser->pattern->max_refresh_time = $2; 846 cfg_parser->pattern->max_refresh_time_is_default = 0; 847 } 848 | VAR_MIN_REFRESH_TIME number 849 { 850 cfg_parser->pattern->min_refresh_time = $2; 851 cfg_parser->pattern->min_refresh_time_is_default = 0; 852 } 853 | VAR_MAX_RETRY_TIME number 854 { 855 cfg_parser->pattern->max_retry_time = $2; 856 cfg_parser->pattern->max_retry_time_is_default = 0; 857 } 858 | VAR_MIN_RETRY_TIME number 859 { 860 cfg_parser->pattern->min_retry_time = $2; 861 cfg_parser->pattern->min_retry_time_is_default = 0; 862 } 863 | VAR_MIN_EXPIRE_TIME STRING 864 { 865 long long num; 866 uint8_t expr; 867 868 if (!parse_expire_expr($2, &num, &expr)) { 869 yyerror("expected an expire time in seconds or \"refresh+retry+1\""); 870 YYABORT; /* trigger a parser error */ 871 } 872 cfg_parser->pattern->min_expire_time = num; 873 cfg_parser->pattern->min_expire_time_expr = expr; 874 }; 875 876 ip_address: 877 STRING 878 { 879 struct ip_address_option *ip = region_alloc_zero( 880 cfg_parser->opt->region, sizeof(*ip)); 881 ip->address = region_strdup(cfg_parser->opt->region, $1); 882 ip->fib = -1; 883 $$ = ip; 884 } ; 885 886 number: 887 STRING 888 { 889 if(!parse_number($1, &$$)) { 890 yyerror("expected a number"); 891 YYABORT; /* trigger a parser error */ 892 } 893 } ; 894 895 boolean: 896 STRING 897 { 898 if(!parse_boolean($1, &$$)) { 899 yyerror("expected yes or no"); 900 YYABORT; /* trigger a parser error */ 901 } 902 } ; 903 904 %% 905 906 static void 907 append_acl(struct acl_options **list, struct acl_options *acl) 908 { 909 assert(list != NULL); 910 911 if(*list == NULL) { 912 *list = acl; 913 } else { 914 struct acl_options *tail = *list; 915 while(tail->next != NULL) 916 tail = tail->next; 917 tail->next = acl; 918 } 919 } 920 921 static int 922 parse_boolean(const char *str, int *bln) 923 { 924 if(strcmp(str, "yes") == 0) { 925 *bln = 1; 926 } else if(strcmp(str, "no") == 0) { 927 *bln = 0; 928 } else { 929 return 0; 930 } 931 932 return 1; 933 } 934 935 static int 936 parse_expire_expr(const char *str, long long *num, uint8_t *expr) 937 { 938 if(parse_number(str, num)) { 939 *expr = EXPIRE_TIME_HAS_VALUE; 940 return 1; 941 } 942 if(strcmp(str, REFRESHPLUSRETRYPLUS1_STR) == 0) { 943 *num = 0; 944 *expr = REFRESHPLUSRETRYPLUS1; 945 return 1; 946 } 947 return 0; 948 } 949 950 static int 951 parse_number(const char *str, long long *num) 952 { 953 /* ensure string consists entirely of digits */ 954 size_t pos = 0; 955 while(str[pos] >= '0' && str[pos] <= '9') { 956 pos++; 957 } 958 959 if(pos != 0 && str[pos] == '\0') { 960 *num = strtoll(str, NULL, 10); 961 return 1; 962 } 963 964 return 0; 965 } 966 967 static int 968 parse_range(const char *str, long long *low, long long *high) 969 { 970 const char *ptr = str; 971 long long num[2]; 972 973 /* require range to begin with a number */ 974 if(*ptr < '0' || *ptr > '9') { 975 return 0; 976 } 977 978 num[0] = strtoll(ptr, (char **)&ptr, 10); 979 980 /* require number to be followed by nothing at all or a dash */ 981 if(*ptr == '\0') { 982 *low = num[0]; 983 *high = num[0]; 984 return 1; 985 } else if(*ptr != '-') { 986 return 0; 987 } 988 989 ++ptr; 990 /* require dash to be followed by a number */ 991 if(*ptr < '0' || *ptr > '9') { 992 return 0; 993 } 994 995 num[1] = strtoll(ptr, (char **)&ptr, 10); 996 997 /* require number to be followed by nothing at all */ 998 if(*ptr == '\0') { 999 if(num[0] < num[1]) { 1000 *low = num[0]; 1001 *high = num[1]; 1002 } else { 1003 *low = num[1]; 1004 *high = num[0]; 1005 } 1006 return 1; 1007 } 1008 1009 return 0; 1010 } 1011