xref: /netbsd-src/external/bsd/nsd/dist/configparser.y (revision 7d62b00eb9ad855ffcd7da46b41e23feb5476fac)
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 void add_to_last_acl(struct acl_options **list, char *ac);
35 static int parse_boolean(const char *str, int *bln);
36 static int parse_expire_expr(const char *str, long long *num, uint8_t *expr);
37 static int parse_number(const char *str, long long *num);
38 static int parse_range(const char *str, long long *low, long long *high);
39 
40 struct component {
41 	struct component *next;
42 	char *str;
43 };
44 
45 %}
46 
47 %union {
48   char *str;
49   long long llng;
50   int bln;
51   struct ip_address_option *ip;
52   struct range_option *range;
53   struct cpu_option *cpu;
54   char **strv;
55   struct component *comp;
56 }
57 
58 %token <str> STRING
59 %type <llng> number
60 %type <bln> boolean
61 %type <ip> ip_address
62 %type <llng> service_cpu_affinity
63 %type <cpu> cpus
64 %type <strv> command
65 %type <comp> arguments
66 
67 /* server */
68 %token VAR_SERVER
69 %token VAR_SERVER_COUNT
70 %token VAR_IP_ADDRESS
71 %token VAR_IP_TRANSPARENT
72 %token VAR_IP_FREEBIND
73 %token VAR_REUSEPORT
74 %token VAR_SEND_BUFFER_SIZE
75 %token VAR_RECEIVE_BUFFER_SIZE
76 %token VAR_DEBUG_MODE
77 %token VAR_IP4_ONLY
78 %token VAR_IP6_ONLY
79 %token VAR_DO_IP4
80 %token VAR_DO_IP6
81 %token VAR_PORT
82 %token VAR_USE_SYSTEMD
83 %token VAR_VERBOSITY
84 %token VAR_USERNAME
85 %token VAR_CHROOT
86 %token VAR_ZONESDIR
87 %token VAR_ZONELISTFILE
88 %token VAR_DATABASE
89 %token VAR_LOGFILE
90 %token VAR_LOG_ONLY_SYSLOG
91 %token VAR_PIDFILE
92 %token VAR_DIFFFILE
93 %token VAR_XFRDFILE
94 %token VAR_XFRDIR
95 %token VAR_HIDE_VERSION
96 %token VAR_HIDE_IDENTITY
97 %token VAR_VERSION
98 %token VAR_IDENTITY
99 %token VAR_NSID
100 %token VAR_TCP_COUNT
101 %token VAR_TCP_REJECT_OVERFLOW
102 %token VAR_TCP_QUERY_COUNT
103 %token VAR_TCP_TIMEOUT
104 %token VAR_TCP_MSS
105 %token VAR_OUTGOING_TCP_MSS
106 %token VAR_IPV4_EDNS_SIZE
107 %token VAR_IPV6_EDNS_SIZE
108 %token VAR_STATISTICS
109 %token VAR_XFRD_RELOAD_TIMEOUT
110 %token VAR_LOG_TIME_ASCII
111 %token VAR_ROUND_ROBIN
112 %token VAR_MINIMAL_RESPONSES
113 %token VAR_CONFINE_TO_ZONE
114 %token VAR_REFUSE_ANY
115 %token VAR_ZONEFILES_CHECK
116 %token VAR_ZONEFILES_WRITE
117 %token VAR_RRL_SIZE
118 %token VAR_RRL_RATELIMIT
119 %token VAR_RRL_SLIP
120 %token VAR_RRL_IPV4_PREFIX_LENGTH
121 %token VAR_RRL_IPV6_PREFIX_LENGTH
122 %token VAR_RRL_WHITELIST_RATELIMIT
123 %token VAR_TLS_SERVICE_KEY
124 %token VAR_TLS_SERVICE_PEM
125 %token VAR_TLS_SERVICE_OCSP
126 %token VAR_TLS_PORT
127 %token VAR_TLS_CERT_BUNDLE
128 %token VAR_CPU_AFFINITY
129 %token VAR_XFRD_CPU_AFFINITY
130 %token <llng> VAR_SERVER_CPU_AFFINITY
131 %token VAR_DROP_UPDATES
132 %token VAR_XFRD_TCP_MAX
133 %token VAR_XFRD_TCP_PIPELINE
134 
135 /* dnstap */
136 %token VAR_DNSTAP
137 %token VAR_DNSTAP_ENABLE
138 %token VAR_DNSTAP_SOCKET_PATH
139 %token VAR_DNSTAP_SEND_IDENTITY
140 %token VAR_DNSTAP_SEND_VERSION
141 %token VAR_DNSTAP_IDENTITY
142 %token VAR_DNSTAP_VERSION
143 %token VAR_DNSTAP_LOG_AUTH_QUERY_MESSAGES
144 %token VAR_DNSTAP_LOG_AUTH_RESPONSE_MESSAGES
145 
146 /* remote-control */
147 %token VAR_REMOTE_CONTROL
148 %token VAR_CONTROL_ENABLE
149 %token VAR_CONTROL_INTERFACE
150 %token VAR_CONTROL_PORT
151 %token VAR_SERVER_KEY_FILE
152 %token VAR_SERVER_CERT_FILE
153 %token VAR_CONTROL_KEY_FILE
154 %token VAR_CONTROL_CERT_FILE
155 
156 /* key */
157 %token VAR_KEY
158 %token VAR_ALGORITHM
159 %token VAR_SECRET
160 
161 /* xot auth */
162 %token VAR_TLS_AUTH
163 %token VAR_TLS_AUTH_DOMAIN_NAME
164 %token VAR_TLS_AUTH_CLIENT_CERT
165 %token VAR_TLS_AUTH_CLIENT_KEY
166 %token VAR_TLS_AUTH_CLIENT_KEY_PW
167 
168 /* pattern */
169 %token VAR_PATTERN
170 %token VAR_NAME
171 %token VAR_ZONEFILE
172 %token VAR_NOTIFY
173 %token VAR_PROVIDE_XFR
174 %token VAR_ALLOW_QUERY
175 %token VAR_AXFR
176 %token VAR_UDP
177 %token VAR_NOTIFY_RETRY
178 %token VAR_ALLOW_NOTIFY
179 %token VAR_REQUEST_XFR
180 %token VAR_ALLOW_AXFR_FALLBACK
181 %token VAR_OUTGOING_INTERFACE
182 %token VAR_ANSWER_COOKIE
183 %token VAR_COOKIE_SECRET
184 %token VAR_COOKIE_SECRET_FILE
185 %token VAR_MAX_REFRESH_TIME
186 %token VAR_MIN_REFRESH_TIME
187 %token VAR_MAX_RETRY_TIME
188 %token VAR_MIN_RETRY_TIME
189 %token VAR_MIN_EXPIRE_TIME
190 %token VAR_MULTI_MASTER_CHECK
191 %token VAR_SIZE_LIMIT_XFR
192 %token VAR_ZONESTATS
193 %token VAR_INCLUDE_PATTERN
194 %token VAR_STORE_IXFR
195 %token VAR_IXFR_SIZE
196 %token VAR_IXFR_NUMBER
197 %token VAR_CREATE_IXFR
198 
199 /* zone */
200 %token VAR_ZONE
201 %token VAR_RRL_WHITELIST
202 
203 /* socket options */
204 %token VAR_SERVERS
205 %token VAR_BINDTODEVICE
206 %token VAR_SETFIB
207 
208 /* verify */
209 %token VAR_VERIFY
210 %token VAR_ENABLE
211 %token VAR_VERIFY_ZONE
212 %token VAR_VERIFY_ZONES
213 %token VAR_VERIFIER
214 %token VAR_VERIFIER_COUNT
215 %token VAR_VERIFIER_FEED_ZONE
216 %token VAR_VERIFIER_TIMEOUT
217 
218 %%
219 
220 blocks:
221     /* may be empty */
222   | blocks block ;
223 
224 block:
225     server
226   | dnstap
227   | remote_control
228   | key
229   | tls_auth
230   | pattern
231   | zone
232   | verify ;
233 
234 server:
235     VAR_SERVER server_block ;
236 
237 server_block:
238     server_block server_option | ;
239 
240 server_option:
241     VAR_IP_ADDRESS ip_address
242       {
243         struct ip_address_option *ip = cfg_parser->opt->ip_addresses;
244 
245         if(ip == NULL) {
246           cfg_parser->opt->ip_addresses = $2;
247         } else {
248           while(ip->next) { ip = ip->next; }
249           ip->next = $2;
250         }
251 
252         cfg_parser->ip = $2;
253       }
254     socket_options
255     {
256       cfg_parser->ip = NULL;
257     }
258   | VAR_SERVER_COUNT number
259     {
260       if ($2 > 0) {
261         cfg_parser->opt->server_count = (int)$2;
262       } else {
263         yyerror("expected a number greater than zero");
264       }
265     }
266   | VAR_IP_TRANSPARENT boolean
267     { cfg_parser->opt->ip_transparent = $2; }
268   | VAR_IP_FREEBIND boolean
269     { cfg_parser->opt->ip_freebind = $2; }
270   | VAR_SEND_BUFFER_SIZE number
271     { cfg_parser->opt->send_buffer_size = (int)$2; }
272   | VAR_RECEIVE_BUFFER_SIZE number
273     { cfg_parser->opt->receive_buffer_size = (int)$2; }
274   | VAR_DEBUG_MODE boolean
275     { cfg_parser->opt->debug_mode = $2; }
276   | VAR_USE_SYSTEMD boolean
277     { /* ignored, deprecated */ }
278   | VAR_HIDE_VERSION boolean
279     { cfg_parser->opt->hide_version = $2; }
280   | VAR_HIDE_IDENTITY boolean
281     { cfg_parser->opt->hide_identity = $2; }
282   | VAR_DROP_UPDATES boolean
283     { cfg_parser->opt->drop_updates = $2; }
284   | VAR_IP4_ONLY boolean
285     { if($2) { cfg_parser->opt->do_ip4 = 1; cfg_parser->opt->do_ip6 = 0; } }
286   | VAR_IP6_ONLY boolean
287     { if($2) { cfg_parser->opt->do_ip4 = 0; cfg_parser->opt->do_ip6 = 1; } }
288   | VAR_DO_IP4 boolean
289     { cfg_parser->opt->do_ip4 = $2; }
290   | VAR_DO_IP6 boolean
291     { cfg_parser->opt->do_ip6 = $2; }
292   | VAR_DATABASE STRING
293     {
294       cfg_parser->opt->database = region_strdup(cfg_parser->opt->region, $2);
295       if(cfg_parser->opt->database[0] == 0 &&
296          cfg_parser->opt->zonefiles_write == 0)
297       {
298         cfg_parser->opt->zonefiles_write = ZONEFILES_WRITE_INTERVAL;
299       }
300     }
301   | VAR_IDENTITY STRING
302     { cfg_parser->opt->identity = region_strdup(cfg_parser->opt->region, $2); }
303   | VAR_VERSION STRING
304     { cfg_parser->opt->version = region_strdup(cfg_parser->opt->region, $2); }
305   | VAR_NSID STRING
306     {
307       unsigned char* nsid = 0;
308       size_t nsid_len = strlen($2);
309 
310       if (strncasecmp($2, "ascii_", 6) == 0) {
311         nsid_len -= 6; /* discard "ascii_" */
312         if(nsid_len < 65535) {
313           cfg_parser->opt->nsid = region_alloc(cfg_parser->opt->region, nsid_len*2+1);
314           hex_ntop((uint8_t*)$2+6, nsid_len, (char*)cfg_parser->opt->nsid, nsid_len*2+1);
315         } else {
316           yyerror("NSID too long");
317         }
318       } else if (nsid_len % 2 != 0) {
319         yyerror("the NSID must be a hex string of an even length.");
320       } else {
321         nsid_len = nsid_len / 2;
322         if(nsid_len < 65535) {
323           nsid = xalloc(nsid_len);
324           if (hex_pton($2, nsid, nsid_len) == -1) {
325             yyerror("hex string cannot be parsed in NSID.");
326           } else {
327             cfg_parser->opt->nsid = region_strdup(cfg_parser->opt->region, $2);
328           }
329           free(nsid);
330         } else {
331           yyerror("NSID too long");
332         }
333       }
334     }
335   | VAR_LOGFILE STRING
336     { cfg_parser->opt->logfile = region_strdup(cfg_parser->opt->region, $2); }
337   | VAR_LOG_ONLY_SYSLOG boolean
338     { cfg_parser->opt->log_only_syslog = $2; }
339   | VAR_TCP_COUNT number
340     {
341       if ($2 > 0) {
342         cfg_parser->opt->tcp_count = (int)$2;
343       } else {
344         yyerror("expected a number greater than zero");
345       }
346     }
347   | VAR_TCP_REJECT_OVERFLOW boolean
348     { cfg_parser->opt->tcp_reject_overflow = $2; }
349   | VAR_TCP_QUERY_COUNT number
350     { cfg_parser->opt->tcp_query_count = (int)$2; }
351   | VAR_TCP_TIMEOUT number
352     { cfg_parser->opt->tcp_timeout = (int)$2; }
353   | VAR_TCP_MSS number
354     { cfg_parser->opt->tcp_mss = (int)$2; }
355   | VAR_OUTGOING_TCP_MSS number
356     { cfg_parser->opt->outgoing_tcp_mss = (int)$2; }
357   | VAR_IPV4_EDNS_SIZE number
358     { cfg_parser->opt->ipv4_edns_size = (size_t)$2; }
359   | VAR_IPV6_EDNS_SIZE number
360     { cfg_parser->opt->ipv6_edns_size = (size_t)$2; }
361   | VAR_PIDFILE STRING
362     { cfg_parser->opt->pidfile = region_strdup(cfg_parser->opt->region, $2); }
363   | VAR_PORT number
364     {
365       /* port number, stored as a string */
366       char buf[16];
367       (void)snprintf(buf, sizeof(buf), "%lld", $2);
368       cfg_parser->opt->port = region_strdup(cfg_parser->opt->region, buf);
369     }
370   | VAR_REUSEPORT boolean
371     { cfg_parser->opt->reuseport = $2; }
372   | VAR_STATISTICS number
373     { cfg_parser->opt->statistics = (int)$2; }
374   | VAR_CHROOT STRING
375     { cfg_parser->opt->chroot = region_strdup(cfg_parser->opt->region, $2); }
376   | VAR_USERNAME STRING
377     { cfg_parser->opt->username = region_strdup(cfg_parser->opt->region, $2); }
378   | VAR_ZONESDIR STRING
379     { cfg_parser->opt->zonesdir = region_strdup(cfg_parser->opt->region, $2); }
380   | VAR_ZONELISTFILE STRING
381     { cfg_parser->opt->zonelistfile = region_strdup(cfg_parser->opt->region, $2); }
382   | VAR_DIFFFILE STRING
383     { /* ignored, deprecated */ }
384   | VAR_XFRDFILE STRING
385     { cfg_parser->opt->xfrdfile = region_strdup(cfg_parser->opt->region, $2); }
386   | VAR_XFRDIR STRING
387     { cfg_parser->opt->xfrdir = region_strdup(cfg_parser->opt->region, $2); }
388   | VAR_XFRD_RELOAD_TIMEOUT number
389     { cfg_parser->opt->xfrd_reload_timeout = (int)$2; }
390   | VAR_VERBOSITY number
391     { cfg_parser->opt->verbosity = (int)$2; }
392   | VAR_RRL_SIZE number
393     {
394 #ifdef RATELIMIT
395       if ($2 > 0) {
396         cfg_parser->opt->rrl_size = (size_t)$2;
397       } else {
398         yyerror("expected a number greater than zero");
399       }
400 #endif
401     }
402   | VAR_RRL_RATELIMIT number
403     {
404 #ifdef RATELIMIT
405       cfg_parser->opt->rrl_ratelimit = (size_t)$2;
406 #endif
407     }
408   | VAR_RRL_SLIP number
409     {
410 #ifdef RATELIMIT
411       cfg_parser->opt->rrl_slip = (size_t)$2;
412 #endif
413     }
414   | VAR_RRL_IPV4_PREFIX_LENGTH number
415     {
416 #ifdef RATELIMIT
417       if ($2 > 32) {
418         yyerror("invalid IPv4 prefix length");
419       } else {
420         cfg_parser->opt->rrl_ipv4_prefix_length = (size_t)$2;
421       }
422 #endif
423     }
424   | VAR_RRL_IPV6_PREFIX_LENGTH number
425     {
426 #ifdef RATELIMIT
427       if ($2 > 64) {
428         yyerror("invalid IPv6 prefix length");
429       } else {
430         cfg_parser->opt->rrl_ipv6_prefix_length = (size_t)$2;
431       }
432 #endif
433     }
434   | VAR_RRL_WHITELIST_RATELIMIT number
435     {
436 #ifdef RATELIMIT
437       cfg_parser->opt->rrl_whitelist_ratelimit = (size_t)$2;
438 #endif
439     }
440   | VAR_ZONEFILES_CHECK boolean
441     { cfg_parser->opt->zonefiles_check = $2; }
442   | VAR_ZONEFILES_WRITE number
443     { cfg_parser->opt->zonefiles_write = (int)$2; }
444   | VAR_LOG_TIME_ASCII boolean
445     {
446       cfg_parser->opt->log_time_ascii = $2;
447       log_time_asc = cfg_parser->opt->log_time_ascii;
448     }
449   | VAR_ROUND_ROBIN boolean
450     {
451       cfg_parser->opt->round_robin = $2;
452       round_robin = cfg_parser->opt->round_robin;
453     }
454   | VAR_MINIMAL_RESPONSES boolean
455     {
456       cfg_parser->opt->minimal_responses = $2;
457       minimal_responses = cfg_parser->opt->minimal_responses;
458     }
459   | VAR_CONFINE_TO_ZONE boolean
460     { cfg_parser->opt->confine_to_zone = $2; }
461   | VAR_REFUSE_ANY boolean
462     { cfg_parser->opt->refuse_any = $2; }
463   | VAR_TLS_SERVICE_KEY STRING
464     { cfg_parser->opt->tls_service_key = region_strdup(cfg_parser->opt->region, $2); }
465   | VAR_TLS_SERVICE_OCSP STRING
466     { cfg_parser->opt->tls_service_ocsp = region_strdup(cfg_parser->opt->region, $2); }
467   | VAR_TLS_SERVICE_PEM STRING
468     { cfg_parser->opt->tls_service_pem = region_strdup(cfg_parser->opt->region, $2); }
469   | VAR_TLS_PORT number
470     {
471       /* port number, stored as string */
472       char buf[16];
473       (void)snprintf(buf, sizeof(buf), "%lld", $2);
474       cfg_parser->opt->tls_port = region_strdup(cfg_parser->opt->region, buf);
475     }
476   | VAR_TLS_CERT_BUNDLE STRING
477     { cfg_parser->opt->tls_cert_bundle = region_strdup(cfg_parser->opt->region, $2); }
478   | VAR_ANSWER_COOKIE boolean
479     { cfg_parser->opt->answer_cookie = $2; }
480   | VAR_COOKIE_SECRET STRING
481     { cfg_parser->opt->cookie_secret = region_strdup(cfg_parser->opt->region, $2); }
482   | VAR_COOKIE_SECRET_FILE STRING
483     { cfg_parser->opt->cookie_secret_file = region_strdup(cfg_parser->opt->region, $2); }
484   | VAR_XFRD_TCP_MAX number
485     { cfg_parser->opt->xfrd_tcp_max = (int)$2; }
486   | VAR_XFRD_TCP_PIPELINE number
487     { cfg_parser->opt->xfrd_tcp_pipeline = (int)$2; }
488   | VAR_CPU_AFFINITY cpus
489     {
490       cfg_parser->opt->cpu_affinity = $2;
491     }
492   | service_cpu_affinity number
493     {
494       if($2 < 0) {
495         yyerror("expected a non-negative number");
496         YYABORT;
497       } else {
498         struct cpu_map_option *opt, *tail;
499 
500         opt = cfg_parser->opt->service_cpu_affinity;
501         while(opt && opt->service != $1) { opt = opt->next; }
502 
503         if(opt) {
504           opt->cpu = $2;
505         } else {
506           opt = region_alloc_zero(cfg_parser->opt->region, sizeof(*opt));
507           opt->service = (int)$1;
508           opt->cpu = (int)$2;
509 
510           tail = cfg_parser->opt->service_cpu_affinity;
511           if(tail) {
512             while(tail->next) { tail = tail->next; }
513             tail->next = opt;
514           } else {
515             cfg_parser->opt->service_cpu_affinity = opt;
516           }
517         }
518       }
519     }
520   ;
521 
522 socket_options:
523   | socket_options socket_option ;
524 
525 socket_option:
526     VAR_SERVERS STRING
527     {
528       char *tok, *ptr, *str;
529       struct range_option *servers = NULL;
530       long long first, last;
531 
532       /* user may specify "0 1", "0" "1", 0 1 or a combination thereof */
533       for(str = $2; (tok = strtok_r(str, " \t", &ptr)); str = NULL) {
534         struct range_option *opt =
535           region_alloc(cfg_parser->opt->region, sizeof(*opt));
536         first = last = 0;
537         if(!parse_range(tok, &first, &last)) {
538           yyerror("invalid server range '%s'", tok);
539           YYABORT;
540         }
541         assert(first >= 0);
542         assert(last >= 0);
543         opt->next = NULL;
544         opt->first = (int)first;
545         opt->last = (int)last;
546         if(servers) {
547           servers = servers->next = opt;
548         } else {
549           servers = cfg_parser->ip->servers = opt;
550         }
551       }
552     }
553   | VAR_BINDTODEVICE boolean
554     { cfg_parser->ip->dev = $2; }
555   | VAR_SETFIB number
556     { cfg_parser->ip->fib = $2; }
557   ;
558 
559 cpus:
560     { $$ = NULL; }
561   | cpus STRING
562     {
563       char *tok, *ptr, *str;
564       struct cpu_option *tail;
565       long long cpu;
566 
567       str = $2;
568       $$ = tail = $1;
569       if(tail) {
570         while(tail->next) { tail = tail->next; }
571       }
572 
573       /* Users may specify "0 1", "0" "1", 0 1 or a combination thereof. */
574       for(str = $2; (tok = strtok_r(str, " \t", &ptr)); str = NULL) {
575         struct cpu_option *opt =
576           region_alloc_zero(cfg_parser->opt->region, sizeof(*opt));
577         cpu = 0;
578         if(!parse_number(tok, &cpu) || cpu < 0) {
579           yyerror("expected a positive number");
580           YYABORT;
581         }
582         assert(cpu >=0);
583         opt->cpu = (int)cpu;
584         if(tail) {
585           tail->next = opt;
586           tail = opt;
587         } else {
588           $$ = tail = opt;
589         }
590       }
591     }
592   ;
593 
594 service_cpu_affinity:
595     VAR_XFRD_CPU_AFFINITY
596     { $$ = -1; }
597   | VAR_SERVER_CPU_AFFINITY
598     {
599       if($1 <= 0) {
600         yyerror("invalid server identifier");
601         YYABORT;
602       }
603       $$ = $1;
604     }
605   ;
606 
607 dnstap:
608     VAR_DNSTAP dnstap_block ;
609 
610 dnstap_block:
611     dnstap_block dnstap_option | ;
612 
613 dnstap_option:
614     VAR_DNSTAP_ENABLE boolean
615     { cfg_parser->opt->dnstap_enable = $2; }
616   | VAR_DNSTAP_SOCKET_PATH STRING
617     { cfg_parser->opt->dnstap_socket_path = region_strdup(cfg_parser->opt->region, $2); }
618   | VAR_DNSTAP_SEND_IDENTITY boolean
619     { cfg_parser->opt->dnstap_send_identity = $2; }
620   | VAR_DNSTAP_SEND_VERSION boolean
621     { cfg_parser->opt->dnstap_send_version = $2; }
622   | VAR_DNSTAP_IDENTITY STRING
623     { cfg_parser->opt->dnstap_identity = region_strdup(cfg_parser->opt->region, $2); }
624   | VAR_DNSTAP_VERSION STRING
625     { cfg_parser->opt->dnstap_version = region_strdup(cfg_parser->opt->region, $2); }
626   | VAR_DNSTAP_LOG_AUTH_QUERY_MESSAGES boolean
627     { cfg_parser->opt->dnstap_log_auth_query_messages = $2; }
628   | VAR_DNSTAP_LOG_AUTH_RESPONSE_MESSAGES boolean
629     { cfg_parser->opt->dnstap_log_auth_response_messages = $2; }
630   ;
631 
632 remote_control:
633     VAR_REMOTE_CONTROL remote_control_block ;
634 
635 remote_control_block:
636     remote_control_block remote_control_option | ;
637 
638 remote_control_option:
639     VAR_CONTROL_ENABLE boolean
640     { cfg_parser->opt->control_enable = $2; }
641   | VAR_CONTROL_INTERFACE ip_address
642     {
643       struct ip_address_option *ip = cfg_parser->opt->control_interface;
644       if(ip == NULL) {
645         cfg_parser->opt->control_interface = $2;
646       } else {
647         while(ip->next != NULL) { ip = ip->next; }
648         ip->next = $2;
649       }
650     }
651   | VAR_CONTROL_PORT number
652     {
653       if($2 == 0) {
654         yyerror("control port number expected");
655       } else {
656         cfg_parser->opt->control_port = (int)$2;
657       }
658     }
659   | VAR_SERVER_KEY_FILE STRING
660     { cfg_parser->opt->server_key_file = region_strdup(cfg_parser->opt->region, $2); }
661   | VAR_SERVER_CERT_FILE STRING
662     { cfg_parser->opt->server_cert_file = region_strdup(cfg_parser->opt->region, $2); }
663   | VAR_CONTROL_KEY_FILE STRING
664     { cfg_parser->opt->control_key_file = region_strdup(cfg_parser->opt->region, $2); }
665   | VAR_CONTROL_CERT_FILE STRING
666     { cfg_parser->opt->control_cert_file = region_strdup(cfg_parser->opt->region, $2); }
667   ;
668 
669 tls_auth:
670     VAR_TLS_AUTH
671       {
672         tls_auth_options_type *tls_auth = tls_auth_options_create(cfg_parser->opt->region);
673         assert(cfg_parser->tls_auth == NULL);
674         cfg_parser->tls_auth = tls_auth;
675       }
676       tls_auth_block
677     {
678       struct tls_auth_options *tls_auth = cfg_parser->tls_auth;
679       if(tls_auth->name == NULL) {
680         yyerror("tls-auth has no name");
681       } else if(tls_auth->auth_domain_name == NULL) {
682         yyerror("tls-auth %s has no auth-domain-name", tls_auth->name);
683       } else if(tls_auth_options_find(cfg_parser->opt, tls_auth->name)) {
684         yyerror("duplicate tls-auth %s", tls_auth->name);
685       } else {
686       	tls_auth_options_insert(cfg_parser->opt, tls_auth);
687         cfg_parser->tls_auth = NULL;
688       }
689     } ;
690 
691 tls_auth_block:
692     tls_auth_block tls_auth_option | ;
693 
694 tls_auth_option:
695     VAR_NAME STRING
696     {
697       dname_type *dname;
698       dname = (dname_type *)dname_parse(cfg_parser->opt->region, $2);
699       cfg_parser->tls_auth->name = region_strdup(cfg_parser->opt->region, $2);
700       if(dname == NULL) {
701         yyerror("bad tls-auth name %s", $2);
702       } else {
703         region_recycle(cfg_parser->opt->region, dname, dname_total_size(dname));
704       }
705     }
706   | VAR_TLS_AUTH_DOMAIN_NAME STRING
707     {
708       cfg_parser->tls_auth->auth_domain_name = region_strdup(cfg_parser->opt->region, $2);
709     }
710   | VAR_TLS_AUTH_CLIENT_CERT STRING
711     {
712 	    cfg_parser->tls_auth->client_cert = region_strdup(cfg_parser->opt->region, $2);
713     }
714   | VAR_TLS_AUTH_CLIENT_KEY STRING
715     {
716 	    cfg_parser->tls_auth->client_key = region_strdup(cfg_parser->opt->region, $2);
717     }
718   | VAR_TLS_AUTH_CLIENT_KEY_PW STRING
719     {
720 	    cfg_parser->tls_auth->client_key_pw = region_strdup(cfg_parser->opt->region, $2);
721     }
722   ;
723 
724 key:
725     VAR_KEY
726       {
727         key_options_type *key = key_options_create(cfg_parser->opt->region);
728         key->algorithm = region_strdup(cfg_parser->opt->region, "sha256");
729         assert(cfg_parser->key == NULL);
730         cfg_parser->key = key;
731       }
732       key_block
733     {
734       struct key_options *key = cfg_parser->key;
735       if(key->name == NULL) {
736         yyerror("tsig key has no name");
737       } else if(key->algorithm == NULL) {
738         yyerror("tsig key %s has no algorithm", key->name);
739       } else if(key->secret == NULL) {
740         yyerror("tsig key %s has no secret blob", key->name);
741       } else if(key_options_find(cfg_parser->opt, key->name)) {
742         yyerror("duplicate tsig key %s", key->name);
743       } else {
744         key_options_insert(cfg_parser->opt, key);
745         cfg_parser->key = NULL;
746       }
747     } ;
748 
749 key_block:
750     key_block key_option | ;
751 
752 key_option:
753     VAR_NAME STRING
754     {
755       dname_type *dname;
756 
757       dname = (dname_type *)dname_parse(cfg_parser->opt->region, $2);
758       cfg_parser->key->name = region_strdup(cfg_parser->opt->region, $2);
759       if(dname == NULL) {
760         yyerror("bad tsig key name %s", $2);
761       } else {
762         region_recycle(cfg_parser->opt->region, dname, dname_total_size(dname));
763       }
764     }
765   | VAR_ALGORITHM STRING
766     {
767       if(tsig_get_algorithm_by_name($2) == NULL) {
768         yyerror("bad tsig key algorithm %s", $2);
769       } else {
770         cfg_parser->key->algorithm = region_strdup(cfg_parser->opt->region, $2);
771       }
772     }
773   | VAR_SECRET STRING
774     {
775       uint8_t data[16384];
776       int size;
777 
778       cfg_parser->key->secret = region_strdup(cfg_parser->opt->region, $2);
779       size = b64_pton($2, data, sizeof(data));
780       if(size == -1) {
781         yyerror("cannot base64 decode tsig secret %s",
782           cfg_parser->key->name?
783           cfg_parser->key->name:"");
784       } else if(size != 0) {
785         memset(data, 0xdd, size); /* wipe secret */
786       }
787     } ;
788 
789 
790 zone:
791     VAR_ZONE
792       {
793         assert(cfg_parser->pattern == NULL);
794         assert(cfg_parser->zone == NULL);
795         cfg_parser->zone = zone_options_create(cfg_parser->opt->region);
796         cfg_parser->zone->part_of_config = 1;
797         cfg_parser->zone->pattern = cfg_parser->pattern =
798           pattern_options_create(cfg_parser->opt->region);
799         cfg_parser->zone->pattern->implicit = 1;
800       }
801     zone_block
802     {
803       assert(cfg_parser->zone != NULL);
804       if(cfg_parser->zone->name == NULL) {
805         yyerror("zone has no name");
806       } else if(!nsd_options_insert_zone(cfg_parser->opt, cfg_parser->zone)) {
807         yyerror("duplicate zone %s", cfg_parser->zone->name);
808       } else if(!nsd_options_insert_pattern(cfg_parser->opt, cfg_parser->zone->pattern)) {
809         yyerror("duplicate pattern %s", cfg_parser->zone->pattern->pname);
810       }
811       cfg_parser->pattern = NULL;
812       cfg_parser->zone = NULL;
813     } ;
814 
815 zone_block:
816     zone_block zone_option | ;
817 
818 zone_option:
819     VAR_NAME STRING
820     {
821       const char *marker = PATTERN_IMPLICIT_MARKER;
822       char *pname = region_alloc(cfg_parser->opt->region, strlen($2) + strlen(marker) + 1);
823       memmove(pname, marker, strlen(marker));
824       memmove(pname + strlen(marker), $2, strlen($2) + 1);
825       cfg_parser->zone->pattern->pname = pname;
826       cfg_parser->zone->name = region_strdup(cfg_parser->opt->region, $2);
827       if(pattern_options_find(cfg_parser->opt, pname)) {
828         yyerror("zone %s cannot be created because implicit pattern %s "
829                     "already exists", $2, pname);
830       }
831     }
832   | pattern_or_zone_option ;
833 
834 pattern:
835     VAR_PATTERN
836       {
837         assert(cfg_parser->pattern == NULL);
838         cfg_parser->pattern = pattern_options_create(cfg_parser->opt->region);
839       }
840       pattern_block
841     {
842       pattern_options_type *pattern = cfg_parser->pattern;
843       if(pattern->pname == NULL) {
844         yyerror("pattern has no name");
845       } else if(!nsd_options_insert_pattern(cfg_parser->opt, pattern)) {
846         yyerror("duplicate pattern %s", pattern->pname);
847       }
848       cfg_parser->pattern = NULL;
849     } ;
850 
851 pattern_block:
852     pattern_block pattern_option | ;
853 
854 pattern_option:
855     VAR_NAME STRING
856     {
857       if(strchr($2, ' ')) {
858         yyerror("space is not allowed in pattern name: '%s'", $2);
859       }
860       cfg_parser->pattern->pname = region_strdup(cfg_parser->opt->region, $2);
861     }
862   | pattern_or_zone_option ;
863 
864 pattern_or_zone_option:
865     VAR_RRL_WHITELIST STRING
866     {
867 #ifdef RATELIMIT
868       cfg_parser->pattern->rrl_whitelist |= rrlstr2type($2);
869 #endif
870     }
871   | VAR_ZONEFILE STRING
872     { cfg_parser->pattern->zonefile = region_strdup(cfg_parser->opt->region, $2); }
873   | VAR_ZONESTATS STRING
874     { cfg_parser->pattern->zonestats = region_strdup(cfg_parser->opt->region, $2); }
875   | VAR_SIZE_LIMIT_XFR number
876     {
877       if($2 > 0) {
878         cfg_parser->pattern->size_limit_xfr = (int)$2;
879       } else {
880         yyerror("expected a number greater than zero");
881       }
882     }
883   | VAR_MULTI_MASTER_CHECK boolean
884     { cfg_parser->pattern->multi_master_check = (int)$2; }
885   | VAR_INCLUDE_PATTERN STRING
886     { config_apply_pattern(cfg_parser->pattern, $2); }
887   | VAR_REQUEST_XFR STRING STRING
888     {
889       acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, $3);
890       if(acl->blocked)
891         yyerror("blocked address used for request-xfr");
892       if(acl->rangetype != acl_range_single)
893         yyerror("address range used for request-xfr");
894       append_acl(&cfg_parser->pattern->request_xfr, acl);
895     }
896 	tlsauth_option
897 	{ }
898   | VAR_REQUEST_XFR VAR_AXFR STRING STRING
899     {
900       acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $3, $4);
901       acl->use_axfr_only = 1;
902       if(acl->blocked)
903         yyerror("blocked address used for request-xfr");
904       if(acl->rangetype != acl_range_single)
905         yyerror("address range used for request-xfr");
906       append_acl(&cfg_parser->pattern->request_xfr, acl);
907     }
908 	tlsauth_option
909 	{ }
910   | VAR_REQUEST_XFR VAR_UDP STRING STRING
911     {
912       acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $3, $4);
913       acl->allow_udp = 1;
914       if(acl->blocked)
915         yyerror("blocked address used for request-xfr");
916       if(acl->rangetype != acl_range_single)
917         yyerror("address range used for request-xfr");
918       append_acl(&cfg_parser->pattern->request_xfr, acl);
919     }
920   | VAR_ALLOW_NOTIFY STRING STRING
921     {
922       acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, $3);
923       append_acl(&cfg_parser->pattern->allow_notify, acl);
924     }
925   | VAR_NOTIFY STRING STRING
926     {
927       acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, $3);
928       if(acl->blocked)
929         yyerror("blocked address used for notify");
930       if(acl->rangetype != acl_range_single)
931         yyerror("address range used for notify");
932       append_acl(&cfg_parser->pattern->notify, acl);
933     }
934   | VAR_PROVIDE_XFR STRING STRING
935     {
936       acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, $3);
937       append_acl(&cfg_parser->pattern->provide_xfr, acl);
938     }
939   | VAR_ALLOW_QUERY STRING STRING
940     {
941       acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, $3);
942       append_acl(&cfg_parser->pattern->allow_query, acl);
943     }
944   | VAR_OUTGOING_INTERFACE STRING
945     {
946       acl_options_type *acl = parse_acl_info(cfg_parser->opt->region, $2, "NOKEY");
947       append_acl(&cfg_parser->pattern->outgoing_interface, acl);
948     }
949   | VAR_ALLOW_AXFR_FALLBACK boolean
950     {
951       cfg_parser->pattern->allow_axfr_fallback = $2;
952       cfg_parser->pattern->allow_axfr_fallback_is_default = 0;
953     }
954   | VAR_NOTIFY_RETRY number
955     {
956       cfg_parser->pattern->notify_retry = $2;
957       cfg_parser->pattern->notify_retry_is_default = 0;
958     }
959   | VAR_MAX_REFRESH_TIME number
960     {
961       cfg_parser->pattern->max_refresh_time = $2;
962       cfg_parser->pattern->max_refresh_time_is_default = 0;
963     }
964   | VAR_MIN_REFRESH_TIME number
965     {
966       cfg_parser->pattern->min_refresh_time = $2;
967       cfg_parser->pattern->min_refresh_time_is_default = 0;
968     }
969   | VAR_MAX_RETRY_TIME number
970     {
971       cfg_parser->pattern->max_retry_time = $2;
972       cfg_parser->pattern->max_retry_time_is_default = 0;
973     }
974   | VAR_MIN_RETRY_TIME number
975     {
976       cfg_parser->pattern->min_retry_time = $2;
977       cfg_parser->pattern->min_retry_time_is_default = 0;
978     }
979   | VAR_MIN_EXPIRE_TIME STRING
980     {
981       long long num;
982       uint8_t expr;
983 
984       if (!parse_expire_expr($2, &num, &expr)) {
985         yyerror("expected an expire time in seconds or \"refresh+retry+1\"");
986         YYABORT; /* trigger a parser error */
987       }
988       cfg_parser->pattern->min_expire_time = num;
989       cfg_parser->pattern->min_expire_time_expr = expr;
990     }
991   | VAR_STORE_IXFR boolean
992     {
993       cfg_parser->pattern->store_ixfr = $2;
994       cfg_parser->pattern->store_ixfr_is_default = 0;
995     }
996   | VAR_IXFR_SIZE number
997     {
998       cfg_parser->pattern->ixfr_size = $2;
999       cfg_parser->pattern->ixfr_size_is_default = 0;
1000     }
1001   | VAR_IXFR_NUMBER number
1002     {
1003       cfg_parser->pattern->ixfr_number = $2;
1004       cfg_parser->pattern->ixfr_number_is_default = 0;
1005     }
1006   | VAR_CREATE_IXFR boolean
1007     {
1008       cfg_parser->pattern->create_ixfr = $2;
1009       cfg_parser->pattern->create_ixfr_is_default = 0;
1010     }
1011   | VAR_VERIFY_ZONE boolean
1012     { cfg_parser->pattern->verify_zone = $2; }
1013   | VAR_VERIFIER command
1014     { cfg_parser->pattern->verifier = $2; }
1015   | VAR_VERIFIER_FEED_ZONE boolean
1016     { cfg_parser->pattern->verifier_feed_zone = $2; }
1017   | VAR_VERIFIER_TIMEOUT number
1018     { cfg_parser->pattern->verifier_timeout = $2; } ;
1019 
1020 verify:
1021     VAR_VERIFY verify_block ;
1022 
1023 verify_block:
1024     verify_block verify_option | ;
1025 
1026 verify_option:
1027     VAR_ENABLE boolean
1028     { cfg_parser->opt->verify_enable = $2; }
1029   | VAR_IP_ADDRESS ip_address
1030     {
1031       struct ip_address_option *ip = cfg_parser->opt->verify_ip_addresses;
1032       if(!ip) {
1033         cfg_parser->opt->verify_ip_addresses = $2;
1034       } else {
1035         while(ip->next) { ip = ip->next; }
1036         ip->next = $2;
1037       }
1038     }
1039   | VAR_PORT number
1040     {
1041       /* port number, stored as a string */
1042       char buf[16];
1043       (void)snprintf(buf, sizeof(buf), "%lld", $2);
1044       cfg_parser->opt->verify_port = region_strdup(cfg_parser->opt->region, buf);
1045     }
1046   | VAR_VERIFY_ZONES boolean
1047     { cfg_parser->opt->verify_zones = $2; }
1048   | VAR_VERIFIER command
1049     { cfg_parser->opt->verifier = $2; }
1050   | VAR_VERIFIER_COUNT number
1051     { cfg_parser->opt->verifier_count = (int)$2; }
1052   | VAR_VERIFIER_TIMEOUT number
1053     { cfg_parser->opt->verifier_timeout = (int)$2; }
1054   | VAR_VERIFIER_FEED_ZONE boolean
1055     { cfg_parser->opt->verifier_feed_zone = $2; } ;
1056 
1057 command:
1058     STRING arguments
1059     {
1060       char **argv;
1061       size_t argc = 1;
1062       for(struct component *i = $2; i; i = i->next) {
1063         argc++;
1064       }
1065       argv = region_alloc_zero(
1066         cfg_parser->opt->region, (argc + 1) * sizeof(char *));
1067       argc = 0;
1068       argv[argc++] = $1;
1069       for(struct component *j, *i = $2; i; i = j) {
1070         j = i->next;
1071         argv[argc++] = i->str;
1072         region_recycle(cfg_parser->opt->region, i, sizeof(*i));
1073       }
1074       $$ = argv;
1075     } ;
1076 
1077 arguments:
1078     { $$ = NULL; }
1079   | arguments STRING
1080     {
1081       struct component *comp = region_alloc_zero(
1082         cfg_parser->opt->region, sizeof(*comp));
1083       comp->str = region_strdup(cfg_parser->opt->region, $2);
1084       if($1) {
1085         struct component *tail = $1;
1086         while(tail->next) {
1087          tail = tail->next;
1088         }
1089         tail->next = comp;
1090         $$ = $1;
1091       } else {
1092         $$ = comp;
1093       }
1094     } ;
1095 
1096 ip_address:
1097     STRING
1098     {
1099       struct ip_address_option *ip = region_alloc_zero(
1100         cfg_parser->opt->region, sizeof(*ip));
1101       ip->address = region_strdup(cfg_parser->opt->region, $1);
1102       ip->fib = -1;
1103       $$ = ip;
1104     } ;
1105 
1106 number:
1107     STRING
1108     {
1109       if(!parse_number($1, &$$)) {
1110         yyerror("expected a number");
1111         YYABORT; /* trigger a parser error */
1112       }
1113     } ;
1114 
1115 boolean:
1116     STRING
1117     {
1118       if(!parse_boolean($1, &$$)) {
1119         yyerror("expected yes or no");
1120         YYABORT; /* trigger a parser error */
1121       }
1122     } ;
1123 
1124 tlsauth_option:
1125 	| STRING
1126 	{ char *tls_auth_name = region_strdup(cfg_parser->opt->region, $1);
1127 	  add_to_last_acl(&cfg_parser->pattern->request_xfr, tls_auth_name);} ;
1128 
1129 %%
1130 
1131 static void
1132 append_acl(struct acl_options **list, struct acl_options *acl)
1133 {
1134 	assert(list != NULL);
1135 
1136 	if(*list == NULL) {
1137 		*list = acl;
1138 	} else {
1139 		struct acl_options *tail = *list;
1140 		while(tail->next != NULL)
1141 			tail = tail->next;
1142 		tail->next = acl;
1143 	}
1144 }
1145 
1146 static void
1147 add_to_last_acl(struct acl_options **list, char *tls_auth_name)
1148 {
1149 	struct acl_options *tail = *list;
1150 	assert(list != NULL);
1151 	assert(*list != NULL);
1152 	while(tail->next != NULL)
1153 		tail = tail->next;
1154 	tail->tls_auth_name = tls_auth_name;
1155 }
1156 
1157 static int
1158 parse_boolean(const char *str, int *bln)
1159 {
1160 	if(strcmp(str, "yes") == 0) {
1161 		*bln = 1;
1162 	} else if(strcmp(str, "no") == 0) {
1163 		*bln = 0;
1164 	} else {
1165 		return 0;
1166 	}
1167 
1168 	return 1;
1169 }
1170 
1171 static int
1172 parse_expire_expr(const char *str, long long *num, uint8_t *expr)
1173 {
1174 	if(parse_number(str, num)) {
1175 		*expr = EXPIRE_TIME_HAS_VALUE;
1176 		return 1;
1177 	}
1178 	if(strcmp(str, REFRESHPLUSRETRYPLUS1_STR) == 0) {
1179 		*num = 0;
1180 		*expr = REFRESHPLUSRETRYPLUS1;
1181 		return 1;
1182 	}
1183 	return 0;
1184 }
1185 
1186 static int
1187 parse_number(const char *str, long long *num)
1188 {
1189 	/* ensure string consists entirely of digits */
1190 	size_t pos = 0;
1191 	while(str[pos] >= '0' && str[pos] <= '9') {
1192 		pos++;
1193 	}
1194 
1195 	if(pos != 0 && str[pos] == '\0') {
1196 		*num = strtoll(str, NULL, 10);
1197 		return 1;
1198 	}
1199 
1200 	return 0;
1201 }
1202 
1203 static int
1204 parse_range(const char *str, long long *low, long long *high)
1205 {
1206 	const char *ptr = str;
1207 	long long num[2];
1208 
1209 	/* require range to begin with a number */
1210 	if(*ptr < '0' || *ptr > '9') {
1211 		return 0;
1212 	}
1213 
1214 	num[0] = strtoll(ptr, (char **)&ptr, 10);
1215 
1216 	/* require number to be followed by nothing at all or a dash */
1217 	if(*ptr == '\0') {
1218 		*low = num[0];
1219 		*high = num[0];
1220 		return 1;
1221 	} else if(*ptr != '-') {
1222 		return 0;
1223 	}
1224 
1225 	++ptr;
1226 	/* require dash to be followed by a number */
1227 	if(*ptr < '0' || *ptr > '9') {
1228 		return 0;
1229 	}
1230 
1231 	num[1] = strtoll(ptr, (char **)&ptr, 10);
1232 
1233 	/* require number to be followed by nothing at all */
1234 	if(*ptr == '\0') {
1235 		if(num[0] < num[1]) {
1236 			*low = num[0];
1237 			*high = num[1];
1238 		} else {
1239 			*low = num[1];
1240 			*high = num[0];
1241 		}
1242 		return 1;
1243 	}
1244 
1245 	return 0;
1246 }
1247