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