]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind/bin/named/ns_parser.y
This commit was generated by cvs2svn to compensate for changes in r55099,
[FreeBSD/FreeBSD.git] / contrib / bind / bin / named / ns_parser.y
1 %{
2 #if !defined(lint) && !defined(SABER)
3 static char rcsid[] = "$Id: ns_parser.y,v 8.51 1999/11/12 05:29:18 vixie Exp $";
4 #endif /* not lint */
5
6 /*
7  * Copyright (c) 1996-1999 by Internet Software Consortium.
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
14  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
16  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
17  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20  * SOFTWARE.
21  */
22
23 /* Global C stuff goes here. */
24
25 #include "port_before.h"
26
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/un.h>
30
31 #include <netinet/in.h>
32 #include <arpa/nameser.h>
33 #include <arpa/inet.h>
34
35 #include <ctype.h>
36 #include <limits.h>
37 #include <resolv.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <syslog.h>
42 #include <time.h>
43
44 #include <isc/eventlib.h>
45 #include <isc/logging.h>
46
47 #include <isc/dst.h>
48
49 #include "port_after.h"
50
51 #include "named.h"
52 #include "ns_parseutil.h"
53 #include "ns_lexer.h"
54
55 #define SYM_ZONE        0x010000
56 #define SYM_SERVER      0x020000
57 #define SYM_KEY         0x030000
58 #define SYM_ACL         0x040000
59 #define SYM_CHANNEL     0x050000
60 #define SYM_PORT        0x060000
61
62 #define SYMBOL_TABLE_SIZE 29989         /* should always be prime */
63 static symbol_table symtab;
64
65 #define AUTH_TABLE_SIZE 397             /* should always be prime */
66 static symbol_table authtab = NULL;
67
68 static zone_config current_zone;
69 static int should_install;
70
71 static options current_options;
72 static int seen_options;
73
74 static controls current_controls;
75
76 static topology_config current_topology;
77 static int seen_topology;
78
79 static server_config current_server;
80 static int seen_server;
81
82 static char *current_algorithm;
83 static char *current_secret;
84
85 static log_config current_logging;
86 static int current_category;
87 static int chan_type;
88 static int chan_level;
89 static u_int chan_flags;
90 static int chan_facility;
91 static char *chan_name;
92 static int chan_versions;
93 static u_long chan_max_size;
94
95 static log_channel lookup_channel(char *);
96 static void define_channel(char *, log_channel);
97 static char *canonical_name(char *);
98
99 int yyparse();
100         
101 %}
102
103 %union {
104         char *                  cp;
105         int                     s_int;
106         long                    num;
107         u_long                  ul_int;
108         u_int16_t               us_int;
109         struct in_addr          ip_addr;
110         ip_match_element        ime;
111         ip_match_list           iml;
112         rrset_order_list        rol;
113         rrset_order_element     roe;
114         struct dst_key *        keyi;
115         enum axfr_format        axfr_fmt;
116 }
117
118 /* Lexical analyzer return values. */
119 %token                  L_EOS
120 %token  <ip_addr>       L_IPADDR
121 %token  <num>           L_NUMBER
122 %token  <cp>            L_STRING
123 %token  <cp>            L_QSTRING
124 %token                  L_END_INCLUDE
125
126 /* Include support */
127 %token                  T_INCLUDE
128
129 /* Items related to the "options" statement: */
130 %token                  T_OPTIONS
131 %token                  T_DIRECTORY T_PIDFILE T_NAMED_XFER
132 %token                  T_DUMP_FILE T_STATS_FILE T_MEMSTATS_FILE
133 %token                  T_FAKE_IQUERY T_RECURSION T_FETCH_GLUE 
134 %token                  T_QUERY_SOURCE T_LISTEN_ON T_PORT T_ADDRESS
135 %token                  T_RRSET_ORDER T_ORDER T_NAME T_CLASS
136 %token                  T_CONTROLS T_INET T_UNIX T_PERM T_OWNER T_GROUP T_ALLOW
137 %type   <us_int>        in_port
138 %type   <us_int>        maybe_port
139 %type   <us_int>        maybe_zero_port
140 %type   <us_int>        maybe_wild_port
141 %type   <ip_addr>       maybe_wild_addr
142 %token                  T_DATASIZE T_STACKSIZE T_CORESIZE
143 %token                  T_DEFAULT T_UNLIMITED
144 %token                  T_FILES T_VERSION
145 %token                  T_HOSTSTATS T_DEALLOC_ON_EXIT
146 %token                  T_TRANSFERS_IN T_TRANSFERS_OUT T_TRANSFERS_PER_NS
147 %token                  T_TRANSFER_FORMAT T_MAX_TRANSFER_TIME_IN
148 %token                  T_SERIAL_QUERIES T_ONE_ANSWER T_MANY_ANSWERS
149 %type   <axfr_fmt>      transfer_format
150 %token                  T_NOTIFY T_AUTH_NXDOMAIN T_MULTIPLE_CNAMES T_USE_IXFR T_MAINTAIN_IXFR_BASE
151 %token                  T_CLEAN_INTERVAL T_INTERFACE_INTERVAL T_STATS_INTERVAL T_MAX_LOG_SIZE_IXFR
152 %token                  T_HEARTBEAT T_USE_ID_POOL
153 %token                  T_MAX_NCACHE_TTL T_HAS_OLD_CLIENTS T_RFC2308_TYPE1
154 %token                  T_LAME_TTL T_MIN_ROOTS
155 %token                  T_TREAT_CR_AS_SPACE
156
157 /* Items used for the "logging" statement: */
158 %token                  T_LOGGING T_CATEGORY T_CHANNEL T_SEVERITY T_DYNAMIC
159 %token                  T_FILE T_VERSIONS T_SIZE
160 %token                  T_SYSLOG T_DEBUG T_NULL_OUTPUT
161 %token                  T_PRINT_TIME T_PRINT_CATEGORY T_PRINT_SEVERITY
162 %type   <s_int>         category
163 %type   <cp>            category_name channel_name facility_name
164 %type   <s_int>         maybe_syslog_facility
165
166 /* Items used for the "sortlist" statement: */
167 %token                  T_SORTLIST
168
169 /* Items used for the "topology" statement: */
170 %token                  T_TOPOLOGY
171
172 %type   <s_int>         ordering_class
173 %type   <s_int>         ordering_type
174 %type   <cp>            ordering_name
175 %type   <rol>           rrset_ordering_list
176 %type   <roe>           rrset_ordering_element
177
178 /* ip_match_list */
179 %type   <ime>           address_match_simple address_match_element address_name
180 %type   <iml>           address_match_list
181
182 /* Items used for "server" statements: */
183 %token                  T_SERVER 
184 %token                  T_LONG_AXFR 
185 %token                  T_BOGUS 
186 %token                  T_TRANSFERS 
187 %token                  T_KEYS
188 %token                  T_SUPPORT_IXFR
189
190 /* Items used for "zone" statements: */
191 %token                  T_ZONE
192 %type   <num>           optional_class
193 %type   <s_int>         zone_type
194 %token                  T_IN T_CHAOS T_HESIOD
195 %token                  T_TYPE
196 %token                  T_MASTER T_SLAVE T_STUB T_RESPONSE
197 %token                  T_HINT
198 %token                  T_MASTERS T_TRANSFER_SOURCE
199 %token                  T_PUBKEY
200 %token                  T_ALSO_NOTIFY
201 %token                  T_DIALUP
202 %token                  T_FILE_IXFR
203 %token                  T_IXFR_TMP
204
205 /* Items used for "trusted-keys" statements: */
206 %token                  T_TRUSTED_KEYS
207
208 /* Items used for access control lists and "allow" clauses: */
209 %token                  T_ACL 
210 %token                  T_ALLOW_UPDATE T_ALLOW_QUERY T_ALLOW_TRANSFER
211 %token                  T_ALLOW_RECURSION
212 %token                  T_BLACKHOLE
213
214 /* Items related to the "key" statement: */
215 %token                  T_SEC_KEY T_ALGID T_SECRET
216 %type   <keyi>          key_ref
217 %type   <cp>            algorithm_id secret
218
219 /* Items used for "size_spec" clauses: */
220 %type   <ul_int>        size_spec
221
222 /* Items used for a "check-names" clause: */
223 %token                  T_CHECK_NAMES
224 %type   <s_int>         check_names_type
225 %type   <s_int>         check_names_opt
226 %token                  T_WARN T_FAIL T_IGNORE
227
228 /* Items used for "forward" clauses: */
229 %token                  T_FORWARD T_FORWARDERS
230 %token                  T_ONLY T_FIRST T_IF_NO_ANSWER T_IF_NO_DOMAIN
231
232 /* Items used for yes/no responses: */
233 %type   <num>           yea_or_nay
234 %token                  T_YES T_TRUE T_NO T_FALSE
235
236 /* Miscellaneous items (used in several places): */
237 %type   <cp>            any_string
238
239 %%
240 config_file: statement_list
241         {
242                 if (EMPTY(current_controls))
243                         ns_ctl_defaults(&current_controls);
244                 ns_ctl_install(&current_controls);
245         }
246         ;
247
248 statement_list: statement
249         | statement_list statement
250         ;
251
252 statement: include_stmt
253         | options_stmt L_EOS
254         | controls_stmt L_EOS
255         | logging_stmt L_EOS
256         | server_stmt L_EOS
257         | zone_stmt L_EOS
258         | trusted_keys_stmt L_EOS
259         | acl_stmt L_EOS
260         | key_stmt L_EOS
261         | L_END_INCLUDE
262         | error L_EOS
263         | error L_END_INCLUDE
264         ;
265
266 include_stmt: T_INCLUDE L_QSTRING L_EOS { lexer_begin_file($2, NULL); }
267         ;
268
269 /*
270  * Options
271  */
272
273 options_stmt: T_OPTIONS 
274         {
275                 if (seen_options)
276                         parser_error(0, "cannot redefine options");
277                 current_options = new_options();
278         }
279         '{' options '}'
280         {
281                 if (!seen_options)
282                         set_options(current_options, 0);
283                 else
284                         free_options(current_options);
285                 current_options = NULL;
286                 seen_options = 1;
287         }
288         ;
289
290 options: option L_EOS
291         | options option L_EOS
292         ;
293
294 option: /* Empty */
295         | T_VERSION L_QSTRING
296         {
297                 if (current_options->version != NULL)
298                         freestr(current_options->version);
299                 current_options->version = $2;
300         }
301         | T_DIRECTORY L_QSTRING
302         {
303                 if (current_options->directory != NULL)
304                         freestr(current_options->directory);
305                 current_options->directory = $2;
306         }
307         | T_NAMED_XFER L_QSTRING
308         {
309                 if (current_options->named_xfer != NULL)
310                         freestr(current_options->named_xfer);
311                 current_options->named_xfer = $2;
312         }
313         | T_PIDFILE L_QSTRING
314         {
315                 if (current_options->pid_filename != NULL)
316                         freestr(current_options->pid_filename);
317                 current_options->pid_filename = $2;
318         }
319         | T_STATS_FILE L_QSTRING
320         {
321                 if (current_options->stats_filename != NULL)
322                         freestr(current_options->stats_filename);
323                 current_options->stats_filename = $2;
324         }
325         | T_MEMSTATS_FILE L_QSTRING
326         {
327                 if (current_options->memstats_filename != NULL)
328                         freestr(current_options->memstats_filename);
329                 current_options->memstats_filename = $2;
330         }
331         | T_DUMP_FILE L_QSTRING
332         {
333                 if (current_options->dump_filename != NULL)
334                         freestr(current_options->dump_filename);
335                 current_options->dump_filename = $2;
336         }
337         | T_FAKE_IQUERY yea_or_nay
338         {
339                 set_global_boolean_option(current_options,
340                         OPTION_FAKE_IQUERY, $2);
341         }
342         | T_RECURSION yea_or_nay
343         {
344                 set_global_boolean_option(current_options,
345                         OPTION_NORECURSE, !$2);
346         }
347         | T_FETCH_GLUE yea_or_nay
348         {
349                 set_global_boolean_option(current_options,
350                         OPTION_NOFETCHGLUE, !$2);
351         }
352         | T_NOTIFY yea_or_nay
353         {
354                 set_global_boolean_option(current_options, 
355                         OPTION_NONOTIFY, !$2);
356         }
357         | T_HOSTSTATS yea_or_nay
358         {
359                 set_global_boolean_option(current_options,
360                         OPTION_HOSTSTATS, $2);
361         }
362         | T_DEALLOC_ON_EXIT yea_or_nay
363         {
364                 set_global_boolean_option(current_options,
365                         OPTION_DEALLOC_ON_EXIT, $2);
366         }
367         | T_USE_IXFR yea_or_nay
368         {
369                 set_global_boolean_option(current_options, OPTION_USE_IXFR, $2);
370         }
371         | T_MAINTAIN_IXFR_BASE yea_or_nay
372         {
373                 set_global_boolean_option(current_options,
374                                           OPTION_MAINTAIN_IXFR_BASE, $2);
375         }
376         | T_HAS_OLD_CLIENTS yea_or_nay
377         {
378                 set_global_boolean_option(current_options,
379                                           OPTION_MAINTAIN_IXFR_BASE, $2);
380                 set_global_boolean_option(current_options,
381                                           OPTION_NORFC2308_TYPE1, $2);
382                 set_global_boolean_option(current_options,
383                                           OPTION_NONAUTH_NXDOMAIN, !$2);
384         }
385         | T_AUTH_NXDOMAIN yea_or_nay
386         {
387                 set_global_boolean_option(current_options, OPTION_NONAUTH_NXDOMAIN,
388                                    !$2);
389         }
390         | T_MULTIPLE_CNAMES yea_or_nay
391         {
392                 set_global_boolean_option(current_options,
393                         OPTION_MULTIPLE_CNAMES, $2);
394         }
395         | T_CHECK_NAMES check_names_type check_names_opt
396         {
397                 current_options->check_names[$2] = (enum severity)$3;
398         }
399         | T_USE_ID_POOL yea_or_nay
400         {
401                 set_global_boolean_option(current_options,
402                                           OPTION_USE_ID_POOL, $2);
403         }
404         | T_RFC2308_TYPE1 yea_or_nay
405         {
406                 set_global_boolean_option(current_options,
407                                           OPTION_NORFC2308_TYPE1, !$2);
408         }
409         | T_LISTEN_ON maybe_port '{' address_match_list '}'
410         {
411                 char port_string[10];
412                 symbol_value value;
413
414                 (void)sprintf(port_string, "%u", $2);
415                 if (lookup_symbol(symtab, port_string, SYM_PORT, NULL))
416                         parser_error(0,
417                                      "cannot redefine listen-on for port %u",
418                                      ntohs($2));
419                 else {
420                         add_listen_on(current_options, $2, $4);
421                         value.pointer = NULL;
422                         define_symbol(symtab, savestr(port_string, 1),
423                                       SYM_PORT, value, SYMBOL_FREE_KEY);
424                 }
425
426         }
427         | T_FORWARD forward_opt
428         | T_FORWARDERS 
429         {
430                 if (current_options->fwdtab) {
431                         free_forwarders(current_options->fwdtab);
432                         current_options->fwdtab = NULL;
433                 }
434         }
435         '{' opt_forwarders_list '}'
436         | T_QUERY_SOURCE query_source
437         | T_TRANSFER_SOURCE maybe_wild_addr
438         {
439                 current_options->axfr_src = $2;
440         }
441         | T_ALLOW_QUERY '{' address_match_list '}'
442         {
443                 if (current_options->query_acl) {
444                         parser_warning(0,
445                               "options allow-query acl already set; skipping");
446                         free_ip_match_list($3);
447                 } else 
448                         current_options->query_acl = $3;
449         }
450         | T_ALLOW_RECURSION '{' address_match_list '}'
451         {
452                 if (current_options->recursion_acl) {
453                         parser_warning(0,
454                               "options allow-recursion acl already set; skipping");
455                         free_ip_match_list($3);
456                 } else
457                         current_options->recursion_acl = $3;
458         }
459         | T_ALLOW_TRANSFER '{' address_match_list '}'
460         {
461                 if (current_options->transfer_acl) {
462                         parser_warning(0,
463                            "options allow-transfer acl already set; skipping");
464                         free_ip_match_list($3);
465                 } else 
466                         current_options->transfer_acl = $3;
467         }
468         | T_SORTLIST '{' address_match_list '}'
469         {
470                 if (current_options->sortlist) {
471                         parser_warning(0,
472                               "options sortlist already set; skipping");
473                         free_ip_match_list($3);
474                 } else
475                         current_options->sortlist = $3;
476         }
477         | T_ALSO_NOTIFY
478         {
479                 if (current_options->also_notify) {
480                         parser_warning(0,
481                             "duplicate also-notify clause: overwriting");
482                         free_also_notify(current_options);
483                         current_options->also_notify = NULL;
484                 }
485         }
486         '{' opt_also_notify_list '}'
487         | T_BLACKHOLE '{' address_match_list '}'
488         {
489                 if (current_options->blackhole_acl) {
490                         parser_warning(0,
491                               "options blackhole already set; skipping");
492                         free_ip_match_list($3);
493                 } else
494                         current_options->blackhole_acl = $3;
495         }
496         | T_TOPOLOGY '{' address_match_list '}'
497         {
498                 if (current_options->topology) {
499                         parser_warning(0,
500                               "options topology already set; skipping");
501                         free_ip_match_list($3);
502                 } else
503                         current_options->topology = $3;
504         }
505         | size_clause
506         {
507                 /* To get around the $$ = $1 default rule. */
508         }
509         | transfer_clause
510         | T_TRANSFER_FORMAT transfer_format
511         {
512                 current_options->transfer_format = $2;
513         }
514         | T_MAX_TRANSFER_TIME_IN L_NUMBER
515         {
516                 current_options->max_transfer_time_in = $2 * 60;
517         }
518         | T_SERIAL_QUERIES L_NUMBER
519         {
520                 current_options->serial_queries = $2;
521         }
522         | T_CLEAN_INTERVAL L_NUMBER
523         {
524                 current_options->clean_interval = $2 * 60;
525         }
526         | T_INTERFACE_INTERVAL L_NUMBER
527         {
528                 current_options->interface_interval = $2 * 60;
529         }
530         | T_STATS_INTERVAL L_NUMBER
531         {
532                 current_options->stats_interval = $2 * 60;
533         }
534         | T_MAX_LOG_SIZE_IXFR L_NUMBER
535         {
536                 current_options->max_log_size_ixfr = $2;
537         }
538         | T_MAX_NCACHE_TTL L_NUMBER
539         {
540                 current_options->max_ncache_ttl = $2;
541         }
542         | T_LAME_TTL L_NUMBER
543         {
544                 current_options->lame_ttl = $2;
545         }
546         | T_HEARTBEAT L_NUMBER
547         {
548                 current_options->heartbeat_interval = $2 * 60;
549         }
550         | T_DIALUP yea_or_nay
551         {
552                 set_global_boolean_option(current_options,
553                                           OPTION_NODIALUP, !$2);
554         }
555         | T_RRSET_ORDER '{' rrset_ordering_list '}'
556         {
557                 if (current_options->ordering)
558                         free_rrset_order_list(current_options->ordering);
559                 current_options->ordering = $3;
560         }
561         | T_TREAT_CR_AS_SPACE yea_or_nay
562         {
563                 set_global_boolean_option(current_options,
564                                           OPTION_TREAT_CR_AS_SPACE, $2);
565         }
566         | T_MIN_ROOTS L_NUMBER
567         {
568                 if ($2 >= 1)
569                         current_options->minroots = $2;
570         }
571         | error
572         ;
573
574 /*
575  * Controls.
576  */
577 controls_stmt: T_CONTROLS '{' controls '}'
578         ;               
579
580 controls: control L_EOS
581         | controls control L_EOS
582         ;
583
584 control: /* Empty */
585         | T_INET maybe_wild_addr T_PORT in_port
586           T_ALLOW '{' address_match_list '}'
587         {
588                 ns_ctl_add(&current_controls, ns_ctl_new_inet($2, $4, $7));
589         }
590         | T_UNIX L_QSTRING T_PERM L_NUMBER T_OWNER L_NUMBER T_GROUP L_NUMBER
591         {
592                 ns_ctl_add(&current_controls, ns_ctl_new_unix($2, $4, $6, $8));
593         }
594         | error
595         ;
596
597 rrset_ordering_list: rrset_ordering_element L_EOS
598         {
599                 rrset_order_list rol;
600
601                 rol = new_rrset_order_list();
602                 if ($1 != NULL) {
603                         add_to_rrset_order_list(rol, $1);
604                 }
605                 
606                 $$ = rol;
607         }
608         | rrset_ordering_list rrset_ordering_element L_EOS
609         {
610                 if ($2 != NULL) {
611                         add_to_rrset_order_list($1, $2);
612                 }
613                 $$ = $1;
614         }
615         ;
616
617 ordering_class: /* nothing */
618         {
619                 $$ = C_ANY;
620         }
621         | T_CLASS any_string
622         {
623                 symbol_value value;
624
625                 if (lookup_symbol(constants, $2, SYM_CLASS, &value))
626                         $$ = value.integer;
627                 else {
628                         parser_error(0, "unknown class '%s'; using ANY", $2);
629                         $$ = C_ANY;
630                 }
631                 freestr($2);
632         }
633         ;
634
635 ordering_type: /* nothing */
636         {
637                 $$ = ns_t_any;
638         }
639         | T_TYPE any_string
640         {
641                 int success;
642
643                 if (strcmp($2, "*") == 0) {
644                         $$ = ns_t_any;
645                 } else {
646                         $$ = __sym_ston(__p_type_syms, $2, &success);
647                         if (success == 0) {
648                                 $$ = ns_t_any;
649                                 parser_error(0,
650                                              "unknown type '%s'; assuming ANY",
651                                              $2);
652                         }
653                 }
654                 freestr($2);
655         }
656
657 ordering_name: /* nothing */
658         {
659                 $$ = savestr("*", 1);
660         }
661         | T_NAME L_QSTRING
662         {
663                 if (strcmp(".",$2) == 0 || strcmp("*.",$2) == 0) {
664                         $$ = savestr("*", 1);
665                         freestr($2);
666                 } else {
667                         $$ = $2 ;
668                 }
669                 /* XXX Should do any more name validation here? */
670         }
671
672
673 rrset_ordering_element: ordering_class ordering_type ordering_name T_ORDER L_STRING
674         {
675                 enum ordering o;
676
677                 if (strlen($5) == 0) {
678                         parser_error(0, "null order name");
679                         $$ = NULL ;
680                 } else {
681                         o = lookup_ordering($5);
682                         if (o == unknown_order) {
683                                 o = (enum ordering)DEFAULT_ORDERING;
684                                 parser_error(0,
685                                              "invalid order name '%s'; using %s",
686                                              $5, p_order(o));
687                         }
688                         
689                         freestr($5);
690                         
691                         $$ = new_rrset_order_element($1, $2, $3, o);
692                 }
693         }
694
695         
696 transfer_format: T_ONE_ANSWER
697         {
698                 $$ = axfr_one_answer;
699         }
700         | T_MANY_ANSWERS
701         {
702                 $$ = axfr_many_answers;
703         }
704         ;
705         
706 maybe_wild_addr: L_IPADDR { $$ = $1; }
707         | '*' { $$.s_addr = htonl(INADDR_ANY); }
708         ;
709
710 maybe_wild_port: in_port { $$ = $1; }
711         | '*' { $$ = htons(0); }
712         ;
713
714 query_source_address: T_ADDRESS maybe_wild_addr
715         {
716                 current_options->query_source.sin_addr = $2;
717         }
718         ;
719
720 query_source_port: T_PORT maybe_wild_port
721         {
722                 current_options->query_source.sin_port = $2;
723         }
724         ;
725
726 query_source: query_source_address
727         | query_source_port
728         | query_source_address query_source_port
729         | query_source_port query_source_address
730         ;
731
732 maybe_port: /* nothing */ { $$ = htons(NS_DEFAULTPORT); }
733         | T_PORT in_port { $$ = $2; }
734         ;
735
736 maybe_zero_port: /* nothing */ { $$ = htons(0); }
737         | T_PORT in_port { $$ = $2; }
738         ;
739
740
741 yea_or_nay: T_YES
742         { 
743                 $$ = 1; 
744         }
745         | T_TRUE
746         { 
747                 $$ = 1; 
748         }
749         | T_NO
750         { 
751                 $$ = 0; 
752         }
753         | T_FALSE 
754         { 
755                 $$ = 0; 
756         }
757         | L_NUMBER
758         { 
759                 if ($1 == 1 || $1 == 0) {
760                         $$ = $1;
761                 } else {
762                         parser_warning(0,
763                                        "number should be 0 or 1; assuming 1");
764                         $$ = 1;
765                 }
766         }
767         ;
768
769 check_names_type: T_MASTER
770         {
771                 $$ = primary_trans;
772         }
773         | T_SLAVE
774         {
775                 $$ = secondary_trans;
776         }
777         | T_RESPONSE
778         {
779                 $$ = response_trans;
780         }
781         ;
782
783 check_names_opt: T_WARN
784         {
785                 $$ = warn;
786         }
787         | T_FAIL
788         {
789                 $$ = fail;
790         }
791         | T_IGNORE
792         {
793                 $$ = ignore;
794         }
795         ;
796
797 forward_opt: T_ONLY
798         {
799                 set_global_boolean_option(current_options,
800                         OPTION_FORWARD_ONLY, 1);
801         }
802         | T_FIRST
803         {
804                 set_global_boolean_option(current_options,
805                         OPTION_FORWARD_ONLY, 0);
806         }
807         | T_IF_NO_ANSWER
808         {
809                 parser_warning(0, "forward if-no-answer is unimplemented");
810         }
811         | T_IF_NO_DOMAIN
812         {
813                 parser_warning(0, "forward if-no-domain is unimplemented");
814         }
815         ;
816
817 size_clause: T_DATASIZE size_spec
818         {
819                 current_options->data_size = $2;
820         }
821         | T_STACKSIZE size_spec
822         {
823                 current_options->stack_size = $2;
824         }
825         | T_CORESIZE size_spec
826         {
827                 current_options->core_size = $2;
828         }
829         | T_FILES size_spec
830         {
831                 current_options->files = $2;
832         }
833         ;
834
835 size_spec: any_string
836         {
837                 u_long result;
838
839                 if (unit_to_ulong($1, &result))
840                         $$ = result;
841                 else {
842                         parser_error(0, "invalid unit string '%s'", $1);
843                         /* 0 means "use default" */
844                         $$ = 0;
845                 }
846                 freestr($1);
847         }
848         | L_NUMBER
849         {       
850                 $$ = (u_long)$1;
851         }
852         | T_DEFAULT
853         {
854                 $$ = 0;
855         }
856         | T_UNLIMITED
857         {
858                 $$ = ULONG_MAX;
859         }
860         ;
861
862 transfer_clause: T_TRANSFERS_IN L_NUMBER
863         {
864                 current_options->transfers_in = (u_long) $2;
865         }
866         | T_TRANSFERS_OUT L_NUMBER
867         {
868                 current_options->transfers_out = (u_long) $2;
869         }
870         | T_TRANSFERS_PER_NS L_NUMBER
871         {
872                 current_options->transfers_per_ns = (u_long) $2;
873         }
874         ;
875
876 opt_forwarders_list: /* nothing */
877         | forwarders_in_addr_list
878         ;
879
880 forwarders_in_addr_list: forwarders_in_addr L_EOS
881         {
882                 /* nothing */
883         }
884         | forwarders_in_addr_list forwarders_in_addr L_EOS
885         {
886                 /* nothing */
887         }
888         ;
889
890 forwarders_in_addr: L_IPADDR
891         {
892                 add_global_forwarder(current_options, $1);
893         }
894         ;
895
896 opt_also_notify_list: /* nothing */
897         | also_notify_in_addr_list
898         ;
899
900 also_notify_in_addr_list: also_notify_in_addr L_EOS
901         {
902                 /* nothing */
903         }
904         | also_notify_in_addr_list also_notify_in_addr L_EOS
905         {
906                 /* nothing */
907         }
908         ;
909
910 also_notify_in_addr: L_IPADDR
911         {
912                 add_global_also_notify(current_options, $1);
913         }
914         ;
915
916 /*
917  * Logging
918  */
919
920 logging_stmt: T_LOGGING
921         {
922                 current_logging = begin_logging();
923         }
924         '{' logging_opts_list '}'
925         {
926                 end_logging(current_logging, 1);
927                 current_logging = NULL;
928         }
929         ;
930
931 logging_opts_list: logging_opt L_EOS
932         | logging_opts_list logging_opt L_EOS
933         | error
934         ;
935
936 logging_opt: T_CATEGORY category 
937         {
938                 current_category = $2;
939         }
940         '{' channel_list '}'
941         | T_CHANNEL channel_name
942         {
943                 chan_type = log_null;
944                 chan_flags = 0;
945                 chan_level = log_info;
946         }
947         '{' channel_opt_list '}'
948         {
949                 log_channel current_channel = NULL;
950
951                 if (lookup_channel($2) != NULL) {
952                         parser_error(0, "can't redefine channel '%s'", $2);
953                         freestr($2);
954                 } else {
955                         switch (chan_type) {
956                         case log_file:
957                                 current_channel =
958                                         log_new_file_channel(chan_flags,
959                                                              chan_level,
960                                                              chan_name, NULL,
961                                                              chan_versions,
962                                                              chan_max_size);
963                                 freestr(chan_name);
964                                 chan_name = NULL;
965                                 break;
966                         case log_syslog:
967                                 current_channel =
968                                         log_new_syslog_channel(chan_flags,
969                                                                chan_level,
970                                                                chan_facility);
971                                 break;
972                         case log_null:
973                                 current_channel = log_new_null_channel();
974                                 break;
975                         default:
976                                 ns_panic(ns_log_parser, 1,
977                                          "unknown channel type: %d",
978                                          chan_type);
979                         }
980                         if (current_channel == NULL)
981                                 ns_panic(ns_log_parser, 0,
982                                          "couldn't create channel");
983                         define_channel($2, current_channel);
984                 }
985         }
986         ;
987
988 channel_severity: any_string
989         {
990                 symbol_value value;
991
992                 if (lookup_symbol(constants, $1, SYM_LOGGING, &value)) {
993                         chan_level = value.integer;
994                 } else {
995                         parser_error(0, "unknown severity '%s'", $1);
996                         chan_level = log_debug(99);
997                 }
998                 freestr($1);
999         }
1000         | T_DEBUG
1001         {
1002                 chan_level = log_debug(1);
1003         }
1004         | T_DEBUG L_NUMBER
1005         {
1006                 chan_level = $2;
1007         }
1008         | T_DYNAMIC
1009         {
1010                 chan_level = 0;
1011                 chan_flags |= LOG_USE_CONTEXT_LEVEL|LOG_REQUIRE_DEBUG;
1012         }
1013         ;
1014
1015 version_modifier: T_VERSIONS L_NUMBER
1016         {
1017                 chan_versions = $2;
1018         }
1019         | T_VERSIONS T_UNLIMITED
1020         {
1021                 chan_versions = LOG_MAX_VERSIONS;
1022         }
1023         ;
1024
1025 size_modifier: T_SIZE size_spec
1026         {
1027                 chan_max_size = $2;
1028         }
1029         ;
1030
1031 maybe_file_modifiers: /* nothing */
1032         {
1033                 chan_versions = 0;
1034                 chan_max_size = ULONG_MAX;
1035         }
1036         | version_modifier
1037         {
1038                 chan_max_size = ULONG_MAX;
1039         }
1040         | size_modifier
1041         {
1042                 chan_versions = 0;
1043         }
1044         | version_modifier size_modifier
1045         | size_modifier version_modifier
1046         ;
1047
1048 channel_file: T_FILE L_QSTRING maybe_file_modifiers
1049         {
1050                 chan_flags |= LOG_CLOSE_STREAM;
1051                 chan_type = log_file;
1052                 chan_name = $2;
1053         }
1054         ;
1055
1056
1057 facility_name: any_string { $$ = $1; }
1058         | T_SYSLOG { $$ = savestr("syslog", 1); }
1059         ;
1060
1061 maybe_syslog_facility: /* nothing */ { $$ = LOG_DAEMON; }
1062         | facility_name
1063         {
1064                 symbol_value value;
1065
1066                 if (lookup_symbol(constants, $1, SYM_SYSLOG, &value)) {
1067                         $$ = value.integer;
1068                 } else {
1069                         parser_error(0, "unknown facility '%s'", $1);
1070                         $$ = LOG_DAEMON;
1071                 }
1072                 freestr($1);
1073         }
1074         ;
1075
1076 channel_syslog: T_SYSLOG maybe_syslog_facility
1077         {
1078                 chan_type = log_syslog;
1079                 chan_facility = $2;
1080         }
1081         ;
1082
1083 channel_opt: channel_file { /* nothing to do */ }
1084         | channel_syslog { /* nothing to do */ }
1085         | T_NULL_OUTPUT
1086         {
1087                 chan_type = log_null;
1088         }
1089         | T_SEVERITY channel_severity { /* nothing to do */ }
1090         | T_PRINT_TIME yea_or_nay
1091         {
1092                 if ($2)
1093                         chan_flags |= LOG_TIMESTAMP;
1094                 else
1095                         chan_flags &= ~LOG_TIMESTAMP;
1096         }
1097         | T_PRINT_CATEGORY yea_or_nay
1098         {
1099                 if ($2)
1100                         chan_flags |= LOG_PRINT_CATEGORY;
1101                 else
1102                         chan_flags &= ~LOG_PRINT_CATEGORY;
1103         }
1104         | T_PRINT_SEVERITY yea_or_nay
1105         {
1106                 if ($2)
1107                         chan_flags |= LOG_PRINT_LEVEL;
1108                 else
1109                         chan_flags &= ~LOG_PRINT_LEVEL;
1110         }
1111         ;
1112
1113 channel_opt_list: channel_opt L_EOS
1114         | channel_opt_list channel_opt L_EOS
1115         | error
1116         ;
1117
1118 channel_name: any_string
1119         | T_NULL_OUTPUT { $$ = savestr("null", 1); }
1120         ;
1121
1122 channel: channel_name
1123         {
1124                 log_channel channel;
1125                 symbol_value value;
1126
1127                 if (current_category >= 0) {
1128                         channel = lookup_channel($1);
1129                         if (channel != NULL) {
1130                                 add_log_channel(current_logging,
1131                                                 current_category, channel);
1132                         } else
1133                                 parser_error(0, "unknown channel '%s'", $1);
1134                 }
1135                 freestr($1);
1136         }
1137         ;
1138
1139 channel_list: channel L_EOS
1140         | channel_list channel L_EOS
1141         | error
1142         ;
1143
1144 category_name: any_string
1145         | T_DEFAULT { $$ = savestr("default", 1); }
1146         | T_NOTIFY { $$ = savestr("notify", 1); }
1147         ;
1148
1149 category: category_name
1150         {
1151                 symbol_value value;
1152
1153                 if (lookup_symbol(constants, $1, SYM_CATEGORY, &value))
1154                         $$ = value.integer;
1155                 else {
1156                         parser_error(0, "invalid logging category '%s'",
1157                                      $1);
1158                         $$ = -1;
1159                 }
1160                 freestr($1);
1161         }
1162         ;
1163
1164 /*
1165  * Server Information
1166  */
1167
1168 server_stmt: T_SERVER L_IPADDR
1169         {
1170                 const char *ip_printable;
1171                 symbol_value value;
1172                 
1173                 ip_printable = inet_ntoa($2);
1174                 value.pointer = NULL;
1175                 if (lookup_symbol(symtab, ip_printable, SYM_SERVER, NULL))
1176                         seen_server = 1;
1177                 else
1178                         seen_server = 0;
1179                 if (seen_server)
1180                         parser_error(0, "cannot redefine server '%s'", 
1181                                      ip_printable);
1182                 else
1183                         define_symbol(symtab, savestr(ip_printable, 1),
1184                                       SYM_SERVER, value,
1185                                       SYMBOL_FREE_KEY);
1186                 current_server = begin_server($2);
1187         }
1188         '{' server_info_list '}'
1189         {
1190                 end_server(current_server, !seen_server);
1191         }
1192         ;
1193
1194 server_info_list: server_info L_EOS
1195         | server_info_list server_info L_EOS
1196         ;
1197
1198 server_info: T_BOGUS yea_or_nay
1199         {
1200                 set_server_option(current_server, SERVER_INFO_BOGUS, $2);
1201         }
1202         | T_SUPPORT_IXFR yea_or_nay
1203         {
1204                 set_server_option(current_server, SERVER_INFO_SUPPORT_IXFR, $2);
1205         }       
1206         | T_TRANSFERS L_NUMBER
1207         {
1208                 set_server_transfers(current_server, (int)$2);
1209         }
1210         | T_TRANSFER_FORMAT transfer_format
1211         {
1212                 set_server_transfer_format(current_server, $2);
1213         }
1214         | T_KEYS '{' key_list '}'
1215         | error
1216         ;
1217
1218 /*
1219  * Address Matching
1220  */
1221
1222 address_match_list: address_match_element L_EOS
1223         {
1224                 ip_match_list iml;
1225                 
1226                 iml = new_ip_match_list();
1227                 if ($1 != NULL)
1228                         add_to_ip_match_list(iml, $1);
1229                 $$ = iml;
1230         }
1231         | address_match_list address_match_element L_EOS
1232         {
1233                 if ($2 != NULL)
1234                         add_to_ip_match_list($1, $2);
1235                 $$ = $1;
1236         }
1237         ;
1238
1239 address_match_element: address_match_simple
1240         | '!' address_match_simple
1241         {
1242                 if ($2 != NULL)
1243                         ip_match_negate($2);
1244                 $$ = $2;
1245         }
1246         | T_SEC_KEY L_STRING
1247         {
1248                 char *key_name;
1249                 struct dst_key *dst_key;
1250
1251                 key_name = canonical_name($2);
1252                 if (key_name == NULL) {
1253                         parser_error(0, "can't make key name '%s' canonical",
1254                                      $2);
1255                         key_name = savestr("__bad_key__", 1);
1256                 }
1257                 dst_key = find_key(key_name, NULL);
1258                 if (dst_key == NULL) {
1259                         parser_error(0, "key \"%s\" not found", key_name);
1260                         $$ = NULL;
1261                 }
1262                 else
1263                         $$ = new_ip_match_key(dst_key);
1264         }
1265         ;
1266
1267 address_match_simple: L_IPADDR
1268         {
1269                 $$ = new_ip_match_pattern($1, 32);
1270         }
1271         | L_IPADDR '/' L_NUMBER
1272         {
1273                 if ($3 < 0 || $3 > 32) {
1274                         parser_error(0, "mask bits out of range; skipping");
1275                         $$ = NULL;
1276                 } else {
1277                         $$ = new_ip_match_pattern($1, $3);
1278                         if ($$ == NULL)
1279                                 parser_error(0, 
1280                                            "address/mask mismatch; skipping");
1281                 }
1282         }
1283         | L_NUMBER '/' L_NUMBER
1284         {
1285                 struct in_addr ia;
1286
1287                 if ($1 > 255) {
1288                         parser_error(0, "address out of range; skipping");
1289                         $$ = NULL;
1290                 } else {
1291                         if ($3 < 0 || $3 > 32) {
1292                                 parser_error(0,
1293                                         "mask bits out of range; skipping");
1294                                         $$ = NULL;
1295                         } else {
1296                                 ia.s_addr = htonl(($1 & 0xff) << 24);
1297                                 $$ = new_ip_match_pattern(ia, $3);
1298                                 if ($$ == NULL)
1299                                         parser_error(0, 
1300                                            "address/mask mismatch; skipping");
1301                         }
1302                 }
1303         }
1304         | address_name
1305         | '{' address_match_list '}'
1306         {
1307                 char name[256];
1308
1309                 /*
1310                  * We want to be able to clean up this iml later so
1311                  * we give it a name and treat it like any other acl.
1312                  */
1313                 sprintf(name, "__internal_%p", $2);
1314                 define_acl(savestr(name, 1), $2);
1315                 $$ = new_ip_match_indirect($2);
1316         }
1317         ;
1318
1319 address_name: any_string
1320         {
1321                 ip_match_list iml;
1322
1323                 iml = lookup_acl($1);
1324                 if (iml == NULL) {
1325                         parser_error(0, "unknown ACL '%s'", $1);
1326                         $$ = NULL;
1327                 } else
1328                         $$ = new_ip_match_indirect(iml);
1329                 freestr($1);
1330         }
1331         ;
1332
1333 /*
1334  * Keys
1335  */
1336
1337 key_ref: any_string
1338         {
1339                 struct dst_key *dst_key;
1340                 char *key_name;
1341
1342                 key_name = canonical_name($1);
1343                 if (key_name == NULL) {
1344                         parser_error(0, "can't make key name '%s' canonical",
1345                                      $1);
1346                         $$ = NULL;
1347                 } else {
1348                         dst_key = lookup_key(key_name);
1349                         if (dst_key == NULL) {
1350                                 parser_error(0, "unknown key '%s'", key_name);
1351                                 $$ = NULL;
1352                         } else
1353                                 $$ = dst_key;
1354                         freestr(key_name);
1355                 }
1356                 freestr($1);
1357         }
1358         ;
1359
1360 key_list_element: key_ref
1361         {
1362                 if ($1 == NULL)
1363                         parser_error(0, "empty key not added to server list ");
1364                 else
1365                         add_server_key_info(current_server, $1);
1366         }
1367         ;
1368
1369 key_list: key_list_element L_EOS
1370         | key_list key_list_element L_EOS
1371         | error
1372         ;
1373
1374 key_stmt: T_SEC_KEY
1375         {
1376                 current_algorithm = NULL;
1377                 current_secret = NULL;
1378         }
1379         any_string '{' key_definition '}'
1380         {
1381                 struct dst_key *dst_key;
1382                 char *key_name;
1383
1384                 key_name = canonical_name($3);
1385                 if (key_name == NULL) {
1386                         parser_error(0, "can't make key name '%s' canonical",
1387                                      $3);
1388                 } else if (lookup_key(key_name) != NULL) {
1389                         parser_error(0, "can't redefine key '%s'", key_name);
1390                         freestr(key_name);
1391                 } else {
1392                         if (current_algorithm == NULL ||
1393                             current_secret == NULL)  {
1394                                 parser_error(0, "skipping bad key '%s'",
1395                                              key_name);
1396                                 freestr(key_name);
1397                         } else {
1398                                 dst_key = new_key_info(key_name,
1399                                                        current_algorithm,
1400                                                        current_secret);
1401                                 if (dst_key != NULL) {
1402                                         define_key(key_name, dst_key);
1403                                         if (secretkey_info == NULL)
1404                                                 secretkey_info =
1405                                                         new_key_info_list();
1406                                         add_to_key_info_list(secretkey_info,
1407                                                              dst_key);
1408                                 }
1409                         }
1410                 }
1411                 freestr($3);
1412         }
1413         ;
1414         
1415 key_definition: algorithm_id secret
1416         {
1417                 current_algorithm = $1;
1418                 current_secret = $2;
1419         }
1420         | secret algorithm_id
1421         {
1422                 current_algorithm = $2;
1423                 current_secret = $1;
1424         }
1425         | error
1426         {
1427                 current_algorithm = NULL;
1428                 current_secret = NULL;
1429         }
1430         ;
1431
1432 algorithm_id: T_ALGID any_string L_EOS { $$ = $2; }
1433         ;
1434
1435 secret: T_SECRET any_string L_EOS { $$ = $2; }
1436         ;
1437
1438 /*
1439  * ACLs
1440  */
1441
1442 acl_stmt: T_ACL any_string '{' address_match_list '}'
1443         {
1444                 if (lookup_acl($2) != NULL) {
1445                         parser_error(0, "can't redefine ACL '%s'", $2);
1446                         freestr($2);
1447                 } else
1448                         define_acl($2, $4);
1449         }
1450         ;
1451
1452 /*
1453  * Zones
1454  */
1455         
1456 zone_stmt: T_ZONE L_QSTRING optional_class
1457         {
1458                 int sym_type;
1459                 symbol_value value;
1460                 char *zone_name;
1461
1462                 if (!seen_options)
1463                         parser_error(0,
1464              "no options statement before first zone; using previous/default");
1465                 sym_type = SYM_ZONE | ($3 & 0xffff);
1466                 value.pointer = NULL;
1467                 zone_name = canonical_name($2);
1468                 if (zone_name == NULL) {
1469                         parser_error(0, "can't make zone name '%s' canonical",
1470                                      $2);
1471                         should_install = 0;
1472                         zone_name = savestr("__bad_zone__", 1);
1473                 } else {
1474                         if (lookup_symbol(symtab, zone_name, sym_type, NULL)) {
1475                                 should_install = 0;
1476                                 parser_error(0,
1477                                         "cannot redefine zone '%s' class %s",
1478                                              *zone_name ? zone_name : ".",
1479                                              p_class($3));
1480                         } else {
1481                                 should_install = 1;
1482                                 define_symbol(symtab, savestr(zone_name, 1),
1483                                               sym_type, value,
1484                                               SYMBOL_FREE_KEY);
1485                         }
1486                 }
1487                 freestr($2);
1488                 current_zone = begin_zone(zone_name, $3); 
1489         }
1490         optional_zone_options_list
1491         {
1492                 end_zone(current_zone, should_install);
1493         }
1494         ;
1495
1496 optional_zone_options_list: /* Empty */
1497         | '{' zone_option_list '}'
1498         ;
1499
1500 optional_class: /* Empty */
1501         {
1502                 $$ = C_IN;
1503         }
1504         | any_string
1505         {
1506                 symbol_value value;
1507
1508                 if (lookup_symbol(constants, $1, SYM_CLASS, &value))
1509                         $$ = value.integer;
1510                 else {
1511                         /* the zone validator will give the error */
1512                         $$ = C_NONE;
1513                 }
1514                 freestr($1);
1515         }
1516         ;
1517
1518 zone_type: T_MASTER
1519         {
1520                 $$ = Z_MASTER;
1521         }
1522         | T_SLAVE
1523         {
1524                 $$ = Z_SLAVE;
1525         }
1526         | T_HINT
1527         {
1528                 $$ = Z_HINT;
1529         }
1530         | T_STUB
1531         {
1532                 $$ = Z_STUB;
1533         }
1534         | T_FORWARD
1535         {
1536                 $$ = Z_FORWARD;
1537         }
1538         ;
1539
1540 zone_option_list: zone_option L_EOS
1541         | zone_option_list zone_option L_EOS
1542         ;
1543
1544 zone_option: T_TYPE zone_type
1545         {
1546                 if (!set_zone_type(current_zone, $2))
1547                         parser_warning(0, "zone type already set; skipping");
1548         }
1549         | T_FILE L_QSTRING
1550         {
1551                 if (!set_zone_filename(current_zone, $2))
1552                         parser_warning(0,
1553                                        "zone filename already set; skipping");
1554         }
1555         | T_FILE_IXFR L_QSTRING
1556     {
1557                 if (!set_zone_ixfr_file(current_zone, $2))
1558                         parser_warning(0,
1559                                        "zone ixfr data base already set; skipping");
1560     }
1561         | T_IXFR_TMP L_QSTRING
1562     {
1563                 if (!set_zone_ixfr_tmp(current_zone, $2))
1564                         parser_warning(0,
1565                                        "zone ixfr temp filename already set; skipping");
1566     }
1567         | T_MASTERS maybe_zero_port '{' master_in_addr_list '}'
1568         {
1569                 set_zone_master_port(current_zone, $2);
1570         }
1571         | T_TRANSFER_SOURCE maybe_wild_addr
1572         {
1573                 set_zone_transfer_source(current_zone, $2);
1574         }
1575         | T_CHECK_NAMES check_names_opt
1576         {
1577                 if (!set_zone_checknames(current_zone, (enum severity)$2))
1578                         parser_warning(0,
1579                                       "zone checknames already set; skipping");
1580         }
1581         | T_ALLOW_UPDATE '{' address_match_list '}'
1582         {
1583                 if (!set_zone_update_acl(current_zone, $3))
1584                         parser_warning(0,
1585                                       "zone update acl already set; skipping");
1586         }
1587         | T_ALLOW_QUERY '{' address_match_list '}'
1588         {
1589                 if (!set_zone_query_acl(current_zone, $3))
1590                         parser_warning(0,
1591                                       "zone query acl already set; skipping");
1592         }
1593         | T_ALLOW_TRANSFER '{' address_match_list '}'
1594         {
1595                 if (!set_zone_transfer_acl(current_zone, $3))
1596                         parser_warning(0,
1597                                     "zone transfer acl already set; skipping");
1598         }
1599         | T_FORWARD zone_forward_opt
1600         | T_FORWARDERS 
1601         {
1602                 struct zoneinfo *zp = current_zone.opaque;
1603                 if (zp->z_fwdtab) {
1604                         free_forwarders(zp->z_fwdtab);
1605                         zp->z_fwdtab = NULL;
1606                 }
1607
1608         }
1609         '{' opt_zone_forwarders_list '}'
1610         | T_MAX_TRANSFER_TIME_IN L_NUMBER
1611         {
1612                 if (!set_zone_transfer_time_in(current_zone, $2*60))
1613                         parser_warning(0,
1614                        "zone max transfer time (in) already set; skipping");
1615         }
1616         | T_MAX_LOG_SIZE_IXFR L_NUMBER
1617         {
1618                 set_zone_max_log_size_ixfr(current_zone, $2);
1619         }
1620         | T_NOTIFY yea_or_nay
1621         {
1622                 set_zone_notify(current_zone, $2);
1623         }
1624         | T_MAINTAIN_IXFR_BASE yea_or_nay
1625         {
1626                 set_zone_maintain_ixfr_base(current_zone, $2);
1627         }
1628         | T_PUBKEY L_NUMBER L_NUMBER L_NUMBER L_QSTRING
1629         {
1630                 /* flags proto alg key */
1631                 set_zone_pubkey(current_zone, $2, $3, $4, $5);
1632         }
1633         | T_PUBKEY L_STRING L_NUMBER L_NUMBER L_QSTRING
1634         {
1635                 /* flags proto alg key */
1636                 char *endp;
1637                 int flags = (int) strtol($2, &endp, 0);
1638                 if (*endp != '\0')
1639                         ns_panic(ns_log_parser, 1,
1640                                  "Invalid flags string: %s", $2);
1641                 set_zone_pubkey(current_zone, flags, $3, $4, $5);
1642
1643         }
1644         | T_ALSO_NOTIFY '{' opt_notify_in_addr_list '}'
1645         | T_DIALUP yea_or_nay 
1646         {
1647                  set_zone_dialup(current_zone, $2);
1648         }
1649         | error
1650         ;
1651
1652 master_in_addr_list: master_in_addr L_EOS
1653         {
1654                 /* nothing */
1655         }
1656         | master_in_addr_list master_in_addr L_EOS
1657         {
1658                 /* nothing */
1659         }
1660         ;
1661
1662 master_in_addr: L_IPADDR
1663         {
1664                 add_zone_master(current_zone, $1);
1665         }
1666         ;
1667
1668 opt_notify_in_addr_list: /* nothing */
1669         | notify_in_addr_list
1670         ;
1671
1672 notify_in_addr_list: notify_in_addr L_EOS
1673         {
1674                 /* nothing */
1675         }
1676         | notify_in_addr_list notify_in_addr L_EOS
1677         {
1678                 /* nothing */
1679         }
1680         ;
1681
1682 notify_in_addr: L_IPADDR
1683         {
1684                 add_zone_notify(current_zone, $1);
1685         }
1686         ;
1687
1688 zone_forward_opt: T_ONLY
1689         {
1690                 set_zone_boolean_option(current_zone, OPTION_FORWARD_ONLY, 1);
1691         }
1692         | T_FIRST
1693         {
1694                 set_zone_boolean_option(current_zone, OPTION_FORWARD_ONLY, 0);
1695         }
1696         ;
1697
1698 opt_zone_forwarders_list: /* nothing */
1699         {
1700                 set_zone_forward(current_zone);
1701         }
1702         | zone_forwarders_in_addr_list
1703         ;
1704
1705 zone_forwarders_in_addr_list: zone_forwarders_in_addr L_EOS
1706         {
1707                 /* nothing */
1708         }
1709         | zone_forwarders_in_addr_list zone_forwarders_in_addr L_EOS
1710         {
1711                 /* nothing */
1712         }
1713         ;
1714
1715 zone_forwarders_in_addr: L_IPADDR
1716         {
1717                 add_zone_forwarder(current_zone, $1);
1718         }
1719         ;
1720
1721 /*
1722  * Trusted Key statement
1723  */
1724
1725 trusted_keys_stmt: T_TRUSTED_KEYS '{' trusted_keys_list '}'
1726         {
1727         }
1728         ;
1729 trusted_keys_list: trusted_key L_EOS
1730         {
1731                 /* nothing */
1732         }
1733         | trusted_keys_list trusted_key L_EOS
1734         {
1735                 /* nothing */
1736         }
1737         ;
1738 trusted_key: L_STRING L_NUMBER L_NUMBER L_NUMBER L_QSTRING
1739         {
1740                 /* name flags proto alg key */
1741                 set_trusted_key($1, $2, $3, $4, $5);
1742         }
1743         | L_STRING L_STRING L_NUMBER L_NUMBER L_QSTRING
1744         {
1745                 /* name flags proto alg key */
1746                 char *endp;
1747                 int flags = (int) strtol($2, &endp, 0);
1748                 if (*endp != '\0')
1749                         ns_panic(ns_log_parser, 1,
1750                                  "Invalid flags string: %s", $2);
1751                 set_trusted_key($1, flags, $3, $4, $5);
1752         }
1753         ;
1754
1755 /*
1756  * Misc.
1757  */
1758
1759 in_port: L_NUMBER
1760         {
1761                 if ($1 < 0 || $1 > 65535) {
1762                         parser_warning(0, 
1763                           "invalid IP port number '%d'; setting port to 0",
1764                                        $1);
1765                         $1 = 0;
1766                 } else
1767                         $$ = htons($1);
1768         }
1769         ;
1770
1771 any_string: L_STRING
1772         | L_QSTRING
1773         ;
1774         
1775 %%
1776
1777 static char *
1778 canonical_name(char *name) {
1779         char canonical[MAXDNAME];
1780         
1781         if (strlen(name) >= MAXDNAME)
1782                 return (NULL);
1783         strcpy(canonical, name);
1784         if (makename(canonical, ".", sizeof canonical) < 0)
1785                 return (NULL);
1786         return (savestr(canonical, 0));
1787 }
1788
1789 static void
1790 init_acls() {
1791         ip_match_element ime;
1792         ip_match_list iml;
1793         struct in_addr address;
1794
1795         /* Create the predefined ACLs */
1796
1797         address.s_addr = 0U;
1798
1799         /* ACL "any" */
1800         ime = new_ip_match_pattern(address, 0);
1801         iml = new_ip_match_list();
1802         add_to_ip_match_list(iml, ime);
1803         define_acl(savestr("any", 1), iml);
1804
1805         /* ACL "none" */
1806         ime = new_ip_match_pattern(address, 0);
1807         ip_match_negate(ime);
1808         iml = new_ip_match_list();
1809         add_to_ip_match_list(iml, ime);
1810         define_acl(savestr("none", 1), iml);
1811
1812         /* ACL "localhost" */
1813         ime = new_ip_match_localhost();
1814         iml = new_ip_match_list();
1815         add_to_ip_match_list(iml, ime);
1816         define_acl(savestr("localhost", 1), iml);
1817
1818         /* ACL "localnets" */
1819         ime = new_ip_match_localnets();
1820         iml = new_ip_match_list();
1821         add_to_ip_match_list(iml, ime);
1822         define_acl(savestr("localnets", 1), iml);
1823 }
1824
1825 static void
1826 free_sym_value(int type, void *value) {
1827         ns_debug(ns_log_parser, 99, "free_sym_value: type %06x value %p",
1828                  type, value);
1829         type &= ~0xffff;
1830         switch (type) {
1831         case SYM_ACL:
1832                 free_ip_match_list(value);
1833                 break;
1834         case SYM_KEY:
1835                 free_key_info(value);
1836                 break;
1837         default:
1838                 ns_panic(ns_log_parser, 1,
1839                          "unhandled case in free_sym_value()");
1840                 /* NOTREACHED */
1841                 break;
1842         }
1843 }
1844
1845 static log_channel
1846 lookup_channel(char *name) {
1847         symbol_value value;
1848
1849         if (lookup_symbol(symtab, name, SYM_CHANNEL, &value))
1850                 return ((log_channel)(value.pointer));
1851         return (NULL);
1852 }
1853
1854 static void
1855 define_channel(char *name, log_channel channel) {
1856         symbol_value value;
1857
1858         value.pointer = channel;  
1859         define_symbol(symtab, name, SYM_CHANNEL, value, SYMBOL_FREE_KEY);
1860 }
1861
1862 static void
1863 define_builtin_channels() {
1864         define_channel(savestr("default_syslog", 1), syslog_channel);
1865         define_channel(savestr("default_debug", 1), debug_channel);
1866         define_channel(savestr("default_stderr", 1), stderr_channel);
1867         define_channel(savestr("null", 1), null_channel);
1868 }
1869
1870 static void
1871 parser_setup() {
1872         seen_options = 0;
1873         seen_topology = 0;
1874         symtab = new_symbol_table(SYMBOL_TABLE_SIZE, NULL);
1875         if (authtab != NULL)
1876                 free_symbol_table(authtab);
1877         authtab = new_symbol_table(AUTH_TABLE_SIZE, free_sym_value);
1878         init_acls();
1879         define_builtin_channels();
1880         INIT_LIST(current_controls);
1881 }
1882
1883 static void
1884 parser_cleanup() {
1885         if (symtab != NULL)
1886                 free_symbol_table(symtab);
1887         symtab = NULL;
1888         /*
1889          * We don't clean up authtab here because the ip_match_lists are in
1890          * use.
1891          */
1892 }
1893
1894 /*
1895  * Public Interface
1896  */
1897
1898 ip_match_list
1899 lookup_acl(char *name) {
1900         symbol_value value;
1901
1902         if (lookup_symbol(authtab, name, SYM_ACL, &value))
1903                 return ((ip_match_list)(value.pointer));
1904         return (NULL);
1905 }
1906
1907 void
1908 define_acl(char *name, ip_match_list iml) {
1909         symbol_value value;
1910
1911         INSIST(name != NULL);
1912         INSIST(iml != NULL);
1913
1914         value.pointer = iml;
1915         define_symbol(authtab, name, SYM_ACL, value,
1916                       SYMBOL_FREE_KEY|SYMBOL_FREE_VALUE);
1917         ns_debug(ns_log_parser, 7, "acl %s", name);
1918         dprint_ip_match_list(ns_log_parser, iml, 2, "allow ", "deny ");
1919 }
1920
1921 struct dst_key *
1922 lookup_key(char *name) {
1923         symbol_value value;
1924
1925         if (lookup_symbol(authtab, name, SYM_KEY, &value))
1926                 return ((struct dst_key *)(value.pointer));
1927         return (NULL);
1928 }
1929
1930 void
1931 define_key(char *name, struct dst_key *dst_key) {
1932         symbol_value value;
1933
1934         INSIST(name != NULL);
1935         INSIST(dst_key != NULL);
1936
1937         value.pointer = dst_key;
1938         define_symbol(authtab, name, SYM_KEY, value, SYMBOL_FREE_VALUE);
1939         dprint_key_info(dst_key);
1940 }
1941
1942 void
1943 parse_configuration(const char *filename) {
1944         FILE *config_stream;
1945
1946         config_stream = fopen(filename, "r");
1947         if (config_stream == NULL)
1948                 ns_panic(ns_log_parser, 0, "can't open '%s'", filename);
1949
1950         lexer_setup();
1951         parser_setup();
1952         lexer_begin_file(filename, config_stream);
1953         (void)yyparse();
1954         lexer_end_file();
1955         parser_cleanup();
1956 }
1957
1958 void
1959 parser_initialize(void) {
1960         lexer_initialize();
1961 }
1962
1963 void
1964 parser_shutdown(void) {
1965         if (authtab != NULL)
1966                 free_symbol_table(authtab);
1967         lexer_shutdown();
1968 }