1 /* 2 * configparser.y -- yacc grammar for NSD configuration files 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 %{ 11 #include "config.h" 12 13 #include <stdarg.h> 14 #include <stdio.h> 15 #include <string.h> 16 #include <stdlib.h> 17 #include <assert.h> 18 19 #include "options.h" 20 #include "util.h" 21 #include "dname.h" 22 #include "tsig.h" 23 #include "rrl.h" 24 #include "configyyrename.h" 25 int c_lex(void); 26 void c_error(const char *message); 27 28 #ifdef __cplusplus 29 extern "C" 30 #endif /* __cplusplus */ 31 32 /* these need to be global, otherwise they cannot be used inside yacc */ 33 extern config_parser_state_t* cfg_parser; 34 35 #if 0 36 #define OUTYY(s) printf s /* used ONLY when debugging */ 37 #else 38 #define OUTYY(s) 39 #endif 40 41 %} 42 %union { 43 char* str; 44 } 45 46 %token SPACE LETTER NEWLINE COMMENT COLON ANY ZONESTR 47 %token <str> STRING 48 %token VAR_SERVER VAR_NAME VAR_IP_ADDRESS VAR_IP_TRANSPARENT VAR_DEBUG_MODE 49 %token VAR_IP4_ONLY VAR_IP6_ONLY VAR_DATABASE VAR_IDENTITY VAR_NSID VAR_LOGFILE 50 %token VAR_SERVER_COUNT VAR_TCP_COUNT VAR_PIDFILE VAR_PORT VAR_STATISTICS 51 %token VAR_CHROOT VAR_USERNAME VAR_ZONESDIR VAR_XFRDFILE VAR_DIFFFILE 52 %token VAR_XFRD_RELOAD_TIMEOUT VAR_TCP_QUERY_COUNT VAR_TCP_TIMEOUT 53 %token VAR_IPV4_EDNS_SIZE VAR_IPV6_EDNS_SIZE VAR_DO_IP4 VAR_DO_IP6 54 %token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS VAR_IP_FREEBIND 55 %token VAR_ZONEFILE 56 %token VAR_ZONE 57 %token VAR_ALLOW_NOTIFY VAR_REQUEST_XFR VAR_NOTIFY VAR_PROVIDE_XFR VAR_SIZE_LIMIT_XFR 58 %token VAR_NOTIFY_RETRY VAR_OUTGOING_INTERFACE VAR_ALLOW_AXFR_FALLBACK 59 %token VAR_KEY 60 %token VAR_ALGORITHM VAR_SECRET 61 %token VAR_AXFR VAR_UDP 62 %token VAR_VERBOSITY VAR_HIDE_VERSION 63 %token VAR_PATTERN VAR_INCLUDEPATTERN VAR_ZONELISTFILE 64 %token VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE VAR_CONTROL_INTERFACE 65 %token VAR_CONTROL_PORT VAR_SERVER_KEY_FILE VAR_SERVER_CERT_FILE 66 %token VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE VAR_XFRDIR 67 %token VAR_RRL_SIZE VAR_RRL_RATELIMIT VAR_RRL_SLIP 68 %token VAR_RRL_IPV4_PREFIX_LENGTH VAR_RRL_IPV6_PREFIX_LENGTH 69 %token VAR_RRL_WHITELIST_RATELIMIT VAR_RRL_WHITELIST 70 %token VAR_ZONEFILES_CHECK VAR_ZONEFILES_WRITE VAR_LOG_TIME_ASCII 71 %token VAR_ROUND_ROBIN VAR_ZONESTATS VAR_REUSEPORT VAR_VERSION 72 %token VAR_MAX_REFRESH_TIME VAR_MIN_REFRESH_TIME 73 %token VAR_MAX_RETRY_TIME VAR_MIN_RETRY_TIME 74 75 %% 76 toplevelvars: /* empty */ | toplevelvars toplevelvar ; 77 toplevelvar: serverstart contents_server | zonestart contents_zone | 78 keystart contents_key | patternstart contents_pattern | 79 rcstart contents_rc; 80 81 /* server: declaration */ 82 serverstart: VAR_SERVER 83 { OUTYY(("\nP(server:)\n")); 84 if(cfg_parser->server_settings_seen) { 85 yyerror("duplicate server: element."); 86 } 87 cfg_parser->server_settings_seen = 1; 88 } 89 ; 90 contents_server: contents_server content_server | ; 91 content_server: server_ip_address | server_ip_transparent | server_debug_mode | server_ip4_only | 92 server_ip6_only | server_database | server_identity | server_nsid | server_logfile | 93 server_server_count | server_tcp_count | server_pidfile | server_port | 94 server_statistics | server_chroot | server_username | server_zonesdir | 95 server_difffile | server_xfrdfile | server_xfrd_reload_timeout | 96 server_tcp_query_count | server_tcp_timeout | server_ipv4_edns_size | 97 server_ipv6_edns_size | server_verbosity | server_hide_version | 98 server_zonelistfile | server_xfrdir | 99 server_tcp_mss | server_outgoing_tcp_mss | 100 server_rrl_size | server_rrl_ratelimit | server_rrl_slip | 101 server_rrl_ipv4_prefix_length | server_rrl_ipv6_prefix_length | server_rrl_whitelist_ratelimit | 102 server_zonefiles_check | server_do_ip4 | server_do_ip6 | 103 server_zonefiles_write | server_log_time_ascii | server_round_robin | 104 server_reuseport | server_version | server_ip_freebind; 105 server_ip_address: VAR_IP_ADDRESS STRING 106 { 107 OUTYY(("P(server_ip_address:%s)\n", $2)); 108 if(cfg_parser->current_ip_address_option) { 109 cfg_parser->current_ip_address_option->next = 110 (ip_address_option_t*)region_alloc( 111 cfg_parser->opt->region, sizeof(ip_address_option_t)); 112 cfg_parser->current_ip_address_option = 113 cfg_parser->current_ip_address_option->next; 114 cfg_parser->current_ip_address_option->next=0; 115 } else { 116 cfg_parser->current_ip_address_option = 117 (ip_address_option_t*)region_alloc( 118 cfg_parser->opt->region, sizeof(ip_address_option_t)); 119 cfg_parser->current_ip_address_option->next=0; 120 cfg_parser->opt->ip_addresses = cfg_parser->current_ip_address_option; 121 } 122 123 cfg_parser->current_ip_address_option->address = 124 region_strdup(cfg_parser->opt->region, $2); 125 } 126 ; 127 server_ip_transparent: VAR_IP_TRANSPARENT STRING 128 { 129 OUTYY(("P(server_ip_transparent:%s)\n", $2)); 130 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 131 yyerror("expected yes or no."); 132 else cfg_parser->opt->ip_transparent = (strcmp($2, "yes")==0); 133 } 134 ; 135 server_ip_freebind: VAR_IP_FREEBIND STRING 136 { 137 OUTYY(("P(server_ip_freebind:%s)\n", $2)); 138 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 139 yyerror("expected yes or no."); 140 else cfg_parser->opt->ip_freebind = (strcmp($2, "yes")==0); 141 } 142 ; 143 server_debug_mode: VAR_DEBUG_MODE STRING 144 { 145 OUTYY(("P(server_debug_mode:%s)\n", $2)); 146 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 147 yyerror("expected yes or no."); 148 else cfg_parser->opt->debug_mode = (strcmp($2, "yes")==0); 149 } 150 ; 151 server_verbosity: VAR_VERBOSITY STRING 152 { 153 OUTYY(("P(server_verbosity:%s)\n", $2)); 154 if(atoi($2) == 0 && strcmp($2, "0") != 0) 155 yyerror("number expected"); 156 else cfg_parser->opt->verbosity = atoi($2); 157 } 158 ; 159 server_hide_version: VAR_HIDE_VERSION STRING 160 { 161 OUTYY(("P(server_hide_version:%s)\n", $2)); 162 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 163 yyerror("expected yes or no."); 164 else cfg_parser->opt->hide_version = (strcmp($2, "yes")==0); 165 } 166 ; 167 server_ip4_only: VAR_IP4_ONLY STRING 168 { 169 /* for backwards compatibility in config file with NSD3 */ 170 OUTYY(("P(server_ip4_only:%s)\n", $2)); 171 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 172 yyerror("expected yes or no."); 173 else if(strcmp($2, "yes")==0) { 174 cfg_parser->opt->do_ip4 = 1; 175 cfg_parser->opt->do_ip6 = 0; 176 } 177 } 178 ; 179 server_ip6_only: VAR_IP6_ONLY STRING 180 { 181 /* for backwards compatibility in config file with NSD3 */ 182 OUTYY(("P(server_ip6_only:%s)\n", $2)); 183 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 184 yyerror("expected yes or no."); 185 else if(strcmp($2, "yes")==0) { 186 cfg_parser->opt->do_ip6 = 1; 187 cfg_parser->opt->do_ip4 = 0; 188 } 189 } 190 ; 191 server_do_ip4: VAR_DO_IP4 STRING 192 { 193 OUTYY(("P(server_do_ip4:%s)\n", $2)); 194 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 195 yyerror("expected yes or no."); 196 else cfg_parser->opt->do_ip4 = (strcmp($2, "yes")==0); 197 } 198 ; 199 server_do_ip6: VAR_DO_IP6 STRING 200 { 201 OUTYY(("P(server_do_ip6:%s)\n", $2)); 202 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 203 yyerror("expected yes or no."); 204 else cfg_parser->opt->do_ip6 = (strcmp($2, "yes")==0); 205 } 206 ; 207 server_reuseport: VAR_REUSEPORT STRING 208 { 209 OUTYY(("P(server_reuseport:%s)\n", $2)); 210 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 211 yyerror("expected yes or no."); 212 else cfg_parser->opt->reuseport = (strcmp($2, "yes")==0); 213 } 214 ; 215 server_database: VAR_DATABASE STRING 216 { 217 OUTYY(("P(server_database:%s)\n", $2)); 218 cfg_parser->opt->database = region_strdup(cfg_parser->opt->region, $2); 219 if(cfg_parser->opt->database[0] == 0 && 220 cfg_parser->opt->zonefiles_write == 0) 221 cfg_parser->opt->zonefiles_write = ZONEFILES_WRITE_INTERVAL; 222 } 223 ; 224 server_identity: VAR_IDENTITY STRING 225 { 226 OUTYY(("P(server_identity:%s)\n", $2)); 227 cfg_parser->opt->identity = region_strdup(cfg_parser->opt->region, $2); 228 } 229 ; 230 server_version: VAR_VERSION STRING 231 { 232 OUTYY(("P(server_version:%s)\n", $2)); 233 cfg_parser->opt->version = region_strdup(cfg_parser->opt->region, $2); 234 } 235 ; 236 server_nsid: VAR_NSID STRING 237 { 238 unsigned char* nsid = 0; 239 size_t nsid_len = 0; 240 241 OUTYY(("P(server_nsid:%s)\n", $2)); 242 243 if (strncasecmp($2, "ascii_", 6) == 0) { 244 nsid_len = strlen($2+6); 245 if(nsid_len < 65535) { 246 cfg_parser->opt->nsid = region_alloc(cfg_parser->opt->region, nsid_len*2+1); 247 hex_ntop((uint8_t*)$2+6, nsid_len, (char*)cfg_parser->opt->nsid, nsid_len*2+1); 248 } else 249 yyerror("NSID too long"); 250 } else if (strlen($2) % 2 != 0) { 251 yyerror("the NSID must be a hex string of an even length."); 252 } else { 253 nsid_len = strlen($2) / 2; 254 if(nsid_len < 65535) { 255 nsid = xalloc(nsid_len); 256 if (hex_pton($2, nsid, nsid_len) == -1) 257 yyerror("hex string cannot be parsed in NSID."); 258 else 259 cfg_parser->opt->nsid = region_strdup(cfg_parser->opt->region, $2); 260 free(nsid); 261 } else 262 yyerror("NSID too long"); 263 } 264 } 265 ; 266 server_logfile: VAR_LOGFILE STRING 267 { 268 OUTYY(("P(server_logfile:%s)\n", $2)); 269 cfg_parser->opt->logfile = region_strdup(cfg_parser->opt->region, $2); 270 } 271 ; 272 server_log_time_ascii: VAR_LOG_TIME_ASCII STRING 273 { 274 OUTYY(("P(server_log_time_ascii:%s)\n", $2)); 275 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 276 yyerror("expected yes or no."); 277 else { 278 cfg_parser->opt->log_time_ascii = (strcmp($2, "yes")==0); 279 log_time_asc = cfg_parser->opt->log_time_ascii; 280 } 281 } 282 ; 283 server_round_robin: VAR_ROUND_ROBIN STRING 284 { 285 OUTYY(("P(server_round_robin:%s)\n", $2)); 286 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 287 yyerror("expected yes or no."); 288 else { 289 cfg_parser->opt->round_robin = (strcmp($2, "yes")==0); 290 round_robin = cfg_parser->opt->round_robin; 291 } 292 } 293 ; 294 server_server_count: VAR_SERVER_COUNT STRING 295 { 296 OUTYY(("P(server_server_count:%s)\n", $2)); 297 if(atoi($2) <= 0) 298 yyerror("number greater than zero expected"); 299 else cfg_parser->opt->server_count = atoi($2); 300 } 301 ; 302 server_tcp_count: VAR_TCP_COUNT STRING 303 { 304 OUTYY(("P(server_tcp_count:%s)\n", $2)); 305 if(atoi($2) <= 0) 306 yyerror("number greater than zero expected"); 307 else cfg_parser->opt->tcp_count = atoi($2); 308 } 309 ; 310 server_pidfile: VAR_PIDFILE STRING 311 { 312 OUTYY(("P(server_pidfile:%s)\n", $2)); 313 cfg_parser->opt->pidfile = region_strdup(cfg_parser->opt->region, $2); 314 } 315 ; 316 server_port: VAR_PORT STRING 317 { 318 OUTYY(("P(server_port:%s)\n", $2)); 319 cfg_parser->opt->port = region_strdup(cfg_parser->opt->region, $2); 320 } 321 ; 322 server_statistics: VAR_STATISTICS STRING 323 { 324 OUTYY(("P(server_statistics:%s)\n", $2)); 325 if(atoi($2) == 0 && strcmp($2, "0") != 0) 326 yyerror("number expected"); 327 else cfg_parser->opt->statistics = atoi($2); 328 } 329 ; 330 server_chroot: VAR_CHROOT STRING 331 { 332 OUTYY(("P(server_chroot:%s)\n", $2)); 333 cfg_parser->opt->chroot = region_strdup(cfg_parser->opt->region, $2); 334 } 335 ; 336 server_username: VAR_USERNAME STRING 337 { 338 OUTYY(("P(server_username:%s)\n", $2)); 339 cfg_parser->opt->username = region_strdup(cfg_parser->opt->region, $2); 340 } 341 ; 342 server_zonesdir: VAR_ZONESDIR STRING 343 { 344 OUTYY(("P(server_zonesdir:%s)\n", $2)); 345 cfg_parser->opt->zonesdir = region_strdup(cfg_parser->opt->region, $2); 346 } 347 ; 348 server_zonelistfile: VAR_ZONELISTFILE STRING 349 { 350 OUTYY(("P(server_zonelistfile:%s)\n", $2)); 351 cfg_parser->opt->zonelistfile = region_strdup(cfg_parser->opt->region, $2); 352 } 353 ; 354 server_xfrdir: VAR_XFRDIR STRING 355 { 356 OUTYY(("P(server_xfrdir:%s)\n", $2)); 357 cfg_parser->opt->xfrdir = region_strdup(cfg_parser->opt->region, $2); 358 } 359 ; 360 server_difffile: VAR_DIFFFILE STRING 361 { 362 OUTYY(("P(server_difffile:%s)\n", $2)); 363 /* ignore the value for backwards compatibility in config file*/ 364 } 365 ; 366 server_xfrdfile: VAR_XFRDFILE STRING 367 { 368 OUTYY(("P(server_xfrdfile:%s)\n", $2)); 369 cfg_parser->opt->xfrdfile = region_strdup(cfg_parser->opt->region, $2); 370 } 371 ; 372 server_xfrd_reload_timeout: VAR_XFRD_RELOAD_TIMEOUT STRING 373 { 374 OUTYY(("P(server_xfrd_reload_timeout:%s)\n", $2)); 375 if(atoi($2) == 0 && strcmp($2, "0") != 0) 376 yyerror("number expected"); 377 cfg_parser->opt->xfrd_reload_timeout = atoi($2); 378 } 379 ; 380 server_tcp_query_count: VAR_TCP_QUERY_COUNT STRING 381 { 382 OUTYY(("P(server_tcp_query_count:%s)\n", $2)); 383 if(atoi($2) == 0 && strcmp($2, "0") != 0) 384 yyerror("number expected"); 385 cfg_parser->opt->tcp_query_count = atoi($2); 386 } 387 ; 388 server_tcp_timeout: VAR_TCP_TIMEOUT STRING 389 { 390 OUTYY(("P(server_tcp_timeout:%s)\n", $2)); 391 if(atoi($2) == 0 && strcmp($2, "0") != 0) 392 yyerror("number expected"); 393 cfg_parser->opt->tcp_timeout = atoi($2); 394 } 395 ; 396 server_tcp_mss: VAR_TCP_MSS STRING 397 { 398 OUTYY(("P(server_tcp_mss:%s)\n", $2)); 399 if(atoi($2) == 0 && strcmp($2, "0") != 0) 400 yyerror("number expected"); 401 cfg_parser->opt->tcp_mss = atoi($2); 402 } 403 ; 404 server_outgoing_tcp_mss: VAR_OUTGOING_TCP_MSS STRING 405 { 406 OUTYY(("P(server_outgoing_tcp_mss:%s)\n", $2)); 407 if(atoi($2) == 0 && strcmp($2, "0") != 0) 408 yyerror("number expected"); 409 cfg_parser->opt->outgoing_tcp_mss = atoi($2); 410 } 411 ; 412 server_ipv4_edns_size: VAR_IPV4_EDNS_SIZE STRING 413 { 414 OUTYY(("P(server_ipv4_edns_size:%s)\n", $2)); 415 if(atoi($2) == 0 && strcmp($2, "0") != 0) 416 yyerror("number expected"); 417 cfg_parser->opt->ipv4_edns_size = atoi($2); 418 } 419 ; 420 server_ipv6_edns_size: VAR_IPV6_EDNS_SIZE STRING 421 { 422 OUTYY(("P(server_ipv6_edns_size:%s)\n", $2)); 423 if(atoi($2) == 0 && strcmp($2, "0") != 0) 424 yyerror("number expected"); 425 cfg_parser->opt->ipv6_edns_size = atoi($2); 426 } 427 ; 428 server_rrl_size: VAR_RRL_SIZE STRING 429 { 430 OUTYY(("P(server_rrl_size:%s)\n", $2)); 431 #ifdef RATELIMIT 432 if(atoi($2) <= 0) 433 yyerror("number greater than zero expected"); 434 cfg_parser->opt->rrl_size = atoi($2); 435 #endif 436 } 437 ; 438 server_rrl_ratelimit: VAR_RRL_RATELIMIT STRING 439 { 440 OUTYY(("P(server_rrl_ratelimit:%s)\n", $2)); 441 #ifdef RATELIMIT 442 cfg_parser->opt->rrl_ratelimit = atoi($2); 443 #endif 444 } 445 ; 446 server_rrl_slip: VAR_RRL_SLIP STRING 447 { 448 OUTYY(("P(server_rrl_slip:%s)\n", $2)); 449 #ifdef RATELIMIT 450 if(atoi($2) < 0) 451 yyerror("number equal or greater than zero expected"); 452 cfg_parser->opt->rrl_slip = atoi($2); 453 #endif 454 } 455 ; 456 server_rrl_ipv4_prefix_length: VAR_RRL_IPV4_PREFIX_LENGTH STRING 457 { 458 OUTYY(("P(server_rrl_ipv4_prefix_length:%s)\n", $2)); 459 #ifdef RATELIMIT 460 if(atoi($2) < 0 || atoi($2) > 32) 461 yyerror("invalid IPv4 prefix length"); 462 cfg_parser->opt->rrl_ipv4_prefix_length = atoi($2); 463 #endif 464 } 465 ; 466 server_rrl_ipv6_prefix_length: VAR_RRL_IPV6_PREFIX_LENGTH STRING 467 { 468 OUTYY(("P(server_rrl_ipv6_prefix_length:%s)\n", $2)); 469 #ifdef RATELIMIT 470 if(atoi($2) < 0 || atoi($2) > 64) 471 yyerror("invalid IPv6 prefix length"); 472 cfg_parser->opt->rrl_ipv6_prefix_length = atoi($2); 473 #endif 474 } 475 ; 476 server_rrl_whitelist_ratelimit: VAR_RRL_WHITELIST_RATELIMIT STRING 477 { 478 OUTYY(("P(server_rrl_whitelist_ratelimit:%s)\n", $2)); 479 #ifdef RATELIMIT 480 cfg_parser->opt->rrl_whitelist_ratelimit = atoi($2); 481 #endif 482 } 483 ; 484 server_zonefiles_check: VAR_ZONEFILES_CHECK STRING 485 { 486 OUTYY(("P(server_zonefiles_check:%s)\n", $2)); 487 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 488 yyerror("expected yes or no."); 489 else cfg_parser->opt->zonefiles_check = (strcmp($2, "yes")==0); 490 } 491 ; 492 server_zonefiles_write: VAR_ZONEFILES_WRITE STRING 493 { 494 OUTYY(("P(server_zonefiles_write:%s)\n", $2)); 495 if(atoi($2) == 0 && strcmp($2, "0") != 0) 496 yyerror("number expected"); 497 else cfg_parser->opt->zonefiles_write = atoi($2); 498 } 499 ; 500 501 rcstart: VAR_REMOTE_CONTROL 502 { 503 OUTYY(("\nP(remote-control:)\n")); 504 } 505 ; 506 contents_rc: contents_rc content_rc 507 | ; 508 content_rc: rc_control_enable | rc_control_interface | rc_control_port | 509 rc_server_key_file | rc_server_cert_file | rc_control_key_file | 510 rc_control_cert_file 511 ; 512 rc_control_enable: VAR_CONTROL_ENABLE STRING 513 { 514 OUTYY(("P(control_enable:%s)\n", $2)); 515 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 516 yyerror("expected yes or no."); 517 else cfg_parser->opt->control_enable = (strcmp($2, "yes")==0); 518 } 519 ; 520 rc_control_port: VAR_CONTROL_PORT STRING 521 { 522 OUTYY(("P(control_port:%s)\n", $2)); 523 if(atoi($2) == 0) 524 yyerror("control port number expected"); 525 else cfg_parser->opt->control_port = atoi($2); 526 } 527 ; 528 rc_control_interface: VAR_CONTROL_INTERFACE STRING 529 { 530 ip_address_option_t* o = (ip_address_option_t*)region_alloc( 531 cfg_parser->opt->region, sizeof(ip_address_option_t)); 532 OUTYY(("P(control_interface:%s)\n", $2)); 533 o->next = cfg_parser->opt->control_interface; 534 cfg_parser->opt->control_interface = o; 535 o->address = region_strdup(cfg_parser->opt->region, $2); 536 } 537 ; 538 rc_server_key_file: VAR_SERVER_KEY_FILE STRING 539 { 540 OUTYY(("P(rc_server_key_file:%s)\n", $2)); 541 cfg_parser->opt->server_key_file = region_strdup(cfg_parser->opt->region, $2); 542 } 543 ; 544 rc_server_cert_file: VAR_SERVER_CERT_FILE STRING 545 { 546 OUTYY(("P(rc_server_cert_file:%s)\n", $2)); 547 cfg_parser->opt->server_cert_file = region_strdup(cfg_parser->opt->region, $2); 548 } 549 ; 550 rc_control_key_file: VAR_CONTROL_KEY_FILE STRING 551 { 552 OUTYY(("P(rc_control_key_file:%s)\n", $2)); 553 cfg_parser->opt->control_key_file = region_strdup(cfg_parser->opt->region, $2); 554 } 555 ; 556 rc_control_cert_file: VAR_CONTROL_CERT_FILE STRING 557 { 558 OUTYY(("P(rc_control_cert_file:%s)\n", $2)); 559 cfg_parser->opt->control_cert_file = region_strdup(cfg_parser->opt->region, $2); 560 } 561 ; 562 563 /* pattern: declaration */ 564 patternstart: VAR_PATTERN 565 { 566 OUTYY(("\nP(pattern:)\n")); 567 if(cfg_parser->current_zone) { 568 if(!cfg_parser->current_zone->name) 569 c_error("previous zone has no name"); 570 else { 571 if(!nsd_options_insert_zone(cfg_parser->opt, 572 cfg_parser->current_zone)) 573 c_error("duplicate zone"); 574 } 575 if(!cfg_parser->current_zone->pattern) 576 c_error("previous zone has no pattern"); 577 cfg_parser->current_zone = NULL; 578 } 579 if(cfg_parser->current_pattern) { 580 if(!cfg_parser->current_pattern->pname) 581 c_error("previous pattern has no name"); 582 else { 583 if(!nsd_options_insert_pattern(cfg_parser->opt, 584 cfg_parser->current_pattern)) 585 c_error_msg("duplicate pattern %s", 586 cfg_parser->current_pattern->pname); 587 } 588 } 589 cfg_parser->current_pattern = pattern_options_create( 590 cfg_parser->opt->region); 591 cfg_parser->current_allow_notify = 0; 592 cfg_parser->current_request_xfr = 0; 593 cfg_parser->current_notify = 0; 594 cfg_parser->current_provide_xfr = 0; 595 cfg_parser->current_outgoing_interface = 0; 596 } 597 ; 598 contents_pattern: contents_pattern content_pattern | content_pattern; 599 content_pattern: pattern_name | zone_config_item; 600 zone_config_item: zone_zonefile | zone_allow_notify | zone_request_xfr | 601 zone_notify | zone_notify_retry | zone_provide_xfr | 602 zone_outgoing_interface | zone_allow_axfr_fallback | include_pattern | 603 zone_rrl_whitelist | zone_zonestats | zone_max_refresh_time | 604 zone_min_refresh_time | zone_max_retry_time | zone_min_retry_time | 605 zone_size_limit_xfr; 606 pattern_name: VAR_NAME STRING 607 { 608 OUTYY(("P(pattern_name:%s)\n", $2)); 609 #ifndef NDEBUG 610 assert(cfg_parser->current_pattern); 611 #endif 612 if(strchr($2, ' ')) 613 c_error_msg("space is not allowed in pattern name: " 614 "'%s'", $2); 615 cfg_parser->current_pattern->pname = region_strdup(cfg_parser->opt->region, $2); 616 } 617 ; 618 include_pattern: VAR_INCLUDEPATTERN STRING 619 { 620 OUTYY(("P(include-pattern:%s)\n", $2)); 621 #ifndef NDEBUG 622 assert(cfg_parser->current_pattern); 623 #endif 624 config_apply_pattern($2); 625 } 626 ; 627 628 /* zone: declaration */ 629 zonestart: VAR_ZONE 630 { 631 OUTYY(("\nP(zone:)\n")); 632 if(cfg_parser->current_zone) { 633 if(!cfg_parser->current_zone->name) 634 c_error("previous zone has no name"); 635 else { 636 if(!nsd_options_insert_zone(cfg_parser->opt, 637 cfg_parser->current_zone)) 638 c_error("duplicate zone"); 639 } 640 if(!cfg_parser->current_zone->pattern) 641 c_error("previous zone has no pattern"); 642 } 643 if(cfg_parser->current_pattern) { 644 if(!cfg_parser->current_pattern->pname) 645 c_error("previous pattern has no name"); 646 else { 647 if(!nsd_options_insert_pattern(cfg_parser->opt, 648 cfg_parser->current_pattern)) 649 c_error_msg("duplicate pattern %s", 650 cfg_parser->current_pattern->pname); 651 } 652 } 653 cfg_parser->current_zone = zone_options_create(cfg_parser->opt->region); 654 cfg_parser->current_zone->part_of_config = 1; 655 cfg_parser->current_pattern = pattern_options_create( 656 cfg_parser->opt->region); 657 cfg_parser->current_pattern->implicit = 1; 658 cfg_parser->current_zone->pattern = cfg_parser->current_pattern; 659 cfg_parser->current_allow_notify = 0; 660 cfg_parser->current_request_xfr = 0; 661 cfg_parser->current_notify = 0; 662 cfg_parser->current_provide_xfr = 0; 663 cfg_parser->current_outgoing_interface = 0; 664 } 665 ; 666 contents_zone: contents_zone content_zone | content_zone; 667 content_zone: zone_name | zone_config_item; 668 zone_name: VAR_NAME STRING 669 { 670 char* s; 671 OUTYY(("P(zone_name:%s)\n", $2)); 672 #ifndef NDEBUG 673 assert(cfg_parser->current_zone); 674 assert(cfg_parser->current_pattern); 675 #endif 676 cfg_parser->current_zone->name = region_strdup(cfg_parser->opt->region, $2); 677 s = (char*)region_alloc(cfg_parser->opt->region, 678 strlen($2)+strlen(PATTERN_IMPLICIT_MARKER)+1); 679 memmove(s, PATTERN_IMPLICIT_MARKER, 680 strlen(PATTERN_IMPLICIT_MARKER)); 681 memmove(s+strlen(PATTERN_IMPLICIT_MARKER), $2, strlen($2)+1); 682 if(pattern_options_find(cfg_parser->opt, s)) 683 c_error_msg("zone %s cannot be created because " 684 "implicit pattern %s already exists", $2, s); 685 cfg_parser->current_pattern->pname = s; 686 } 687 ; 688 zone_zonefile: VAR_ZONEFILE STRING 689 { 690 OUTYY(("P(zonefile:%s)\n", $2)); 691 #ifndef NDEBUG 692 assert(cfg_parser->current_pattern); 693 #endif 694 cfg_parser->current_pattern->zonefile = region_strdup(cfg_parser->opt->region, $2); 695 } 696 ; 697 zone_zonestats: VAR_ZONESTATS STRING 698 { 699 OUTYY(("P(zonestats:%s)\n", $2)); 700 #ifndef NDEBUG 701 assert(cfg_parser->current_pattern); 702 #endif 703 cfg_parser->current_pattern->zonestats = region_strdup(cfg_parser->opt->region, $2); 704 } 705 ; 706 zone_allow_notify: VAR_ALLOW_NOTIFY STRING STRING 707 { 708 acl_options_t* acl = parse_acl_info(cfg_parser->opt->region, $2, $3); 709 OUTYY(("P(allow_notify:%s %s)\n", $2, $3)); 710 if(cfg_parser->current_allow_notify) 711 cfg_parser->current_allow_notify->next = acl; 712 else 713 cfg_parser->current_pattern->allow_notify = acl; 714 cfg_parser->current_allow_notify = acl; 715 } 716 ; 717 zone_request_xfr: VAR_REQUEST_XFR zone_request_xfr_data 718 { 719 } 720 ; 721 zone_size_limit_xfr: VAR_SIZE_LIMIT_XFR STRING 722 { 723 OUTYY(("P(size_limit_xfr:%s)\n", $2)); 724 if(atoll($2) < 0) 725 yyerror("number >= 0 expected"); 726 else cfg_parser->current_pattern->size_limit_xfr = atoll($2); 727 } 728 ; 729 zone_request_xfr_data: STRING STRING 730 { 731 acl_options_t* acl = parse_acl_info(cfg_parser->opt->region, $1, $2); 732 OUTYY(("P(request_xfr:%s %s)\n", $1, $2)); 733 if(acl->blocked) c_error("blocked address used for request-xfr"); 734 if(acl->rangetype!=acl_range_single) c_error("address range used for request-xfr"); 735 if(cfg_parser->current_request_xfr) 736 cfg_parser->current_request_xfr->next = acl; 737 else 738 cfg_parser->current_pattern->request_xfr = acl; 739 cfg_parser->current_request_xfr = acl; 740 } 741 | VAR_AXFR STRING STRING 742 { 743 acl_options_t* acl = parse_acl_info(cfg_parser->opt->region, $2, $3); 744 acl->use_axfr_only = 1; 745 OUTYY(("P(request_xfr:%s %s)\n", $2, $3)); 746 if(acl->blocked) c_error("blocked address used for request-xfr"); 747 if(acl->rangetype!=acl_range_single) c_error("address range used for request-xfr"); 748 if(cfg_parser->current_request_xfr) 749 cfg_parser->current_request_xfr->next = acl; 750 else 751 cfg_parser->current_pattern->request_xfr = acl; 752 cfg_parser->current_request_xfr = acl; 753 } 754 | VAR_UDP STRING STRING 755 { 756 acl_options_t* acl = parse_acl_info(cfg_parser->opt->region, $2, $3); 757 acl->allow_udp = 1; 758 OUTYY(("P(request_xfr:%s %s)\n", $2, $3)); 759 if(acl->blocked) c_error("blocked address used for request-xfr"); 760 if(acl->rangetype!=acl_range_single) c_error("address range used for request-xfr"); 761 if(cfg_parser->current_request_xfr) 762 cfg_parser->current_request_xfr->next = acl; 763 else 764 cfg_parser->current_pattern->request_xfr = acl; 765 cfg_parser->current_request_xfr = acl; 766 } 767 ; 768 zone_notify: VAR_NOTIFY STRING STRING 769 { 770 acl_options_t* acl = parse_acl_info(cfg_parser->opt->region, $2, $3); 771 OUTYY(("P(notify:%s %s)\n", $2, $3)); 772 if(acl->blocked) c_error("blocked address used for notify"); 773 if(acl->rangetype!=acl_range_single) c_error("address range used for notify"); 774 if(cfg_parser->current_notify) 775 cfg_parser->current_notify->next = acl; 776 else 777 cfg_parser->current_pattern->notify = acl; 778 cfg_parser->current_notify = acl; 779 } 780 ; 781 zone_notify_retry: VAR_NOTIFY_RETRY STRING 782 { 783 OUTYY(("P(notify_retry:%s)\n", $2)); 784 if(atoi($2) == 0 && strcmp($2, "0") != 0) 785 yyerror("number expected"); 786 else { 787 cfg_parser->current_pattern->notify_retry = atoi($2); 788 cfg_parser->current_pattern->notify_retry_is_default=0; 789 } 790 } 791 ; 792 zone_provide_xfr: VAR_PROVIDE_XFR STRING STRING 793 { 794 acl_options_t* acl = parse_acl_info(cfg_parser->opt->region, $2, $3); 795 OUTYY(("P(provide_xfr:%s %s)\n", $2, $3)); 796 if(cfg_parser->current_provide_xfr) 797 cfg_parser->current_provide_xfr->next = acl; 798 else 799 cfg_parser->current_pattern->provide_xfr = acl; 800 cfg_parser->current_provide_xfr = acl; 801 } 802 ; 803 zone_outgoing_interface: VAR_OUTGOING_INTERFACE STRING 804 { 805 acl_options_t* acl = parse_acl_info(cfg_parser->opt->region, $2, "NOKEY"); 806 OUTYY(("P(outgoing_interface:%s)\n", $2)); 807 if(acl->rangetype!=acl_range_single) c_error("address range used for outgoing interface"); 808 if(cfg_parser->current_outgoing_interface) 809 cfg_parser->current_outgoing_interface->next = acl; 810 else 811 cfg_parser->current_pattern->outgoing_interface = acl; 812 cfg_parser->current_outgoing_interface = acl; 813 } 814 ; 815 zone_allow_axfr_fallback: VAR_ALLOW_AXFR_FALLBACK STRING 816 { 817 OUTYY(("P(allow_axfr_fallback:%s)\n", $2)); 818 if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) 819 yyerror("expected yes or no."); 820 else { 821 cfg_parser->current_pattern->allow_axfr_fallback = (strcmp($2, "yes")==0); 822 cfg_parser->current_pattern->allow_axfr_fallback_is_default = 0; 823 } 824 } 825 ; 826 zone_rrl_whitelist: VAR_RRL_WHITELIST STRING 827 { 828 OUTYY(("P(zone_rrl_whitelist:%s)\n", $2)); 829 #ifdef RATELIMIT 830 cfg_parser->current_pattern->rrl_whitelist |= rrlstr2type($2); 831 #endif 832 } 833 ; 834 zone_max_refresh_time: VAR_MAX_REFRESH_TIME STRING 835 { 836 OUTYY(("P(zone_max_refresh_time:%s)\n", $2)); 837 if(atoi($2) == 0 && strcmp($2, "0") != 0) 838 yyerror("number expected"); 839 else { 840 cfg_parser->current_pattern->max_refresh_time = atoi($2); 841 cfg_parser->current_pattern->max_refresh_time_is_default = 0; 842 } 843 }; 844 zone_min_refresh_time: VAR_MIN_REFRESH_TIME STRING 845 { 846 OUTYY(("P(zone_min_refresh_time:%s)\n", $2)); 847 if(atoi($2) == 0 && strcmp($2, "0") != 0) 848 yyerror("number expected"); 849 else { 850 cfg_parser->current_pattern->min_refresh_time = atoi($2); 851 cfg_parser->current_pattern->min_refresh_time_is_default = 0; 852 } 853 }; 854 zone_max_retry_time: VAR_MAX_RETRY_TIME STRING 855 { 856 OUTYY(("P(zone_max_retry_time:%s)\n", $2)); 857 if(atoi($2) == 0 && strcmp($2, "0") != 0) 858 yyerror("number expected"); 859 else { 860 cfg_parser->current_pattern->max_retry_time = atoi($2); 861 cfg_parser->current_pattern->max_retry_time_is_default = 0; 862 } 863 }; 864 zone_min_retry_time: VAR_MIN_RETRY_TIME STRING 865 { 866 OUTYY(("P(zone_min_retry_time:%s)\n", $2)); 867 if(atoi($2) == 0 && strcmp($2, "0") != 0) 868 yyerror("number expected"); 869 else { 870 cfg_parser->current_pattern->min_retry_time = atoi($2); 871 cfg_parser->current_pattern->min_retry_time_is_default = 0; 872 } 873 }; 874 875 /* key: declaration */ 876 keystart: VAR_KEY 877 { 878 OUTYY(("\nP(key:)\n")); 879 if(cfg_parser->current_key) { 880 if(!cfg_parser->current_key->name) c_error("previous key has no name"); 881 if(!cfg_parser->current_key->algorithm) c_error("previous key has no algorithm"); 882 if(!cfg_parser->current_key->secret) c_error("previous key has no secret blob"); 883 key_options_insert(cfg_parser->opt, cfg_parser->current_key); 884 } 885 cfg_parser->current_key = key_options_create(cfg_parser->opt->region); 886 } 887 ; 888 contents_key: contents_key content_key | content_key; 889 content_key: key_name | key_algorithm | key_secret; 890 key_name: VAR_NAME STRING 891 { 892 const dname_type* d; 893 OUTYY(("P(key_name:%s)\n", $2)); 894 #ifndef NDEBUG 895 assert(cfg_parser->current_key); 896 #endif 897 cfg_parser->current_key->name = region_strdup(cfg_parser->opt->region, $2); 898 d = dname_parse(cfg_parser->opt->region, $2); 899 if(!d) c_error_msg("Failed to parse tsig key name %s", $2); 900 else region_recycle(cfg_parser->opt->region, (void*)d, 901 dname_total_size(d)); 902 } 903 ; 904 key_algorithm: VAR_ALGORITHM STRING 905 { 906 OUTYY(("P(key_algorithm:%s)\n", $2)); 907 #ifndef NDEBUG 908 assert(cfg_parser->current_key); 909 #endif 910 cfg_parser->current_key->algorithm = region_strdup(cfg_parser->opt->region, $2); 911 if(tsig_get_algorithm_by_name($2) == NULL) 912 c_error_msg("Bad tsig algorithm %s", $2); 913 } 914 ; 915 key_secret: VAR_SECRET STRING 916 { 917 uint8_t data[16384]; 918 int size; 919 OUTYY(("key_secret:%s)\n", $2)); 920 #ifndef NDEBUG 921 assert(cfg_parser->current_key); 922 #endif 923 cfg_parser->current_key->secret = region_strdup(cfg_parser->opt->region, $2); 924 size = __b64_pton($2, data, sizeof(data)); 925 if(size == -1) { 926 c_error_msg("Cannot base64 decode tsig secret %s", 927 cfg_parser->current_key->name? 928 cfg_parser->current_key->name:""); 929 } else if(size != 0) { 930 memset(data, 0xdd, size); /* wipe secret */ 931 } 932 } 933 ; 934 935 %% 936 937 /* parse helper routines could be here */ 938