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 $";
7 * Copyright (c) 1996-1999 by Internet Software Consortium.
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.
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
23 /* Global C stuff goes here. */
25 #include "port_before.h"
27 #include <sys/types.h>
28 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/nameser.h>
33 #include <arpa/inet.h>
44 #include <isc/eventlib.h>
45 #include <isc/logging.h>
49 #include "port_after.h"
52 #include "ns_parseutil.h"
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
62 #define SYMBOL_TABLE_SIZE 29989 /* should always be prime */
63 static symbol_table symtab;
65 #define AUTH_TABLE_SIZE 397 /* should always be prime */
66 static symbol_table authtab = NULL;
68 static zone_config current_zone;
69 static int should_install;
71 static options current_options;
72 static int seen_options;
74 static controls current_controls;
76 static topology_config current_topology;
77 static int seen_topology;
79 static server_config current_server;
80 static int seen_server;
82 static char *current_algorithm;
83 static char *current_secret;
85 static log_config current_logging;
86 static int current_category;
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;
95 static log_channel lookup_channel(char *);
96 static void define_channel(char *, log_channel);
97 static char *canonical_name(char *);
109 struct in_addr ip_addr;
110 ip_match_element ime;
112 rrset_order_list rol;
113 rrset_order_element roe;
114 struct dst_key * keyi;
115 enum axfr_format axfr_fmt;
118 /* Lexical analyzer return values. */
120 %token <ip_addr> L_IPADDR
121 %token <num> L_NUMBER
123 %token <cp> L_QSTRING
126 /* Include support */
129 /* Items related to the "options" statement: */
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
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
166 /* Items used for the "sortlist" statement: */
169 /* Items used for the "topology" statement: */
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
179 %type <ime> address_match_simple address_match_element address_name
180 %type <iml> address_match_list
182 /* Items used for "server" statements: */
188 %token T_SUPPORT_IXFR
190 /* Items used for "zone" statements: */
192 %type <num> optional_class
193 %type <s_int> zone_type
194 %token T_IN T_CHAOS T_HESIOD
196 %token T_MASTER T_SLAVE T_STUB T_RESPONSE
198 %token T_MASTERS T_TRANSFER_SOURCE
205 /* Items used for "trusted-keys" statements: */
206 %token T_TRUSTED_KEYS
208 /* Items used for access control lists and "allow" clauses: */
210 %token T_ALLOW_UPDATE T_ALLOW_QUERY T_ALLOW_TRANSFER
211 %token T_ALLOW_RECURSION
214 /* Items related to the "key" statement: */
215 %token T_SEC_KEY T_ALGID T_SECRET
217 %type <cp> algorithm_id secret
219 /* Items used for "size_spec" clauses: */
220 %type <ul_int> size_spec
222 /* Items used for a "check-names" clause: */
224 %type <s_int> check_names_type
225 %type <s_int> check_names_opt
226 %token T_WARN T_FAIL T_IGNORE
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
232 /* Items used for yes/no responses: */
233 %type <num> yea_or_nay
234 %token T_YES T_TRUE T_NO T_FALSE
236 /* Miscellaneous items (used in several places): */
237 %type <cp> any_string
240 config_file: statement_list
242 if (EMPTY(current_controls))
243 ns_ctl_defaults(¤t_controls);
244 ns_ctl_install(¤t_controls);
248 statement_list: statement
249 | statement_list statement
252 statement: include_stmt
254 | controls_stmt L_EOS
258 | trusted_keys_stmt L_EOS
263 | error L_END_INCLUDE
266 include_stmt: T_INCLUDE L_QSTRING L_EOS { lexer_begin_file($2, NULL); }
273 options_stmt: T_OPTIONS
276 parser_error(0, "cannot redefine options");
277 current_options = new_options();
282 set_options(current_options, 0);
284 free_options(current_options);
285 current_options = NULL;
290 options: option L_EOS
291 | options option L_EOS
295 | T_VERSION L_QSTRING
297 if (current_options->version != NULL)
298 freestr(current_options->version);
299 current_options->version = $2;
301 | T_DIRECTORY L_QSTRING
303 if (current_options->directory != NULL)
304 freestr(current_options->directory);
305 current_options->directory = $2;
307 | T_NAMED_XFER L_QSTRING
309 if (current_options->named_xfer != NULL)
310 freestr(current_options->named_xfer);
311 current_options->named_xfer = $2;
313 | T_PIDFILE L_QSTRING
315 if (current_options->pid_filename != NULL)
316 freestr(current_options->pid_filename);
317 current_options->pid_filename = $2;
319 | T_STATS_FILE L_QSTRING
321 if (current_options->stats_filename != NULL)
322 freestr(current_options->stats_filename);
323 current_options->stats_filename = $2;
325 | T_MEMSTATS_FILE L_QSTRING
327 if (current_options->memstats_filename != NULL)
328 freestr(current_options->memstats_filename);
329 current_options->memstats_filename = $2;
331 | T_DUMP_FILE L_QSTRING
333 if (current_options->dump_filename != NULL)
334 freestr(current_options->dump_filename);
335 current_options->dump_filename = $2;
337 | T_FAKE_IQUERY yea_or_nay
339 set_global_boolean_option(current_options,
340 OPTION_FAKE_IQUERY, $2);
342 | T_RECURSION yea_or_nay
344 set_global_boolean_option(current_options,
345 OPTION_NORECURSE, !$2);
347 | T_FETCH_GLUE yea_or_nay
349 set_global_boolean_option(current_options,
350 OPTION_NOFETCHGLUE, !$2);
352 | T_NOTIFY yea_or_nay
354 set_global_boolean_option(current_options,
355 OPTION_NONOTIFY, !$2);
357 | T_HOSTSTATS yea_or_nay
359 set_global_boolean_option(current_options,
360 OPTION_HOSTSTATS, $2);
362 | T_DEALLOC_ON_EXIT yea_or_nay
364 set_global_boolean_option(current_options,
365 OPTION_DEALLOC_ON_EXIT, $2);
367 | T_USE_IXFR yea_or_nay
369 set_global_boolean_option(current_options, OPTION_USE_IXFR, $2);
371 | T_MAINTAIN_IXFR_BASE yea_or_nay
373 set_global_boolean_option(current_options,
374 OPTION_MAINTAIN_IXFR_BASE, $2);
376 | T_HAS_OLD_CLIENTS yea_or_nay
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);
385 | T_AUTH_NXDOMAIN yea_or_nay
387 set_global_boolean_option(current_options, OPTION_NONAUTH_NXDOMAIN,
390 | T_MULTIPLE_CNAMES yea_or_nay
392 set_global_boolean_option(current_options,
393 OPTION_MULTIPLE_CNAMES, $2);
395 | T_CHECK_NAMES check_names_type check_names_opt
397 current_options->check_names[$2] = (enum severity)$3;
399 | T_USE_ID_POOL yea_or_nay
401 set_global_boolean_option(current_options,
402 OPTION_USE_ID_POOL, $2);
404 | T_RFC2308_TYPE1 yea_or_nay
406 set_global_boolean_option(current_options,
407 OPTION_NORFC2308_TYPE1, !$2);
409 | T_LISTEN_ON maybe_port '{' address_match_list '}'
411 char port_string[10];
414 (void)sprintf(port_string, "%u", $2);
415 if (lookup_symbol(symtab, port_string, SYM_PORT, NULL))
417 "cannot redefine listen-on for port %u",
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);
427 | T_FORWARD forward_opt
430 if (current_options->fwdtab) {
431 free_forwarders(current_options->fwdtab);
432 current_options->fwdtab = NULL;
435 '{' opt_forwarders_list '}'
436 | T_QUERY_SOURCE query_source
437 | T_TRANSFER_SOURCE maybe_wild_addr
439 current_options->axfr_src = $2;
441 | T_ALLOW_QUERY '{' address_match_list '}'
443 if (current_options->query_acl) {
445 "options allow-query acl already set; skipping");
446 free_ip_match_list($3);
448 current_options->query_acl = $3;
450 | T_ALLOW_RECURSION '{' address_match_list '}'
452 if (current_options->recursion_acl) {
454 "options allow-recursion acl already set; skipping");
455 free_ip_match_list($3);
457 current_options->recursion_acl = $3;
459 | T_ALLOW_TRANSFER '{' address_match_list '}'
461 if (current_options->transfer_acl) {
463 "options allow-transfer acl already set; skipping");
464 free_ip_match_list($3);
466 current_options->transfer_acl = $3;
468 | T_SORTLIST '{' address_match_list '}'
470 if (current_options->sortlist) {
472 "options sortlist already set; skipping");
473 free_ip_match_list($3);
475 current_options->sortlist = $3;
479 if (current_options->also_notify) {
481 "duplicate also-notify clause: overwriting");
482 free_also_notify(current_options);
483 current_options->also_notify = NULL;
486 '{' opt_also_notify_list '}'
487 | T_BLACKHOLE '{' address_match_list '}'
489 if (current_options->blackhole_acl) {
491 "options blackhole already set; skipping");
492 free_ip_match_list($3);
494 current_options->blackhole_acl = $3;
496 | T_TOPOLOGY '{' address_match_list '}'
498 if (current_options->topology) {
500 "options topology already set; skipping");
501 free_ip_match_list($3);
503 current_options->topology = $3;
507 /* To get around the $$ = $1 default rule. */
510 | T_TRANSFER_FORMAT transfer_format
512 current_options->transfer_format = $2;
514 | T_MAX_TRANSFER_TIME_IN L_NUMBER
516 current_options->max_transfer_time_in = $2 * 60;
518 | T_SERIAL_QUERIES L_NUMBER
520 current_options->serial_queries = $2;
522 | T_CLEAN_INTERVAL L_NUMBER
524 current_options->clean_interval = $2 * 60;
526 | T_INTERFACE_INTERVAL L_NUMBER
528 current_options->interface_interval = $2 * 60;
530 | T_STATS_INTERVAL L_NUMBER
532 current_options->stats_interval = $2 * 60;
534 | T_MAX_LOG_SIZE_IXFR L_NUMBER
536 current_options->max_log_size_ixfr = $2;
538 | T_MAX_NCACHE_TTL L_NUMBER
540 current_options->max_ncache_ttl = $2;
542 | T_LAME_TTL L_NUMBER
544 current_options->lame_ttl = $2;
546 | T_HEARTBEAT L_NUMBER
548 current_options->heartbeat_interval = $2 * 60;
550 | T_DIALUP yea_or_nay
552 set_global_boolean_option(current_options,
553 OPTION_NODIALUP, !$2);
555 | T_RRSET_ORDER '{' rrset_ordering_list '}'
557 if (current_options->ordering)
558 free_rrset_order_list(current_options->ordering);
559 current_options->ordering = $3;
561 | T_TREAT_CR_AS_SPACE yea_or_nay
563 set_global_boolean_option(current_options,
564 OPTION_TREAT_CR_AS_SPACE, $2);
566 | T_MIN_ROOTS L_NUMBER
569 current_options->minroots = $2;
577 controls_stmt: T_CONTROLS '{' controls '}'
580 controls: control L_EOS
581 | controls control L_EOS
585 | T_INET maybe_wild_addr T_PORT in_port
586 T_ALLOW '{' address_match_list '}'
588 ns_ctl_add(¤t_controls, ns_ctl_new_inet($2, $4, $7));
590 | T_UNIX L_QSTRING T_PERM L_NUMBER T_OWNER L_NUMBER T_GROUP L_NUMBER
592 ns_ctl_add(¤t_controls, ns_ctl_new_unix($2, $4, $6, $8));
597 rrset_ordering_list: rrset_ordering_element L_EOS
599 rrset_order_list rol;
601 rol = new_rrset_order_list();
603 add_to_rrset_order_list(rol, $1);
608 | rrset_ordering_list rrset_ordering_element L_EOS
611 add_to_rrset_order_list($1, $2);
617 ordering_class: /* nothing */
625 if (lookup_symbol(constants, $2, SYM_CLASS, &value))
628 parser_error(0, "unknown class '%s'; using ANY", $2);
635 ordering_type: /* nothing */
643 if (strcmp($2, "*") == 0) {
646 $$ = __sym_ston(__p_type_syms, $2, &success);
650 "unknown type '%s'; assuming ANY",
657 ordering_name: /* nothing */
659 $$ = savestr("*", 1);
663 if (strcmp(".",$2) == 0 || strcmp("*.",$2) == 0) {
664 $$ = savestr("*", 1);
669 /* XXX Should do any more name validation here? */
673 rrset_ordering_element: ordering_class ordering_type ordering_name T_ORDER L_STRING
677 if (strlen($5) == 0) {
678 parser_error(0, "null order name");
681 o = lookup_ordering($5);
682 if (o == unknown_order) {
683 o = (enum ordering)DEFAULT_ORDERING;
685 "invalid order name '%s'; using %s",
691 $$ = new_rrset_order_element($1, $2, $3, o);
696 transfer_format: T_ONE_ANSWER
698 $$ = axfr_one_answer;
702 $$ = axfr_many_answers;
706 maybe_wild_addr: L_IPADDR { $$ = $1; }
707 | '*' { $$.s_addr = htonl(INADDR_ANY); }
710 maybe_wild_port: in_port { $$ = $1; }
711 | '*' { $$ = htons(0); }
714 query_source_address: T_ADDRESS maybe_wild_addr
716 current_options->query_source.sin_addr = $2;
720 query_source_port: T_PORT maybe_wild_port
722 current_options->query_source.sin_port = $2;
726 query_source: query_source_address
728 | query_source_address query_source_port
729 | query_source_port query_source_address
732 maybe_port: /* nothing */ { $$ = htons(NS_DEFAULTPORT); }
733 | T_PORT in_port { $$ = $2; }
736 maybe_zero_port: /* nothing */ { $$ = htons(0); }
737 | T_PORT in_port { $$ = $2; }
759 if ($1 == 1 || $1 == 0) {
763 "number should be 0 or 1; assuming 1");
769 check_names_type: T_MASTER
775 $$ = secondary_trans;
783 check_names_opt: T_WARN
799 set_global_boolean_option(current_options,
800 OPTION_FORWARD_ONLY, 1);
804 set_global_boolean_option(current_options,
805 OPTION_FORWARD_ONLY, 0);
809 parser_warning(0, "forward if-no-answer is unimplemented");
813 parser_warning(0, "forward if-no-domain is unimplemented");
817 size_clause: T_DATASIZE size_spec
819 current_options->data_size = $2;
821 | T_STACKSIZE size_spec
823 current_options->stack_size = $2;
825 | T_CORESIZE size_spec
827 current_options->core_size = $2;
831 current_options->files = $2;
835 size_spec: any_string
839 if (unit_to_ulong($1, &result))
842 parser_error(0, "invalid unit string '%s'", $1);
843 /* 0 means "use default" */
862 transfer_clause: T_TRANSFERS_IN L_NUMBER
864 current_options->transfers_in = (u_long) $2;
866 | T_TRANSFERS_OUT L_NUMBER
868 current_options->transfers_out = (u_long) $2;
870 | T_TRANSFERS_PER_NS L_NUMBER
872 current_options->transfers_per_ns = (u_long) $2;
876 opt_forwarders_list: /* nothing */
877 | forwarders_in_addr_list
880 forwarders_in_addr_list: forwarders_in_addr L_EOS
884 | forwarders_in_addr_list forwarders_in_addr L_EOS
890 forwarders_in_addr: L_IPADDR
892 add_global_forwarder(current_options, $1);
896 opt_also_notify_list: /* nothing */
897 | also_notify_in_addr_list
900 also_notify_in_addr_list: also_notify_in_addr L_EOS
904 | also_notify_in_addr_list also_notify_in_addr L_EOS
910 also_notify_in_addr: L_IPADDR
912 add_global_also_notify(current_options, $1);
920 logging_stmt: T_LOGGING
922 current_logging = begin_logging();
924 '{' logging_opts_list '}'
926 end_logging(current_logging, 1);
927 current_logging = NULL;
931 logging_opts_list: logging_opt L_EOS
932 | logging_opts_list logging_opt L_EOS
936 logging_opt: T_CATEGORY category
938 current_category = $2;
941 | T_CHANNEL channel_name
943 chan_type = log_null;
945 chan_level = log_info;
947 '{' channel_opt_list '}'
949 log_channel current_channel = NULL;
951 if (lookup_channel($2) != NULL) {
952 parser_error(0, "can't redefine channel '%s'", $2);
958 log_new_file_channel(chan_flags,
968 log_new_syslog_channel(chan_flags,
973 current_channel = log_new_null_channel();
976 ns_panic(ns_log_parser, 1,
977 "unknown channel type: %d",
980 if (current_channel == NULL)
981 ns_panic(ns_log_parser, 0,
982 "couldn't create channel");
983 define_channel($2, current_channel);
988 channel_severity: any_string
992 if (lookup_symbol(constants, $1, SYM_LOGGING, &value)) {
993 chan_level = value.integer;
995 parser_error(0, "unknown severity '%s'", $1);
996 chan_level = log_debug(99);
1002 chan_level = log_debug(1);
1011 chan_flags |= LOG_USE_CONTEXT_LEVEL|LOG_REQUIRE_DEBUG;
1015 version_modifier: T_VERSIONS L_NUMBER
1019 | T_VERSIONS T_UNLIMITED
1021 chan_versions = LOG_MAX_VERSIONS;
1025 size_modifier: T_SIZE size_spec
1031 maybe_file_modifiers: /* nothing */
1034 chan_max_size = ULONG_MAX;
1038 chan_max_size = ULONG_MAX;
1044 | version_modifier size_modifier
1045 | size_modifier version_modifier
1048 channel_file: T_FILE L_QSTRING maybe_file_modifiers
1050 chan_flags |= LOG_CLOSE_STREAM;
1051 chan_type = log_file;
1057 facility_name: any_string { $$ = $1; }
1058 | T_SYSLOG { $$ = savestr("syslog", 1); }
1061 maybe_syslog_facility: /* nothing */ { $$ = LOG_DAEMON; }
1066 if (lookup_symbol(constants, $1, SYM_SYSLOG, &value)) {
1069 parser_error(0, "unknown facility '%s'", $1);
1076 channel_syslog: T_SYSLOG maybe_syslog_facility
1078 chan_type = log_syslog;
1083 channel_opt: channel_file { /* nothing to do */ }
1084 | channel_syslog { /* nothing to do */ }
1087 chan_type = log_null;
1089 | T_SEVERITY channel_severity { /* nothing to do */ }
1090 | T_PRINT_TIME yea_or_nay
1093 chan_flags |= LOG_TIMESTAMP;
1095 chan_flags &= ~LOG_TIMESTAMP;
1097 | T_PRINT_CATEGORY yea_or_nay
1100 chan_flags |= LOG_PRINT_CATEGORY;
1102 chan_flags &= ~LOG_PRINT_CATEGORY;
1104 | T_PRINT_SEVERITY yea_or_nay
1107 chan_flags |= LOG_PRINT_LEVEL;
1109 chan_flags &= ~LOG_PRINT_LEVEL;
1113 channel_opt_list: channel_opt L_EOS
1114 | channel_opt_list channel_opt L_EOS
1118 channel_name: any_string
1119 | T_NULL_OUTPUT { $$ = savestr("null", 1); }
1122 channel: channel_name
1124 log_channel channel;
1127 if (current_category >= 0) {
1128 channel = lookup_channel($1);
1129 if (channel != NULL) {
1130 add_log_channel(current_logging,
1131 current_category, channel);
1133 parser_error(0, "unknown channel '%s'", $1);
1139 channel_list: channel L_EOS
1140 | channel_list channel L_EOS
1144 category_name: any_string
1145 | T_DEFAULT { $$ = savestr("default", 1); }
1146 | T_NOTIFY { $$ = savestr("notify", 1); }
1149 category: category_name
1153 if (lookup_symbol(constants, $1, SYM_CATEGORY, &value))
1156 parser_error(0, "invalid logging category '%s'",
1165 * Server Information
1168 server_stmt: T_SERVER L_IPADDR
1170 const char *ip_printable;
1173 ip_printable = inet_ntoa($2);
1174 value.pointer = NULL;
1175 if (lookup_symbol(symtab, ip_printable, SYM_SERVER, NULL))
1180 parser_error(0, "cannot redefine server '%s'",
1183 define_symbol(symtab, savestr(ip_printable, 1),
1186 current_server = begin_server($2);
1188 '{' server_info_list '}'
1190 end_server(current_server, !seen_server);
1194 server_info_list: server_info L_EOS
1195 | server_info_list server_info L_EOS
1198 server_info: T_BOGUS yea_or_nay
1200 set_server_option(current_server, SERVER_INFO_BOGUS, $2);
1202 | T_SUPPORT_IXFR yea_or_nay
1204 set_server_option(current_server, SERVER_INFO_SUPPORT_IXFR, $2);
1206 | T_TRANSFERS L_NUMBER
1208 set_server_transfers(current_server, (int)$2);
1210 | T_TRANSFER_FORMAT transfer_format
1212 set_server_transfer_format(current_server, $2);
1214 | T_KEYS '{' key_list '}'
1222 address_match_list: address_match_element L_EOS
1226 iml = new_ip_match_list();
1228 add_to_ip_match_list(iml, $1);
1231 | address_match_list address_match_element L_EOS
1234 add_to_ip_match_list($1, $2);
1239 address_match_element: address_match_simple
1240 | '!' address_match_simple
1243 ip_match_negate($2);
1246 | T_SEC_KEY L_STRING
1249 struct dst_key *dst_key;
1251 key_name = canonical_name($2);
1252 if (key_name == NULL) {
1253 parser_error(0, "can't make key name '%s' canonical",
1255 key_name = savestr("__bad_key__", 1);
1257 dst_key = find_key(key_name, NULL);
1258 if (dst_key == NULL) {
1259 parser_error(0, "key \"%s\" not found", key_name);
1263 $$ = new_ip_match_key(dst_key);
1267 address_match_simple: L_IPADDR
1269 $$ = new_ip_match_pattern($1, 32);
1271 | L_IPADDR '/' L_NUMBER
1273 if ($3 < 0 || $3 > 32) {
1274 parser_error(0, "mask bits out of range; skipping");
1277 $$ = new_ip_match_pattern($1, $3);
1280 "address/mask mismatch; skipping");
1283 | L_NUMBER '/' L_NUMBER
1288 parser_error(0, "address out of range; skipping");
1291 if ($3 < 0 || $3 > 32) {
1293 "mask bits out of range; skipping");
1296 ia.s_addr = htonl(($1 & 0xff) << 24);
1297 $$ = new_ip_match_pattern(ia, $3);
1300 "address/mask mismatch; skipping");
1305 | '{' address_match_list '}'
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.
1313 sprintf(name, "__internal_%p", $2);
1314 define_acl(savestr(name, 1), $2);
1315 $$ = new_ip_match_indirect($2);
1319 address_name: any_string
1323 iml = lookup_acl($1);
1325 parser_error(0, "unknown ACL '%s'", $1);
1328 $$ = new_ip_match_indirect(iml);
1339 struct dst_key *dst_key;
1342 key_name = canonical_name($1);
1343 if (key_name == NULL) {
1344 parser_error(0, "can't make key name '%s' canonical",
1348 dst_key = lookup_key(key_name);
1349 if (dst_key == NULL) {
1350 parser_error(0, "unknown key '%s'", key_name);
1360 key_list_element: key_ref
1363 parser_error(0, "empty key not added to server list ");
1365 add_server_key_info(current_server, $1);
1369 key_list: key_list_element L_EOS
1370 | key_list key_list_element L_EOS
1376 current_algorithm = NULL;
1377 current_secret = NULL;
1379 any_string '{' key_definition '}'
1381 struct dst_key *dst_key;
1384 key_name = canonical_name($3);
1385 if (key_name == NULL) {
1386 parser_error(0, "can't make key name '%s' canonical",
1388 } else if (lookup_key(key_name) != NULL) {
1389 parser_error(0, "can't redefine key '%s'", key_name);
1392 if (current_algorithm == NULL ||
1393 current_secret == NULL) {
1394 parser_error(0, "skipping bad key '%s'",
1398 dst_key = new_key_info(key_name,
1401 if (dst_key != NULL) {
1402 define_key(key_name, dst_key);
1403 if (secretkey_info == NULL)
1405 new_key_info_list();
1406 add_to_key_info_list(secretkey_info,
1415 key_definition: algorithm_id secret
1417 current_algorithm = $1;
1418 current_secret = $2;
1420 | secret algorithm_id
1422 current_algorithm = $2;
1423 current_secret = $1;
1427 current_algorithm = NULL;
1428 current_secret = NULL;
1432 algorithm_id: T_ALGID any_string L_EOS { $$ = $2; }
1435 secret: T_SECRET any_string L_EOS { $$ = $2; }
1442 acl_stmt: T_ACL any_string '{' address_match_list '}'
1444 if (lookup_acl($2) != NULL) {
1445 parser_error(0, "can't redefine ACL '%s'", $2);
1456 zone_stmt: T_ZONE L_QSTRING optional_class
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",
1472 zone_name = savestr("__bad_zone__", 1);
1474 if (lookup_symbol(symtab, zone_name, sym_type, NULL)) {
1477 "cannot redefine zone '%s' class %s",
1478 *zone_name ? zone_name : ".",
1482 define_symbol(symtab, savestr(zone_name, 1),
1488 current_zone = begin_zone(zone_name, $3);
1490 optional_zone_options_list
1492 end_zone(current_zone, should_install);
1496 optional_zone_options_list: /* Empty */
1497 | '{' zone_option_list '}'
1500 optional_class: /* Empty */
1508 if (lookup_symbol(constants, $1, SYM_CLASS, &value))
1511 /* the zone validator will give the error */
1540 zone_option_list: zone_option L_EOS
1541 | zone_option_list zone_option L_EOS
1544 zone_option: T_TYPE zone_type
1546 if (!set_zone_type(current_zone, $2))
1547 parser_warning(0, "zone type already set; skipping");
1551 if (!set_zone_filename(current_zone, $2))
1553 "zone filename already set; skipping");
1555 | T_FILE_IXFR L_QSTRING
1557 if (!set_zone_ixfr_file(current_zone, $2))
1559 "zone ixfr data base already set; skipping");
1561 | T_IXFR_TMP L_QSTRING
1563 if (!set_zone_ixfr_tmp(current_zone, $2))
1565 "zone ixfr temp filename already set; skipping");
1567 | T_MASTERS maybe_zero_port '{' master_in_addr_list '}'
1569 set_zone_master_port(current_zone, $2);
1571 | T_TRANSFER_SOURCE maybe_wild_addr
1573 set_zone_transfer_source(current_zone, $2);
1575 | T_CHECK_NAMES check_names_opt
1577 if (!set_zone_checknames(current_zone, (enum severity)$2))
1579 "zone checknames already set; skipping");
1581 | T_ALLOW_UPDATE '{' address_match_list '}'
1583 if (!set_zone_update_acl(current_zone, $3))
1585 "zone update acl already set; skipping");
1587 | T_ALLOW_QUERY '{' address_match_list '}'
1589 if (!set_zone_query_acl(current_zone, $3))
1591 "zone query acl already set; skipping");
1593 | T_ALLOW_TRANSFER '{' address_match_list '}'
1595 if (!set_zone_transfer_acl(current_zone, $3))
1597 "zone transfer acl already set; skipping");
1599 | T_FORWARD zone_forward_opt
1602 struct zoneinfo *zp = current_zone.opaque;
1604 free_forwarders(zp->z_fwdtab);
1605 zp->z_fwdtab = NULL;
1609 '{' opt_zone_forwarders_list '}'
1610 | T_MAX_TRANSFER_TIME_IN L_NUMBER
1612 if (!set_zone_transfer_time_in(current_zone, $2*60))
1614 "zone max transfer time (in) already set; skipping");
1616 | T_MAX_LOG_SIZE_IXFR L_NUMBER
1618 set_zone_max_log_size_ixfr(current_zone, $2);
1620 | T_NOTIFY yea_or_nay
1622 set_zone_notify(current_zone, $2);
1624 | T_MAINTAIN_IXFR_BASE yea_or_nay
1626 set_zone_maintain_ixfr_base(current_zone, $2);
1628 | T_PUBKEY L_NUMBER L_NUMBER L_NUMBER L_QSTRING
1630 /* flags proto alg key */
1631 set_zone_pubkey(current_zone, $2, $3, $4, $5);
1633 | T_PUBKEY L_STRING L_NUMBER L_NUMBER L_QSTRING
1635 /* flags proto alg key */
1637 int flags = (int) strtol($2, &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);
1644 | T_ALSO_NOTIFY '{' opt_notify_in_addr_list '}'
1645 | T_DIALUP yea_or_nay
1647 set_zone_dialup(current_zone, $2);
1652 master_in_addr_list: master_in_addr L_EOS
1656 | master_in_addr_list master_in_addr L_EOS
1662 master_in_addr: L_IPADDR
1664 add_zone_master(current_zone, $1);
1668 opt_notify_in_addr_list: /* nothing */
1669 | notify_in_addr_list
1672 notify_in_addr_list: notify_in_addr L_EOS
1676 | notify_in_addr_list notify_in_addr L_EOS
1682 notify_in_addr: L_IPADDR
1684 add_zone_notify(current_zone, $1);
1688 zone_forward_opt: T_ONLY
1690 set_zone_boolean_option(current_zone, OPTION_FORWARD_ONLY, 1);
1694 set_zone_boolean_option(current_zone, OPTION_FORWARD_ONLY, 0);
1698 opt_zone_forwarders_list: /* nothing */
1700 set_zone_forward(current_zone);
1702 | zone_forwarders_in_addr_list
1705 zone_forwarders_in_addr_list: zone_forwarders_in_addr L_EOS
1709 | zone_forwarders_in_addr_list zone_forwarders_in_addr L_EOS
1715 zone_forwarders_in_addr: L_IPADDR
1717 add_zone_forwarder(current_zone, $1);
1722 * Trusted Key statement
1725 trusted_keys_stmt: T_TRUSTED_KEYS '{' trusted_keys_list '}'
1729 trusted_keys_list: trusted_key L_EOS
1733 | trusted_keys_list trusted_key L_EOS
1738 trusted_key: L_STRING L_NUMBER L_NUMBER L_NUMBER L_QSTRING
1740 /* name flags proto alg key */
1741 set_trusted_key($1, $2, $3, $4, $5);
1743 | L_STRING L_STRING L_NUMBER L_NUMBER L_QSTRING
1745 /* name flags proto alg key */
1747 int flags = (int) strtol($2, &endp, 0);
1749 ns_panic(ns_log_parser, 1,
1750 "Invalid flags string: %s", $2);
1751 set_trusted_key($1, flags, $3, $4, $5);
1761 if ($1 < 0 || $1 > 65535) {
1763 "invalid IP port number '%d'; setting port to 0",
1771 any_string: L_STRING
1778 canonical_name(char *name) {
1779 char canonical[MAXDNAME];
1781 if (strlen(name) >= MAXDNAME)
1783 strcpy(canonical, name);
1784 if (makename(canonical, ".", sizeof canonical) < 0)
1786 return (savestr(canonical, 0));
1791 ip_match_element ime;
1793 struct in_addr address;
1795 /* Create the predefined ACLs */
1797 address.s_addr = 0U;
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);
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);
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);
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);
1826 free_sym_value(int type, void *value) {
1827 ns_debug(ns_log_parser, 99, "free_sym_value: type %06x value %p",
1832 free_ip_match_list(value);
1835 free_key_info(value);
1838 ns_panic(ns_log_parser, 1,
1839 "unhandled case in free_sym_value()");
1846 lookup_channel(char *name) {
1849 if (lookup_symbol(symtab, name, SYM_CHANNEL, &value))
1850 return ((log_channel)(value.pointer));
1855 define_channel(char *name, log_channel channel) {
1858 value.pointer = channel;
1859 define_symbol(symtab, name, SYM_CHANNEL, value, SYMBOL_FREE_KEY);
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);
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);
1879 define_builtin_channels();
1880 INIT_LIST(current_controls);
1886 free_symbol_table(symtab);
1889 * We don't clean up authtab here because the ip_match_lists are in
1899 lookup_acl(char *name) {
1902 if (lookup_symbol(authtab, name, SYM_ACL, &value))
1903 return ((ip_match_list)(value.pointer));
1908 define_acl(char *name, ip_match_list iml) {
1911 INSIST(name != NULL);
1912 INSIST(iml != NULL);
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 ");
1922 lookup_key(char *name) {
1925 if (lookup_symbol(authtab, name, SYM_KEY, &value))
1926 return ((struct dst_key *)(value.pointer));
1931 define_key(char *name, struct dst_key *dst_key) {
1934 INSIST(name != NULL);
1935 INSIST(dst_key != NULL);
1937 value.pointer = dst_key;
1938 define_symbol(authtab, name, SYM_KEY, value, SYMBOL_FREE_VALUE);
1939 dprint_key_info(dst_key);
1943 parse_configuration(const char *filename) {
1944 FILE *config_stream;
1946 config_stream = fopen(filename, "r");
1947 if (config_stream == NULL)
1948 ns_panic(ns_log_parser, 0, "can't open '%s'", filename);
1952 lexer_begin_file(filename, config_stream);
1959 parser_initialize(void) {
1964 parser_shutdown(void) {
1965 if (authtab != NULL)
1966 free_symbol_table(authtab);