"Fossies" - the Fresh Open Source Software Archive

Member "nsd-4.3.6/configparser.y" (6 Apr 2021, 27915 Bytes) of package /linux/misc/dns/nsd-4.3.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bison source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "configparser.y": 4.3.5_vs_4.3.6.

    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 
   24 int yylex(void);
   25 
   26 #ifdef __cplusplus
   27 extern "C"
   28 #endif
   29 
   30 /* these need to be global, otherwise they cannot be used inside yacc */
   31 extern config_parser_state_type *cfg_parser;
   32 
   33 static void append_acl(struct acl_options **list, struct acl_options *acl);
   34 static int parse_boolean(const char *str, int *bln);
   35 static int parse_expire_expr(const char *str, long long *num, uint8_t *expr);
   36 static int parse_number(const char *str, long long *num);
   37 static int parse_range(const char *str, long long *low, long long *high);
   38 %}
   39 
   40 %union {
   41   char *str;
   42   long long llng;
   43   int bln;
   44   struct ip_address_option *ip;
   45   struct range_option *range;
   46   struct cpu_option *cpu;
   47 }
   48 
   49 %token <str> STRING
   50 %type <llng> number
   51 %type <bln> boolean
   52 %type <ip> ip_address
   53 %type <llng> service_cpu_affinity
   54 %type <cpu> cpus
   55 
   56 /* server */
   57 %token VAR_SERVER
   58 %token VAR_SERVER_COUNT
   59 %token VAR_IP_ADDRESS
   60 %token VAR_IP_TRANSPARENT
   61 %token VAR_IP_FREEBIND
   62 %token VAR_REUSEPORT
   63 %token VAR_SEND_BUFFER_SIZE
   64 %token VAR_RECEIVE_BUFFER_SIZE
   65 %token VAR_DEBUG_MODE
   66 %token VAR_IP4_ONLY
   67 %token VAR_IP6_ONLY
   68 %token VAR_DO_IP4
   69 %token VAR_DO_IP6
   70 %token VAR_PORT
   71 %token VAR_USE_SYSTEMD
   72 %token VAR_VERBOSITY
   73 %token VAR_USERNAME
   74 %token VAR_CHROOT
   75 %token VAR_ZONESDIR
   76 %token VAR_ZONELISTFILE
   77 %token VAR_DATABASE
   78 %token VAR_LOGFILE
   79 %token VAR_LOG_ONLY_SYSLOG
   80 %token VAR_PIDFILE
   81 %token VAR_DIFFFILE
   82 %token VAR_XFRDFILE
   83 %token VAR_XFRDIR
   84 %token VAR_HIDE_VERSION
   85 %token VAR_HIDE_IDENTITY
   86 %token VAR_VERSION
   87 %token VAR_IDENTITY
   88 %token VAR_NSID
   89 %token VAR_TCP_COUNT
   90 %token VAR_TCP_REJECT_OVERFLOW
   91 %token VAR_TCP_QUERY_COUNT
   92 %token VAR_TCP_TIMEOUT
   93 %token VAR_TCP_MSS
   94 %token VAR_OUTGOING_TCP_MSS
   95 %token VAR_IPV4_EDNS_SIZE
   96 %token VAR_IPV6_EDNS_SIZE
   97 %token VAR_STATISTICS
   98 %token VAR_XFRD_RELOAD_TIMEOUT
   99 %token VAR_LOG_TIME_ASCII
  100 %token VAR_ROUND_ROBIN
  101 %token VAR_MINIMAL_RESPONSES
  102 %token VAR_CONFINE_TO_ZONE
  103 %token VAR_REFUSE_ANY
  104 %token VAR_ZONEFILES_CHECK
  105 %token VAR_ZONEFILES_WRITE
  106 %token VAR_RRL_SIZE
  107 %token VAR_RRL_RATELIMIT
  108 %token VAR_RRL_SLIP
  109 %token VAR_RRL_IPV4_PREFIX_LENGTH
  110 %token VAR_RRL_IPV6_PREFIX_LENGTH
  111 %token VAR_RRL_WHITELIST_RATELIMIT
  112 %token VAR_TLS_SERVICE_KEY
  113 %token VAR_TLS_SERVICE_PEM
  114 %token VAR_TLS_SERVICE_OCSP
  115 %token VAR_TLS_PORT
  116 %token VAR_CPU_AFFINITY
  117 %token VAR_XFRD_CPU_AFFINITY
  118 %token <llng> VAR_SERVER_CPU_AFFINITY
  119 %token VAR_DROP_UPDATES
  120 
  121 /* dnstap */
  122 %token VAR_DNSTAP
  123 %token VAR_DNSTAP_ENABLE
  124 %token VAR_DNSTAP_SOCKET_PATH
  125 %token VAR_DNSTAP_SEND_IDENTITY
  126 %token VAR_DNSTAP_SEND_VERSION
  127 %token VAR_DNSTAP_IDENTITY
  128 %token VAR_DNSTAP_VERSION
  129 %token VAR_DNSTAP_LOG_AUTH_QUERY_MESSAGES
  130 %token VAR_DNSTAP_LOG_AUTH_RESPONSE_MESSAGES
  131 
  132 /* remote-control */
  133 %token VAR_REMOTE_CONTROL
  134 %token VAR_CONTROL_ENABLE
  135 %token VAR_CONTROL_INTERFACE
  136 %token VAR_CONTROL_PORT
  137 %token VAR_SERVER_KEY_FILE
  138 %token VAR_SERVER_CERT_FILE
  139 %token VAR_CONTROL_KEY_FILE
  140 %token VAR_CONTROL_CERT_FILE
  141 
  142 /* key */
  143 %token VAR_KEY
  144 %token VAR_ALGORITHM
  145 %token VAR_SECRET
  146 
  147 /* pattern */
  148 %token VAR_PATTERN
  149 %token VAR_NAME
  150 %token VAR_ZONEFILE
  151 %token VAR_NOTIFY
  152 %token VAR_PROVIDE_XFR
  153 %token VAR_ALLOW_QUERY
  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_ALLOW_QUERY STRING STRING
  829     {
  830       acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, $3);
  831       append_acl(&cfg_parser->pattern->allow_query, acl);
  832     }
  833   | VAR_OUTGOING_INTERFACE STRING
  834     {
  835       acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, "NOKEY");
  836       append_acl(&cfg_parser->pattern->outgoing_interface, acl);
  837     }
  838   | VAR_ALLOW_AXFR_FALLBACK boolean
  839     {
  840       cfg_parser->pattern->allow_axfr_fallback = $2;
  841       cfg_parser->pattern->allow_axfr_fallback_is_default = 0;
  842     }
  843   | VAR_NOTIFY_RETRY number
  844     {
  845       cfg_parser->pattern->notify_retry = $2;
  846       cfg_parser->pattern->notify_retry_is_default = 0;
  847     }
  848   | VAR_MAX_REFRESH_TIME number
  849     {
  850       cfg_parser->pattern->max_refresh_time = $2;
  851       cfg_parser->pattern->max_refresh_time_is_default = 0;
  852     }
  853   | VAR_MIN_REFRESH_TIME number
  854     {
  855       cfg_parser->pattern->min_refresh_time = $2;
  856       cfg_parser->pattern->min_refresh_time_is_default = 0;
  857     }
  858   | VAR_MAX_RETRY_TIME number
  859     {
  860       cfg_parser->pattern->max_retry_time = $2;
  861       cfg_parser->pattern->max_retry_time_is_default = 0;
  862     }
  863   | VAR_MIN_RETRY_TIME number
  864     {
  865       cfg_parser->pattern->min_retry_time = $2;
  866       cfg_parser->pattern->min_retry_time_is_default = 0;
  867     } 
  868   | VAR_MIN_EXPIRE_TIME STRING
  869     {
  870       long long num;
  871       uint8_t expr;
  872 
  873       if (!parse_expire_expr($2, &num, &expr)) {
  874         yyerror("expected an expire time in seconds or \"refresh+retry+1\"");
  875         YYABORT; /* trigger a parser error */
  876       }
  877       cfg_parser->pattern->min_expire_time = num;
  878       cfg_parser->pattern->min_expire_time_expr = expr;
  879     };
  880 
  881 ip_address:
  882     STRING
  883     {
  884       struct ip_address_option *ip = region_alloc_zero(
  885         cfg_parser->opt->region, sizeof(*ip));
  886       ip->address = region_strdup(cfg_parser->opt->region, $1);
  887       ip->fib = -1;
  888       $$ = ip;
  889     } ;
  890 
  891 number:
  892     STRING
  893     {
  894       if(!parse_number($1, &$$)) {
  895         yyerror("expected a number");
  896         YYABORT; /* trigger a parser error */
  897       }
  898     } ;
  899 
  900 boolean:
  901     STRING
  902     {
  903       if(!parse_boolean($1, &$$)) {
  904         yyerror("expected yes or no");
  905         YYABORT; /* trigger a parser error */
  906       }
  907     } ;
  908 
  909 %%
  910 
  911 static void
  912 append_acl(struct acl_options **list, struct acl_options *acl)
  913 {
  914     assert(list != NULL);
  915 
  916     if(*list == NULL) {
  917         *list = acl;
  918     } else {
  919         struct acl_options *tail = *list;
  920         while(tail->next != NULL)
  921             tail = tail->next;
  922         tail->next = acl;
  923     }
  924 }
  925 
  926 static int
  927 parse_boolean(const char *str, int *bln)
  928 {
  929     if(strcmp(str, "yes") == 0) {
  930         *bln = 1;
  931     } else if(strcmp(str, "no") == 0) {
  932         *bln = 0;
  933     } else {
  934         return 0;
  935     }
  936 
  937     return 1;
  938 }
  939 
  940 static int
  941 parse_expire_expr(const char *str, long long *num, uint8_t *expr)
  942 {
  943     if(parse_number(str, num)) {
  944         *expr = EXPIRE_TIME_HAS_VALUE;
  945         return 1;
  946     }
  947     if(strcmp(str, REFRESHPLUSRETRYPLUS1_STR) == 0) {
  948         *num = 0;
  949         *expr = REFRESHPLUSRETRYPLUS1;
  950         return 1;
  951     }
  952     return 0;
  953 }
  954 
  955 static int
  956 parse_number(const char *str, long long *num)
  957 {
  958     /* ensure string consists entirely of digits */
  959     size_t pos = 0;
  960     while(str[pos] >= '0' && str[pos] <= '9') {
  961         pos++;
  962     }
  963 
  964     if(pos != 0 && str[pos] == '\0') {
  965         *num = strtoll(str, NULL, 10);
  966         return 1;
  967     }
  968 
  969     return 0;
  970 }
  971 
  972 static int
  973 parse_range(const char *str, long long *low, long long *high)
  974 {
  975     const char *ptr = str;
  976     long long num[2];
  977 
  978     /* require range to begin with a number */
  979     if(*ptr < '0' || *ptr > '9') {
  980         return 0;
  981     }
  982 
  983     num[0] = strtoll(ptr, (char **)&ptr, 10);
  984 
  985     /* require number to be followed by nothing at all or a dash */
  986     if(*ptr == '\0') {
  987         *low = num[0];
  988         *high = num[0];
  989         return 1;
  990     } else if(*ptr != '-') {
  991         return 0;
  992     }
  993 
  994     ++ptr;
  995     /* require dash to be followed by a number */
  996     if(*ptr < '0' || *ptr > '9') {
  997         return 0;
  998     }
  999 
 1000     num[1] = strtoll(ptr, (char **)&ptr, 10);
 1001 
 1002     /* require number to be followed by nothing at all */
 1003     if(*ptr == '\0') {
 1004         if(num[0] < num[1]) {
 1005             *low = num[0];
 1006             *high = num[1];
 1007         } else {
 1008             *low = num[1];
 1009             *high = num[0];
 1010         }
 1011         return 1;
 1012     }
 1013 
 1014     return 0;
 1015 }