4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2002, 2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: namedconf.c,v 1.113 2009/12/04 21:09:34 marka Exp */
30 #include <isc/result.h>
31 #include <isc/string.h>
34 #include <isccfg/cfg.h>
35 #include <isccfg/grammar.h>
36 #include <isccfg/log.h>
38 #define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)
40 /*% Check a return value. */
43 if (result != ISC_R_SUCCESS) goto cleanup; \
46 /*% Clean up a configuration object if non-NULL. */
47 #define CLEANUP_OBJ(obj) \
48 do { if ((obj) != NULL) cfg_obj_destroy(pctx, &(obj)); } while (0)
52 * Forward declarations of static functions.
56 parse_enum_or_other(cfg_parser_t
*pctx
, const cfg_type_t
*enumtype
,
57 const cfg_type_t
*othertype
, cfg_obj_t
**ret
);
60 parse_keyvalue(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
);
63 parse_optional_keyvalue(cfg_parser_t
*pctx
, const cfg_type_t
*type
,
67 parse_updatepolicy(cfg_parser_t
*pctx
, const cfg_type_t
*type
,
71 doc_updatepolicy(cfg_printer_t
*pctx
, const cfg_type_t
*type
);
74 print_keyvalue(cfg_printer_t
*pctx
, const cfg_obj_t
*obj
);
77 doc_keyvalue(cfg_printer_t
*pctx
, const cfg_type_t
*type
);
80 doc_optional_keyvalue(cfg_printer_t
*pctx
, const cfg_type_t
*type
);
82 static cfg_type_t cfg_type_acl
;
83 static cfg_type_t cfg_type_addrmatchelt
;
84 static cfg_type_t cfg_type_bracketed_aml
;
85 static cfg_type_t cfg_type_bracketed_namesockaddrkeylist
;
86 static cfg_type_t cfg_type_bracketed_sockaddrlist
;
87 static cfg_type_t cfg_type_bracketed_sockaddrnameportlist
;
88 static cfg_type_t cfg_type_controls
;
89 static cfg_type_t cfg_type_controls_sockaddr
;
90 static cfg_type_t cfg_type_destinationlist
;
91 static cfg_type_t cfg_type_dialuptype
;
92 static cfg_type_t cfg_type_ixfrdifftype
;
93 static cfg_type_t cfg_type_key
;
94 static cfg_type_t cfg_type_logfile
;
95 static cfg_type_t cfg_type_logging
;
96 static cfg_type_t cfg_type_logseverity
;
97 static cfg_type_t cfg_type_lwres
;
98 static cfg_type_t cfg_type_masterselement
;
99 static cfg_type_t cfg_type_nameportiplist
;
100 static cfg_type_t cfg_type_negated
;
101 static cfg_type_t cfg_type_notifytype
;
102 static cfg_type_t cfg_type_optional_allow
;
103 static cfg_type_t cfg_type_optional_class
;
104 static cfg_type_t cfg_type_optional_facility
;
105 static cfg_type_t cfg_type_optional_keyref
;
106 static cfg_type_t cfg_type_optional_port
;
107 static cfg_type_t cfg_type_options
;
108 static cfg_type_t cfg_type_portiplist
;
109 static cfg_type_t cfg_type_querysource4
;
110 static cfg_type_t cfg_type_querysource6
;
111 static cfg_type_t cfg_type_querysource
;
112 static cfg_type_t cfg_type_server
;
113 static cfg_type_t cfg_type_server_key_kludge
;
114 static cfg_type_t cfg_type_size
;
115 static cfg_type_t cfg_type_sizenodefault
;
116 static cfg_type_t cfg_type_sockaddr4wild
;
117 static cfg_type_t cfg_type_sockaddr6wild
;
118 static cfg_type_t cfg_type_statschannels
;
119 static cfg_type_t cfg_type_view
;
120 static cfg_type_t cfg_type_viewopts
;
121 static cfg_type_t cfg_type_zone
;
122 static cfg_type_t cfg_type_zoneopts
;
123 static cfg_type_t cfg_type_dynamically_loadable_zones
;
124 static cfg_type_t cfg_type_dynamically_loadable_zones_opts
;
125 #ifdef ALLOW_FILTER_AAAA_ON_V4
126 static cfg_type_t cfg_type_v4_aaaa
;
130 * Clauses that can be found in a 'dynamically loadable zones' statement
132 static cfg_clausedef_t
133 dynamically_loadable_zones_clauses
[] = {
134 { "database", &cfg_type_astring
, 0 },
139 * A dynamically loadable zones statement.
141 static cfg_tuplefielddef_t dynamically_loadable_zones_fields
[] = {
142 { "name", &cfg_type_astring
, 0 },
143 { "options", &cfg_type_dynamically_loadable_zones_opts
, 0 },
147 static cfg_type_t cfg_type_dynamically_loadable_zones
= {
148 "dlz", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
150 dynamically_loadable_zones_fields
156 static cfg_tuplefielddef_t tkey_dhkey_fields
[] = {
157 { "name", &cfg_type_qstring
, 0 },
158 { "keyid", &cfg_type_uint32
, 0 },
162 static cfg_type_t cfg_type_tkey_dhkey
= {
163 "tkey-dhkey", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
,
169 static cfg_tuplefielddef_t listenon_fields
[] = {
170 { "port", &cfg_type_optional_port
, 0 },
171 { "acl", &cfg_type_bracketed_aml
, 0 },
174 static cfg_type_t cfg_type_listenon
= {
175 "listenon", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
, listenon_fields
};
179 static cfg_tuplefielddef_t acl_fields
[] = {
180 { "name", &cfg_type_astring
, 0 },
181 { "value", &cfg_type_bracketed_aml
, 0 },
185 static cfg_type_t cfg_type_acl
= {
186 "acl", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
, acl_fields
};
189 static cfg_tuplefielddef_t masters_fields
[] = {
190 { "name", &cfg_type_astring
, 0 },
191 { "port", &cfg_type_optional_port
, 0 },
192 { "addresses", &cfg_type_bracketed_namesockaddrkeylist
, 0 },
196 static cfg_type_t cfg_type_masters
= {
197 "masters", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
, masters_fields
};
200 * "sockaddrkeylist", a list of socket addresses with optional keys
201 * and an optional default port, as used in the masters option.
203 * "port 1234 { mymasters; 10.0.0.1 key foo; 1::2 port 69; }"
206 static cfg_tuplefielddef_t namesockaddrkey_fields
[] = {
207 { "masterselement", &cfg_type_masterselement
, 0 },
208 { "key", &cfg_type_optional_keyref
, 0 },
212 static cfg_type_t cfg_type_namesockaddrkey
= {
213 "namesockaddrkey", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
,
214 namesockaddrkey_fields
217 static cfg_type_t cfg_type_bracketed_namesockaddrkeylist
= {
218 "bracketed_namesockaddrkeylist", cfg_parse_bracketed_list
,
219 cfg_print_bracketed_list
, cfg_doc_bracketed_list
, &cfg_rep_list
, &cfg_type_namesockaddrkey
222 static cfg_tuplefielddef_t namesockaddrkeylist_fields
[] = {
223 { "port", &cfg_type_optional_port
, 0 },
224 { "addresses", &cfg_type_bracketed_namesockaddrkeylist
, 0 },
227 static cfg_type_t cfg_type_namesockaddrkeylist
= {
228 "sockaddrkeylist", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
,
229 namesockaddrkeylist_fields
233 * A list of socket addresses with an optional default port,
234 * as used in the also-notify option. E.g.,
235 * "port 1234 { 10.0.0.1; 1::2 port 69; }"
237 static cfg_tuplefielddef_t portiplist_fields
[] = {
238 { "port", &cfg_type_optional_port
, 0 },
239 { "addresses", &cfg_type_bracketed_sockaddrlist
, 0 },
242 static cfg_type_t cfg_type_portiplist
= {
243 "portiplist", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
,
248 * A public key, as in the "pubkey" statement.
250 static cfg_tuplefielddef_t pubkey_fields
[] = {
251 { "flags", &cfg_type_uint32
, 0 },
252 { "protocol", &cfg_type_uint32
, 0 },
253 { "algorithm", &cfg_type_uint32
, 0 },
254 { "key", &cfg_type_qstring
, 0 },
257 static cfg_type_t cfg_type_pubkey
= {
258 "pubkey", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
259 &cfg_rep_tuple
, pubkey_fields
};
262 * A list of RR types, used in grant statements.
263 * Note that the old parser allows quotes around the RR type names.
265 static cfg_type_t cfg_type_rrtypelist
= {
266 "rrtypelist", cfg_parse_spacelist
, cfg_print_spacelist
,
267 cfg_doc_terminal
, &cfg_rep_list
, &cfg_type_astring
270 static const char *mode_enums
[] = { "grant", "deny", NULL
};
271 static cfg_type_t cfg_type_mode
= {
272 "mode", cfg_parse_enum
, cfg_print_ustring
, cfg_doc_enum
,
273 &cfg_rep_string
, &mode_enums
277 parse_matchtype(cfg_parser_t
*pctx
, const cfg_type_t
*type
,
281 CHECK(cfg_peektoken(pctx
, 0));
282 if (pctx
->token
.type
== isc_tokentype_string
&&
283 strcasecmp(TOKEN_STRING(pctx
), "zonesub") == 0) {
284 pctx
->flags
|= CFG_PCTX_SKIP
;
286 return (cfg_parse_enum(pctx
, type
, ret
));
293 parse_matchname(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
295 cfg_obj_t
*obj
= NULL
;
297 if ((pctx
->flags
& CFG_PCTX_SKIP
) != 0) {
298 pctx
->flags
&= ~CFG_PCTX_SKIP
;
299 CHECK(cfg_parse_void(pctx
, NULL
, &obj
));
301 result
= cfg_parse_astring(pctx
, type
, &obj
);
309 doc_matchname(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
310 cfg_print_chars(pctx
, "[ ", 2);
311 cfg_doc_obj(pctx
, type
->of
);
312 cfg_print_chars(pctx
, " ]", 2);
315 static const char *matchtype_enums
[] = {
316 "name", "subdomain", "wildcard", "self", "selfsub", "selfwild",
317 "krb5-self", "ms-self", "krb5-subdomain", "ms-subdomain",
318 "tcp-self", "6to4-self", "zonesub", NULL
};
320 static cfg_type_t cfg_type_matchtype
= {
321 "matchtype", parse_matchtype
, cfg_print_ustring
,
322 cfg_doc_enum
, &cfg_rep_string
, &matchtype_enums
325 static cfg_type_t cfg_type_matchname
= {
326 "optional_matchname", parse_matchname
, cfg_print_ustring
,
327 &doc_matchname
, &cfg_rep_tuple
, &cfg_type_ustring
331 * A grant statement, used in the update policy.
333 static cfg_tuplefielddef_t grant_fields
[] = {
334 { "mode", &cfg_type_mode
, 0 },
335 { "identity", &cfg_type_astring
, 0 }, /* domain name */
336 { "matchtype", &cfg_type_matchtype
, 0 },
337 { "name", &cfg_type_matchname
, 0 }, /* domain name */
338 { "types", &cfg_type_rrtypelist
, 0 },
341 static cfg_type_t cfg_type_grant
= {
342 "grant", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
343 &cfg_rep_tuple
, grant_fields
346 static cfg_type_t cfg_type_updatepolicy
= {
347 "update_policy", parse_updatepolicy
, NULL
, doc_updatepolicy
,
348 &cfg_rep_list
, &cfg_type_grant
352 parse_updatepolicy(cfg_parser_t
*pctx
, const cfg_type_t
*type
,
355 CHECK(cfg_gettoken(pctx
, 0));
356 if (pctx
->token
.type
== isc_tokentype_special
&&
357 pctx
->token
.value
.as_char
== '{') {
358 cfg_ungettoken(pctx
);
359 return (cfg_parse_bracketed_list(pctx
, type
, ret
));
362 if (pctx
->token
.type
== isc_tokentype_string
&&
363 strcasecmp(TOKEN_STRING(pctx
), "local") == 0) {
364 cfg_obj_t
*obj
= NULL
;
365 CHECK(cfg_create_obj(pctx
, &cfg_type_ustring
, &obj
));
366 obj
->value
.string
.length
= strlen("local");
367 obj
->value
.string
.base
= isc_mem_get(pctx
->mctx
,
368 obj
->value
.string
.length
+ 1);
369 if (obj
->value
.string
.base
== NULL
) {
370 isc_mem_put(pctx
->mctx
, obj
, sizeof(*obj
));
371 return (ISC_R_NOMEMORY
);
373 memcpy(obj
->value
.string
.base
, "local", 5);
374 obj
->value
.string
.base
[5] = '\0';
376 return (ISC_R_SUCCESS
);
379 cfg_ungettoken(pctx
);
380 return (ISC_R_UNEXPECTEDTOKEN
);
387 doc_updatepolicy(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
388 cfg_print_chars(pctx
, "( local | { ", 12);
389 cfg_doc_obj(pctx
, type
->of
);
390 cfg_print_chars(pctx
, "; ... }", 7);
396 static cfg_tuplefielddef_t view_fields
[] = {
397 { "name", &cfg_type_astring
, 0 },
398 { "class", &cfg_type_optional_class
, 0 },
399 { "options", &cfg_type_viewopts
, 0 },
402 static cfg_type_t cfg_type_view
= {
403 "view", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
404 &cfg_rep_tuple
, view_fields
410 static cfg_tuplefielddef_t zone_fields
[] = {
411 { "name", &cfg_type_astring
, 0 },
412 { "class", &cfg_type_optional_class
, 0 },
413 { "options", &cfg_type_zoneopts
, 0 },
416 static cfg_type_t cfg_type_zone
= {
417 "zone", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
418 &cfg_rep_tuple
, zone_fields
422 * A "category" clause in the "logging" statement.
424 static cfg_tuplefielddef_t category_fields
[] = {
425 { "name", &cfg_type_astring
, 0 },
426 { "destinations", &cfg_type_destinationlist
,0 },
429 static cfg_type_t cfg_type_category
= {
430 "category", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
431 &cfg_rep_tuple
, category_fields
436 * A dnssec key, as used in the "trusted-keys" statement.
438 static cfg_tuplefielddef_t dnsseckey_fields
[] = {
439 { "name", &cfg_type_astring
, 0 },
440 { "flags", &cfg_type_uint32
, 0 },
441 { "protocol", &cfg_type_uint32
, 0 },
442 { "algorithm", &cfg_type_uint32
, 0 },
443 { "key", &cfg_type_qstring
, 0 },
446 static cfg_type_t cfg_type_dnsseckey
= {
447 "dnsseckey", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
448 &cfg_rep_tuple
, dnsseckey_fields
452 * A managed key initialization specifier, as used in the
453 * "managed-keys" statement.
455 static cfg_tuplefielddef_t managedkey_fields
[] = {
456 { "name", &cfg_type_astring
, 0 },
457 { "init", &cfg_type_ustring
, 0 }, /* must be literal "initial-key" */
458 { "flags", &cfg_type_uint32
, 0 },
459 { "protocol", &cfg_type_uint32
, 0 },
460 { "algorithm", &cfg_type_uint32
, 0 },
461 { "key", &cfg_type_qstring
, 0 },
464 static cfg_type_t cfg_type_managedkey
= {
465 "managedkey", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
466 &cfg_rep_tuple
, managedkey_fields
469 static keyword_type_t wild_class_kw
= { "class", &cfg_type_ustring
};
471 static cfg_type_t cfg_type_optional_wild_class
= {
472 "optional_wild_class", parse_optional_keyvalue
, print_keyvalue
,
473 doc_optional_keyvalue
, &cfg_rep_string
, &wild_class_kw
476 static keyword_type_t wild_type_kw
= { "type", &cfg_type_ustring
};
478 static cfg_type_t cfg_type_optional_wild_type
= {
479 "optional_wild_type", parse_optional_keyvalue
,
480 print_keyvalue
, doc_optional_keyvalue
, &cfg_rep_string
, &wild_type_kw
483 static keyword_type_t wild_name_kw
= { "name", &cfg_type_qstring
};
485 static cfg_type_t cfg_type_optional_wild_name
= {
486 "optional_wild_name", parse_optional_keyvalue
,
487 print_keyvalue
, doc_optional_keyvalue
, &cfg_rep_string
, &wild_name_kw
491 * An rrset ordering element.
493 static cfg_tuplefielddef_t rrsetorderingelement_fields
[] = {
494 { "class", &cfg_type_optional_wild_class
, 0 },
495 { "type", &cfg_type_optional_wild_type
, 0 },
496 { "name", &cfg_type_optional_wild_name
, 0 },
497 { "order", &cfg_type_ustring
, 0 }, /* must be literal "order" */
498 { "ordering", &cfg_type_ustring
, 0 },
501 static cfg_type_t cfg_type_rrsetorderingelement
= {
502 "rrsetorderingelement", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
,
503 rrsetorderingelement_fields
507 * A global or view "check-names" option. Note that the zone
508 * "check-names" option has a different syntax.
511 static const char *checktype_enums
[] = { "master", "slave", "response", NULL
};
512 static cfg_type_t cfg_type_checktype
= {
513 "checktype", cfg_parse_enum
, cfg_print_ustring
, cfg_doc_enum
,
514 &cfg_rep_string
, &checktype_enums
517 static const char *checkmode_enums
[] = { "fail", "warn", "ignore", NULL
};
518 static cfg_type_t cfg_type_checkmode
= {
519 "checkmode", cfg_parse_enum
, cfg_print_ustring
, cfg_doc_enum
,
520 &cfg_rep_string
, &checkmode_enums
523 static cfg_tuplefielddef_t checknames_fields
[] = {
524 { "type", &cfg_type_checktype
, 0 },
525 { "mode", &cfg_type_checkmode
, 0 },
529 static cfg_type_t cfg_type_checknames
= {
530 "checknames", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
,
534 static cfg_type_t cfg_type_bracketed_sockaddrlist
= {
535 "bracketed_sockaddrlist", cfg_parse_bracketed_list
, cfg_print_bracketed_list
, cfg_doc_bracketed_list
,
536 &cfg_rep_list
, &cfg_type_sockaddr
539 static const char *autodnssec_enums
[] = { "allow", "maintain", "create",
541 static cfg_type_t cfg_type_autodnssec
= {
542 "autodnssec", cfg_parse_enum
, cfg_print_ustring
, cfg_doc_enum
,
543 &cfg_rep_string
, &autodnssec_enums
546 static cfg_type_t cfg_type_rrsetorder
= {
547 "rrsetorder", cfg_parse_bracketed_list
, cfg_print_bracketed_list
, cfg_doc_bracketed_list
,
548 &cfg_rep_list
, &cfg_type_rrsetorderingelement
551 static keyword_type_t port_kw
= { "port", &cfg_type_uint32
};
553 static cfg_type_t cfg_type_optional_port
= {
554 "optional_port", parse_optional_keyvalue
, print_keyvalue
,
555 doc_optional_keyvalue
, &cfg_rep_uint32
, &port_kw
558 /*% A list of keys, as in the "key" clause of the controls statement. */
559 static cfg_type_t cfg_type_keylist
= {
560 "keylist", cfg_parse_bracketed_list
, cfg_print_bracketed_list
,
561 cfg_doc_bracketed_list
, &cfg_rep_list
, &cfg_type_astring
564 /*% A list of dnssec keys, as in "trusted-keys" */
565 static cfg_type_t cfg_type_dnsseckeys
= {
566 "dnsseckeys", cfg_parse_bracketed_list
, cfg_print_bracketed_list
,
567 cfg_doc_bracketed_list
, &cfg_rep_list
, &cfg_type_dnsseckey
571 * A list of managed key entries, as in "trusted-keys". Currently
572 * (9.7.0) this has a format similar to dnssec keys, except the keyname
573 * is followed by the keyword "initial-key". In future releases, this
574 * keyword may take other values indicating different methods for the
575 * key to be initialized.
578 static cfg_type_t cfg_type_managedkeys
= {
579 "managedkeys", cfg_parse_bracketed_list
, cfg_print_bracketed_list
,
580 cfg_doc_bracketed_list
, &cfg_rep_list
, &cfg_type_managedkey
583 static const char *forwardtype_enums
[] = { "first", "only", NULL
};
584 static cfg_type_t cfg_type_forwardtype
= {
585 "forwardtype", cfg_parse_enum
, cfg_print_ustring
, cfg_doc_enum
, &cfg_rep_string
,
589 static const char *zonetype_enums
[] = {
590 "master", "slave", "stub", "hint", "forward", "delegation-only", NULL
};
591 static cfg_type_t cfg_type_zonetype
= {
592 "zonetype", cfg_parse_enum
, cfg_print_ustring
, cfg_doc_enum
,
593 &cfg_rep_string
, &zonetype_enums
596 static const char *loglevel_enums
[] = {
597 "critical", "error", "warning", "notice", "info", "dynamic", NULL
};
598 static cfg_type_t cfg_type_loglevel
= {
599 "loglevel", cfg_parse_enum
, cfg_print_ustring
, cfg_doc_enum
, &cfg_rep_string
,
603 static const char *transferformat_enums
[] = {
604 "many-answers", "one-answer", NULL
};
605 static cfg_type_t cfg_type_transferformat
= {
606 "transferformat", cfg_parse_enum
, cfg_print_ustring
, cfg_doc_enum
, &cfg_rep_string
,
607 &transferformat_enums
611 * The special keyword "none", as used in the pid-file option.
615 print_none(cfg_printer_t
*pctx
, const cfg_obj_t
*obj
) {
617 cfg_print_chars(pctx
, "none", 4);
620 static cfg_type_t cfg_type_none
= {
621 "none", NULL
, print_none
, NULL
, &cfg_rep_void
, NULL
625 * A quoted string or the special keyword "none". Used in the pid-file option.
628 parse_qstringornone(cfg_parser_t
*pctx
, const cfg_type_t
*type
,
633 CHECK(cfg_gettoken(pctx
, CFG_LEXOPT_QSTRING
));
634 if (pctx
->token
.type
== isc_tokentype_string
&&
635 strcasecmp(TOKEN_STRING(pctx
), "none") == 0)
636 return (cfg_create_obj(pctx
, &cfg_type_none
, ret
));
637 cfg_ungettoken(pctx
);
638 return (cfg_parse_qstring(pctx
, type
, ret
));
644 doc_qstringornone(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
646 cfg_print_chars(pctx
, "( <quoted_string> | none )", 26);
649 static cfg_type_t cfg_type_qstringornone
= {
650 "qstringornone", parse_qstringornone
, NULL
, doc_qstringornone
,
659 print_hostname(cfg_printer_t
*pctx
, const cfg_obj_t
*obj
) {
661 cfg_print_chars(pctx
, "hostname", 4);
664 static cfg_type_t cfg_type_hostname
= {
665 "hostname", NULL
, print_hostname
, NULL
, &cfg_rep_boolean
, NULL
669 * "server-id" argument.
673 parse_serverid(cfg_parser_t
*pctx
, const cfg_type_t
*type
,
677 CHECK(cfg_gettoken(pctx
, CFG_LEXOPT_QSTRING
));
678 if (pctx
->token
.type
== isc_tokentype_string
&&
679 strcasecmp(TOKEN_STRING(pctx
), "none") == 0)
680 return (cfg_create_obj(pctx
, &cfg_type_none
, ret
));
681 if (pctx
->token
.type
== isc_tokentype_string
&&
682 strcasecmp(TOKEN_STRING(pctx
), "hostname") == 0) {
683 return (cfg_create_obj(pctx
, &cfg_type_hostname
, ret
));
685 cfg_ungettoken(pctx
);
686 return (cfg_parse_qstring(pctx
, type
, ret
));
692 doc_serverid(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
694 cfg_print_chars(pctx
, "( <quoted_string> | none | hostname )", 26);
697 static cfg_type_t cfg_type_serverid
= {
698 "serverid", parse_serverid
, NULL
, doc_serverid
, NULL
, NULL
};
703 static cfg_tuplefielddef_t porttuple_fields
[] = {
704 { "loport", &cfg_type_uint32
, 0 },
705 { "hiport", &cfg_type_uint32
, 0 },
708 static cfg_type_t cfg_type_porttuple
= {
709 "porttuple", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
710 &cfg_rep_tuple
, porttuple_fields
714 parse_port(cfg_parser_t
*pctx
, cfg_obj_t
**ret
) {
717 CHECK(cfg_parse_uint32(pctx
, NULL
, ret
));
718 if ((*ret
)->value
.uint32
> 0xffff) {
719 cfg_parser_error(pctx
, CFG_LOG_NEAR
, "invalid port");
720 cfg_obj_destroy(pctx
, ret
);
721 result
= ISC_R_RANGE
;
729 parse_portrange(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
731 cfg_obj_t
*obj
= NULL
;
735 CHECK(cfg_peektoken(pctx
, ISC_LEXOPT_NUMBER
| ISC_LEXOPT_CNUMBER
));
736 if (pctx
->token
.type
== isc_tokentype_number
)
737 CHECK(parse_port(pctx
, ret
));
739 CHECK(cfg_gettoken(pctx
, 0));
740 if (pctx
->token
.type
!= isc_tokentype_string
||
741 strcasecmp(TOKEN_STRING(pctx
), "range") != 0) {
742 cfg_parser_error(pctx
, CFG_LOG_NEAR
,
743 "expected integer or 'range'");
744 return (ISC_R_UNEXPECTEDTOKEN
);
746 CHECK(cfg_create_tuple(pctx
, &cfg_type_porttuple
, &obj
));
747 CHECK(parse_port(pctx
, &obj
->value
.tuple
[0]));
748 CHECK(parse_port(pctx
, &obj
->value
.tuple
[1]));
749 if (obj
->value
.tuple
[0]->value
.uint32
>
750 obj
->value
.tuple
[1]->value
.uint32
) {
751 cfg_parser_error(pctx
, CFG_LOG_NOPREP
,
752 "low port '%u' must not be larger "
754 obj
->value
.tuple
[0]->value
.uint32
);
755 result
= ISC_R_RANGE
;
764 cfg_obj_destroy(pctx
, &obj
);
768 static cfg_type_t cfg_type_portrange
= {
769 "portrange", parse_portrange
, NULL
, cfg_doc_terminal
,
773 static cfg_type_t cfg_type_bracketed_portlist
= {
774 "bracketed_sockaddrlist", cfg_parse_bracketed_list
,
775 cfg_print_bracketed_list
, cfg_doc_bracketed_list
,
776 &cfg_rep_list
, &cfg_type_portrange
780 * Clauses that can be found within the top level of the named.conf
783 static cfg_clausedef_t
784 namedconf_clauses
[] = {
785 { "options", &cfg_type_options
, 0 },
786 { "controls", &cfg_type_controls
, CFG_CLAUSEFLAG_MULTI
},
787 { "acl", &cfg_type_acl
, CFG_CLAUSEFLAG_MULTI
},
788 { "masters", &cfg_type_masters
, CFG_CLAUSEFLAG_MULTI
},
789 { "logging", &cfg_type_logging
, 0 },
790 { "view", &cfg_type_view
, CFG_CLAUSEFLAG_MULTI
},
791 { "lwres", &cfg_type_lwres
, CFG_CLAUSEFLAG_MULTI
},
792 { "statistics-channels", &cfg_type_statschannels
,
793 CFG_CLAUSEFLAG_MULTI
},
798 * Clauses that can occur at the top level or in the view
799 * statement, but not in the options block.
801 static cfg_clausedef_t
802 namedconf_or_view_clauses
[] = {
803 { "key", &cfg_type_key
, CFG_CLAUSEFLAG_MULTI
},
804 { "zone", &cfg_type_zone
, CFG_CLAUSEFLAG_MULTI
},
805 /* only 1 DLZ per view allowed */
806 { "dlz", &cfg_type_dynamically_loadable_zones
, 0 },
807 { "server", &cfg_type_server
, CFG_CLAUSEFLAG_MULTI
},
808 { "trusted-keys", &cfg_type_dnsseckeys
, CFG_CLAUSEFLAG_MULTI
},
809 { "managed-keys", &cfg_type_managedkeys
, CFG_CLAUSEFLAG_MULTI
},
814 * Clauses that can occur in the bind.keys file.
816 static cfg_clausedef_t
817 bindkeys_clauses
[] = {
818 { "trusted-keys", &cfg_type_dnsseckeys
, CFG_CLAUSEFLAG_MULTI
},
819 { "managed-keys", &cfg_type_managedkeys
, CFG_CLAUSEFLAG_MULTI
},
824 * Clauses that can be found within the 'options' statement.
826 static cfg_clausedef_t
827 options_clauses
[] = {
828 { "use-v4-udp-ports", &cfg_type_bracketed_portlist
, 0 },
829 { "use-v6-udp-ports", &cfg_type_bracketed_portlist
, 0 },
830 { "avoid-v4-udp-ports", &cfg_type_bracketed_portlist
, 0 },
831 { "avoid-v6-udp-ports", &cfg_type_bracketed_portlist
, 0 },
832 { "bindkeys-file", &cfg_type_qstring
, 0 },
833 { "blackhole", &cfg_type_bracketed_aml
, 0 },
834 { "coresize", &cfg_type_size
, 0 },
835 { "datasize", &cfg_type_size
, 0 },
836 { "session-keyfile", &cfg_type_qstringornone
, 0 },
837 { "session-keyname", &cfg_type_astring
, 0 },
838 { "session-keyalg", &cfg_type_astring
, 0 },
839 { "deallocate-on-exit", &cfg_type_boolean
, CFG_CLAUSEFLAG_OBSOLETE
},
840 { "directory", &cfg_type_qstring
, CFG_CLAUSEFLAG_CALLBACK
},
841 { "dump-file", &cfg_type_qstring
, 0 },
842 { "fake-iquery", &cfg_type_boolean
, CFG_CLAUSEFLAG_OBSOLETE
},
843 { "files", &cfg_type_size
, 0 },
844 { "has-old-clients", &cfg_type_boolean
, CFG_CLAUSEFLAG_OBSOLETE
},
845 { "heartbeat-interval", &cfg_type_uint32
, 0 },
846 { "host-statistics", &cfg_type_boolean
, CFG_CLAUSEFLAG_NOTIMP
},
847 { "host-statistics-max", &cfg_type_uint32
, CFG_CLAUSEFLAG_NOTIMP
},
848 { "hostname", &cfg_type_qstringornone
, 0 },
849 { "interface-interval", &cfg_type_uint32
, 0 },
850 { "listen-on", &cfg_type_listenon
, CFG_CLAUSEFLAG_MULTI
},
851 { "listen-on-v6", &cfg_type_listenon
, CFG_CLAUSEFLAG_MULTI
},
852 { "match-mapped-addresses", &cfg_type_boolean
, 0 },
853 { "memstatistics-file", &cfg_type_qstring
, 0 },
854 { "memstatistics", &cfg_type_boolean
, 0 },
855 { "multiple-cnames", &cfg_type_boolean
, CFG_CLAUSEFLAG_OBSOLETE
},
856 { "named-xfer", &cfg_type_qstring
, CFG_CLAUSEFLAG_OBSOLETE
},
857 { "pid-file", &cfg_type_qstringornone
, 0 },
858 { "port", &cfg_type_uint32
, 0 },
859 { "querylog", &cfg_type_boolean
, 0 },
860 { "recursing-file", &cfg_type_qstring
, 0 },
861 { "random-device", &cfg_type_qstring
, 0 },
862 { "recursive-clients", &cfg_type_uint32
, 0 },
863 { "reserved-sockets", &cfg_type_uint32
, 0 },
864 { "serial-queries", &cfg_type_uint32
, CFG_CLAUSEFLAG_OBSOLETE
},
865 { "serial-query-rate", &cfg_type_uint32
, 0 },
866 { "server-id", &cfg_type_serverid
, 0 },
867 { "stacksize", &cfg_type_size
, 0 },
868 { "statistics-file", &cfg_type_qstring
, 0 },
869 { "statistics-interval", &cfg_type_uint32
, CFG_CLAUSEFLAG_NYI
},
870 { "tcp-clients", &cfg_type_uint32
, 0 },
871 { "tcp-listen-queue", &cfg_type_uint32
, 0 },
872 { "tkey-dhkey", &cfg_type_tkey_dhkey
, 0 },
873 { "tkey-gssapi-credential", &cfg_type_qstring
, 0 },
874 { "tkey-domain", &cfg_type_qstring
, 0 },
875 { "transfers-per-ns", &cfg_type_uint32
, 0 },
876 { "transfers-in", &cfg_type_uint32
, 0 },
877 { "transfers-out", &cfg_type_uint32
, 0 },
878 { "treat-cr-as-space", &cfg_type_boolean
, CFG_CLAUSEFLAG_OBSOLETE
},
879 { "use-id-pool", &cfg_type_boolean
, CFG_CLAUSEFLAG_OBSOLETE
},
880 { "use-ixfr", &cfg_type_boolean
, 0 },
881 { "version", &cfg_type_qstringornone
, 0 },
882 { "flush-zones-on-shutdown", &cfg_type_boolean
, 0 },
887 static cfg_type_t cfg_type_namelist
= {
888 "namelist", cfg_parse_bracketed_list
, cfg_print_bracketed_list
,
889 cfg_doc_bracketed_list
, &cfg_rep_list
, &cfg_type_qstring
};
891 static keyword_type_t exclude_kw
= { "exclude", &cfg_type_namelist
};
893 static cfg_type_t cfg_type_optional_exclude
= {
894 "optional_exclude", parse_optional_keyvalue
, print_keyvalue
,
895 doc_optional_keyvalue
, &cfg_rep_list
, &exclude_kw
};
897 static keyword_type_t exceptionnames_kw
= { "except-from", &cfg_type_namelist
};
899 static cfg_type_t cfg_type_optional_exceptionnames
= {
900 "optional_allow", parse_optional_keyvalue
, print_keyvalue
,
901 doc_optional_keyvalue
, &cfg_rep_list
, &exceptionnames_kw
};
903 static cfg_tuplefielddef_t denyaddresses_fields
[] = {
904 { "acl", &cfg_type_bracketed_aml
, 0 },
905 { "except-from", &cfg_type_optional_exceptionnames
, 0 },
909 static cfg_type_t cfg_type_denyaddresses
= {
910 "denyaddresses", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
911 &cfg_rep_tuple
, denyaddresses_fields
914 static cfg_tuplefielddef_t denyaliases_fields
[] = {
915 { "name", &cfg_type_namelist
, 0 },
916 { "except-from", &cfg_type_optional_exceptionnames
, 0 },
920 static cfg_type_t cfg_type_denyaliases
= {
921 "denyaliases", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
922 &cfg_rep_tuple
, denyaliases_fields
925 static cfg_type_t cfg_type_algorithmlist
= {
926 "algorithmlist", cfg_parse_bracketed_list
, cfg_print_bracketed_list
,
927 cfg_doc_bracketed_list
, &cfg_rep_list
, &cfg_type_astring
};
929 static cfg_tuplefielddef_t disablealgorithm_fields
[] = {
930 { "name", &cfg_type_astring
, 0 },
931 { "algorithms", &cfg_type_algorithmlist
, 0 },
935 static cfg_type_t cfg_type_disablealgorithm
= {
936 "disablealgorithm", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
937 &cfg_rep_tuple
, disablealgorithm_fields
940 static cfg_tuplefielddef_t mustbesecure_fields
[] = {
941 { "name", &cfg_type_astring
, 0 },
942 { "value", &cfg_type_boolean
, 0 },
946 static cfg_type_t cfg_type_mustbesecure
= {
947 "mustbesecure", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
948 &cfg_rep_tuple
, mustbesecure_fields
951 static const char *masterformat_enums
[] = { "text", "raw", NULL
};
952 static cfg_type_t cfg_type_masterformat
= {
953 "masterformat", cfg_parse_enum
, cfg_print_ustring
, cfg_doc_enum
,
954 &cfg_rep_string
, &masterformat_enums
961 static keyword_type_t trustanchor_kw
= { "trust-anchor", &cfg_type_astring
};
963 static cfg_type_t cfg_type_optional_trustanchor
= {
964 "optional_trustanchor", parse_optional_keyvalue
, print_keyvalue
,
965 doc_keyvalue
, &cfg_rep_string
, &trustanchor_kw
968 static cfg_tuplefielddef_t lookaside_fields
[] = {
969 { "domain", &cfg_type_astring
, 0 },
970 { "trust-anchor", &cfg_type_optional_trustanchor
, 0 },
974 static cfg_type_t cfg_type_lookaside
= {
975 "lookaside", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
976 &cfg_rep_tuple
, lookaside_fields
980 * Clauses that can be found within the 'view' statement,
981 * with defaults in the 'options' statement.
984 static cfg_clausedef_t
986 { "acache-cleaning-interval", &cfg_type_uint32
, 0 },
987 { "acache-enable", &cfg_type_boolean
, 0 },
988 { "additional-from-auth", &cfg_type_boolean
, 0 },
989 { "additional-from-cache", &cfg_type_boolean
, 0 },
990 { "allow-query-cache", &cfg_type_bracketed_aml
, 0 },
991 { "allow-query-cache-on", &cfg_type_bracketed_aml
, 0 },
992 { "allow-recursion", &cfg_type_bracketed_aml
, 0 },
993 { "allow-recursion-on", &cfg_type_bracketed_aml
, 0 },
994 { "allow-v6-synthesis", &cfg_type_bracketed_aml
,
995 CFG_CLAUSEFLAG_OBSOLETE
},
996 { "attach-cache", &cfg_type_astring
, 0 },
997 { "auth-nxdomain", &cfg_type_boolean
, CFG_CLAUSEFLAG_NEWDEFAULT
},
998 { "cache-file", &cfg_type_qstring
, 0 },
999 { "check-names", &cfg_type_checknames
, CFG_CLAUSEFLAG_MULTI
},
1000 { "cleaning-interval", &cfg_type_uint32
, 0 },
1001 { "clients-per-query", &cfg_type_uint32
, 0 },
1002 { "deny-answer-addresses", &cfg_type_denyaddresses
, 0 },
1003 { "deny-answer-aliases", &cfg_type_denyaliases
, 0 },
1004 { "disable-algorithms", &cfg_type_disablealgorithm
,
1005 CFG_CLAUSEFLAG_MULTI
},
1006 { "disable-empty-zone", &cfg_type_astring
, CFG_CLAUSEFLAG_MULTI
},
1007 { "dnssec-accept-expired", &cfg_type_boolean
, 0 },
1008 { "dnssec-enable", &cfg_type_boolean
, 0 },
1009 { "dnssec-lookaside", &cfg_type_lookaside
, CFG_CLAUSEFLAG_MULTI
},
1010 { "dnssec-must-be-secure", &cfg_type_mustbesecure
,
1011 CFG_CLAUSEFLAG_MULTI
},
1012 { "dnssec-validation", &cfg_type_boolean
, 0 },
1013 { "dual-stack-servers", &cfg_type_nameportiplist
, 0 },
1014 { "edns-udp-size", &cfg_type_uint32
, 0 },
1015 { "empty-contact", &cfg_type_astring
, 0 },
1016 { "empty-server", &cfg_type_astring
, 0 },
1017 { "empty-zones-enable", &cfg_type_boolean
, 0 },
1018 { "fetch-glue", &cfg_type_boolean
, CFG_CLAUSEFLAG_OBSOLETE
},
1019 { "ixfr-from-differences", &cfg_type_ixfrdifftype
, 0 },
1020 { "lame-ttl", &cfg_type_uint32
, 0 },
1021 { "max-acache-size", &cfg_type_sizenodefault
, 0 },
1022 { "max-cache-size", &cfg_type_sizenodefault
, 0 },
1023 { "max-cache-ttl", &cfg_type_uint32
, 0 },
1024 { "max-clients-per-query", &cfg_type_uint32
, 0 },
1025 { "max-ncache-ttl", &cfg_type_uint32
, 0 },
1026 { "max-udp-size", &cfg_type_uint32
, 0 },
1027 { "min-roots", &cfg_type_uint32
, CFG_CLAUSEFLAG_NOTIMP
},
1028 { "minimal-responses", &cfg_type_boolean
, 0 },
1029 { "preferred-glue", &cfg_type_astring
, 0 },
1030 { "provide-ixfr", &cfg_type_boolean
, 0 },
1032 * Note that the query-source option syntax is different
1033 * from the other -source options.
1035 { "query-source", &cfg_type_querysource4
, 0 },
1036 { "query-source-v6", &cfg_type_querysource6
, 0 },
1037 { "queryport-pool-ports", &cfg_type_uint32
, CFG_CLAUSEFLAG_OBSOLETE
},
1038 { "queryport-pool-updateinterval", &cfg_type_uint32
,
1039 CFG_CLAUSEFLAG_OBSOLETE
},
1040 { "recursion", &cfg_type_boolean
, 0 },
1041 { "request-ixfr", &cfg_type_boolean
, 0 },
1042 { "request-nsid", &cfg_type_boolean
, 0 },
1043 { "rfc2308-type1", &cfg_type_boolean
, CFG_CLAUSEFLAG_NYI
},
1044 { "root-delegation-only", &cfg_type_optional_exclude
, 0 },
1045 { "rrset-order", &cfg_type_rrsetorder
, 0 },
1046 { "sortlist", &cfg_type_bracketed_aml
, 0 },
1047 { "suppress-initial-notify", &cfg_type_boolean
, CFG_CLAUSEFLAG_NYI
},
1048 { "topology", &cfg_type_bracketed_aml
, CFG_CLAUSEFLAG_NOTIMP
},
1049 { "transfer-format", &cfg_type_transferformat
, 0 },
1050 { "use-queryport-pool", &cfg_type_boolean
, CFG_CLAUSEFLAG_OBSOLETE
},
1051 { "zero-no-soa-ttl-cache", &cfg_type_boolean
, 0 },
1052 #ifdef ALLOW_FILTER_AAAA_ON_V4
1053 { "filter-aaaa-on-v4", &cfg_type_v4_aaaa
, 0 },
1059 * Clauses that can be found within the 'view' statement only.
1061 static cfg_clausedef_t
1062 view_only_clauses
[] = {
1063 { "match-clients", &cfg_type_bracketed_aml
, 0 },
1064 { "match-destinations", &cfg_type_bracketed_aml
, 0 },
1065 { "match-recursive-only", &cfg_type_boolean
, 0 },
1070 * Sig-validity-interval.
1073 parse_optional_uint32(cfg_parser_t
*pctx
, const cfg_type_t
*type
,
1076 isc_result_t result
;
1079 CHECK(cfg_peektoken(pctx
, ISC_LEXOPT_NUMBER
| ISC_LEXOPT_CNUMBER
));
1080 if (pctx
->token
.type
== isc_tokentype_number
) {
1081 CHECK(cfg_parse_obj(pctx
, &cfg_type_uint32
, ret
));
1083 CHECK(cfg_parse_obj(pctx
, &cfg_type_void
, ret
));
1090 doc_optional_uint32(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
1092 cfg_print_chars(pctx
, "[ <integer> ]", 13);
1095 static cfg_type_t cfg_type_optional_uint32
= {
1096 "optional_uint32", parse_optional_uint32
, NULL
, doc_optional_uint32
,
1099 static cfg_tuplefielddef_t validityinterval_fields
[] = {
1100 { "validity", &cfg_type_uint32
, 0 },
1101 { "re-sign", &cfg_type_optional_uint32
, 0 },
1105 static cfg_type_t cfg_type_validityinterval
= {
1106 "validityinterval", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
1107 &cfg_rep_tuple
, validityinterval_fields
1111 * Clauses that can be found in a 'zone' statement,
1112 * with defaults in the 'view' or 'options' statement.
1114 static cfg_clausedef_t
1116 { "allow-notify", &cfg_type_bracketed_aml
, 0 },
1117 { "allow-query", &cfg_type_bracketed_aml
, 0 },
1118 { "allow-query-on", &cfg_type_bracketed_aml
, 0 },
1119 { "allow-transfer", &cfg_type_bracketed_aml
, 0 },
1120 { "allow-update", &cfg_type_bracketed_aml
, 0 },
1121 { "allow-update-forwarding", &cfg_type_bracketed_aml
, 0 },
1122 { "also-notify", &cfg_type_portiplist
, 0 },
1123 { "alt-transfer-source", &cfg_type_sockaddr4wild
, 0 },
1124 { "alt-transfer-source-v6", &cfg_type_sockaddr6wild
, 0 },
1125 { "check-dup-records", &cfg_type_checkmode
, 0 },
1126 { "check-integrity", &cfg_type_boolean
, 0 },
1127 { "check-mx", &cfg_type_checkmode
, 0 },
1128 { "check-mx-cname", &cfg_type_checkmode
, 0 },
1129 { "check-sibling", &cfg_type_boolean
, 0 },
1130 { "check-srv-cname", &cfg_type_checkmode
, 0 },
1131 { "check-wildcard", &cfg_type_boolean
, 0 },
1132 { "dialup", &cfg_type_dialuptype
, 0 },
1133 { "dnssec-dnskey-kskonly", &cfg_type_boolean
, 0 },
1134 { "dnssec-secure-to-insecure", &cfg_type_boolean
, 0 },
1135 { "forward", &cfg_type_forwardtype
, 0 },
1136 { "forwarders", &cfg_type_portiplist
, 0 },
1137 { "key-directory", &cfg_type_qstring
, 0 },
1138 { "maintain-ixfr-base", &cfg_type_boolean
, CFG_CLAUSEFLAG_OBSOLETE
},
1139 { "masterfile-format", &cfg_type_masterformat
, 0 },
1140 { "max-ixfr-log-size", &cfg_type_size
, CFG_CLAUSEFLAG_OBSOLETE
},
1141 { "max-journal-size", &cfg_type_sizenodefault
, 0 },
1142 { "max-refresh-time", &cfg_type_uint32
, 0 },
1143 { "max-retry-time", &cfg_type_uint32
, 0 },
1144 { "max-transfer-idle-in", &cfg_type_uint32
, 0 },
1145 { "max-transfer-idle-out", &cfg_type_uint32
, 0 },
1146 { "max-transfer-time-in", &cfg_type_uint32
, 0 },
1147 { "max-transfer-time-out", &cfg_type_uint32
, 0 },
1148 { "min-refresh-time", &cfg_type_uint32
, 0 },
1149 { "min-retry-time", &cfg_type_uint32
, 0 },
1150 { "multi-master", &cfg_type_boolean
, 0 },
1151 { "notify", &cfg_type_notifytype
, 0 },
1152 { "notify-delay", &cfg_type_uint32
, 0 },
1153 { "notify-source", &cfg_type_sockaddr4wild
, 0 },
1154 { "notify-source-v6", &cfg_type_sockaddr6wild
, 0 },
1155 { "notify-to-soa", &cfg_type_boolean
, 0 },
1156 { "nsec3-test-zone", &cfg_type_boolean
, CFG_CLAUSEFLAG_TESTONLY
},
1157 { "sig-signing-nodes", &cfg_type_uint32
, 0 },
1158 { "sig-signing-signatures", &cfg_type_uint32
, 0 },
1159 { "sig-signing-type", &cfg_type_uint32
, 0 },
1160 { "sig-validity-interval", &cfg_type_validityinterval
, 0 },
1161 { "transfer-source", &cfg_type_sockaddr4wild
, 0 },
1162 { "transfer-source-v6", &cfg_type_sockaddr6wild
, 0 },
1163 { "try-tcp-refresh", &cfg_type_boolean
, 0 },
1164 { "update-check-ksk", &cfg_type_boolean
, 0 },
1165 { "use-alt-transfer-source", &cfg_type_boolean
, 0 },
1166 { "zero-no-soa-ttl", &cfg_type_boolean
, 0 },
1167 { "zone-statistics", &cfg_type_boolean
, 0 },
1172 * Clauses that can be found in a 'zone' statement
1175 static cfg_clausedef_t
1176 zone_only_clauses
[] = {
1177 { "type", &cfg_type_zonetype
, 0 },
1178 { "file", &cfg_type_qstring
, 0 },
1179 { "journal", &cfg_type_qstring
, 0 },
1180 { "ixfr-base", &cfg_type_qstring
, CFG_CLAUSEFLAG_OBSOLETE
},
1181 { "ixfr-tmp-file", &cfg_type_qstring
, CFG_CLAUSEFLAG_OBSOLETE
},
1182 { "masters", &cfg_type_namesockaddrkeylist
, 0 },
1183 { "pubkey", &cfg_type_pubkey
,
1184 CFG_CLAUSEFLAG_MULTI
| CFG_CLAUSEFLAG_OBSOLETE
},
1185 { "update-policy", &cfg_type_updatepolicy
, 0 },
1186 { "database", &cfg_type_astring
, 0 },
1187 { "delegation-only", &cfg_type_boolean
, 0 },
1189 * Note that the format of the check-names option is different between
1190 * the zone options and the global/view options. Ugh.
1192 { "check-names", &cfg_type_checkmode
, 0 },
1193 { "ixfr-from-differences", &cfg_type_boolean
, 0 },
1194 { "auto-dnssec", &cfg_type_autodnssec
, 0 },
1199 /*% The top-level named.conf syntax. */
1201 static cfg_clausedef_t
*
1202 namedconf_clausesets
[] = {
1204 namedconf_or_view_clauses
,
1207 LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_namedconf
= {
1208 "namedconf", cfg_parse_mapbody
, cfg_print_mapbody
, cfg_doc_mapbody
,
1209 &cfg_rep_map
, namedconf_clausesets
1212 /*% The bind.keys syntax (trusted-keys/managed-keys only). */
1213 static cfg_clausedef_t
*
1214 bindkeys_clausesets
[] = {
1218 LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_bindkeys
= {
1219 "bindkeys", cfg_parse_mapbody
, cfg_print_mapbody
, cfg_doc_mapbody
,
1220 &cfg_rep_map
, bindkeys_clausesets
1223 /*% The "options" statement syntax. */
1225 static cfg_clausedef_t
*
1226 options_clausesets
[] = {
1232 static cfg_type_t cfg_type_options
= {
1233 "options", cfg_parse_map
, cfg_print_map
, cfg_doc_map
, &cfg_rep_map
, options_clausesets
};
1235 /*% The "view" statement syntax. */
1237 static cfg_clausedef_t
*
1238 view_clausesets
[] = {
1240 namedconf_or_view_clauses
,
1243 dynamically_loadable_zones_clauses
,
1246 static cfg_type_t cfg_type_viewopts
= {
1247 "view", cfg_parse_map
, cfg_print_map
, cfg_doc_map
, &cfg_rep_map
, view_clausesets
};
1249 /*% The "zone" statement syntax. */
1251 static cfg_clausedef_t
*
1252 zone_clausesets
[] = {
1257 static cfg_type_t cfg_type_zoneopts
= {
1258 "zoneopts", cfg_parse_map
, cfg_print_map
,
1259 cfg_doc_map
, &cfg_rep_map
, zone_clausesets
};
1261 /*% The "dynamically loadable zones" statement syntax. */
1263 static cfg_clausedef_t
*
1264 dynamically_loadable_zones_clausesets
[] = {
1265 dynamically_loadable_zones_clauses
,
1268 static cfg_type_t cfg_type_dynamically_loadable_zones_opts
= {
1269 "dynamically_loadable_zones_opts", cfg_parse_map
,
1270 cfg_print_map
, cfg_doc_map
, &cfg_rep_map
,
1271 dynamically_loadable_zones_clausesets
1275 * Clauses that can be found within the 'key' statement.
1277 static cfg_clausedef_t
1279 { "algorithm", &cfg_type_astring
, 0 },
1280 { "secret", &cfg_type_astring
, 0 },
1284 static cfg_clausedef_t
*
1285 key_clausesets
[] = {
1289 static cfg_type_t cfg_type_key
= {
1290 "key", cfg_parse_named_map
, cfg_print_map
,
1291 cfg_doc_map
, &cfg_rep_map
, key_clausesets
1296 * Clauses that can be found in a 'server' statement.
1298 static cfg_clausedef_t
1299 server_clauses
[] = {
1300 { "bogus", &cfg_type_boolean
, 0 },
1301 { "provide-ixfr", &cfg_type_boolean
, 0 },
1302 { "request-ixfr", &cfg_type_boolean
, 0 },
1303 { "support-ixfr", &cfg_type_boolean
, CFG_CLAUSEFLAG_OBSOLETE
},
1304 { "transfers", &cfg_type_uint32
, 0 },
1305 { "transfer-format", &cfg_type_transferformat
, 0 },
1306 { "keys", &cfg_type_server_key_kludge
, 0 },
1307 { "edns", &cfg_type_boolean
, 0 },
1308 { "edns-udp-size", &cfg_type_uint32
, 0 },
1309 { "max-udp-size", &cfg_type_uint32
, 0 },
1310 { "notify-source", &cfg_type_sockaddr4wild
, 0 },
1311 { "notify-source-v6", &cfg_type_sockaddr6wild
, 0 },
1312 { "query-source", &cfg_type_querysource4
, 0 },
1313 { "query-source-v6", &cfg_type_querysource6
, 0 },
1314 { "transfer-source", &cfg_type_sockaddr4wild
, 0 },
1315 { "transfer-source-v6", &cfg_type_sockaddr6wild
, 0 },
1318 static cfg_clausedef_t
*
1319 server_clausesets
[] = {
1323 static cfg_type_t cfg_type_server
= {
1324 "server", cfg_parse_netprefix_map
, cfg_print_map
, cfg_doc_map
, &cfg_rep_map
,
1330 * Clauses that can be found in a 'channel' clause in the
1331 * 'logging' statement.
1333 * These have some additional constraints that need to be
1334 * checked after parsing:
1335 * - There must exactly one of file/syslog/null/stderr
1338 static cfg_clausedef_t
1339 channel_clauses
[] = {
1340 /* Destinations. We no longer require these to be first. */
1341 { "file", &cfg_type_logfile
, 0 },
1342 { "syslog", &cfg_type_optional_facility
, 0 },
1343 { "null", &cfg_type_void
, 0 },
1344 { "stderr", &cfg_type_void
, 0 },
1345 /* Options. We now accept these for the null channel, too. */
1346 { "severity", &cfg_type_logseverity
, 0 },
1347 { "print-time", &cfg_type_boolean
, 0 },
1348 { "print-severity", &cfg_type_boolean
, 0 },
1349 { "print-category", &cfg_type_boolean
, 0 },
1352 static cfg_clausedef_t
*
1353 channel_clausesets
[] = {
1357 static cfg_type_t cfg_type_channel
= {
1358 "channel", cfg_parse_named_map
, cfg_print_map
, cfg_doc_map
,
1359 &cfg_rep_map
, channel_clausesets
1362 /*% A list of log destination, used in the "category" clause. */
1363 static cfg_type_t cfg_type_destinationlist
= {
1364 "destinationlist", cfg_parse_bracketed_list
, cfg_print_bracketed_list
, cfg_doc_bracketed_list
,
1365 &cfg_rep_list
, &cfg_type_astring
};
1368 * Clauses that can be found in a 'logging' statement.
1370 static cfg_clausedef_t
1371 logging_clauses
[] = {
1372 { "channel", &cfg_type_channel
, CFG_CLAUSEFLAG_MULTI
},
1373 { "category", &cfg_type_category
, CFG_CLAUSEFLAG_MULTI
},
1376 static cfg_clausedef_t
*
1377 logging_clausesets
[] = {
1381 static cfg_type_t cfg_type_logging
= {
1382 "logging", cfg_parse_map
, cfg_print_map
, cfg_doc_map
, &cfg_rep_map
, logging_clausesets
};
1386 parse_unitstring(char *str
, isc_resourcevalue_t
*valuep
) {
1392 value
= isc_string_touint64(str
, &endp
, 10);
1395 return (ISC_R_SUCCESS
);
1399 if (len
< 2 || endp
[1] != '\0')
1400 return (ISC_R_FAILURE
);
1402 switch (str
[len
- 1]) {
1413 unit
= 1024 * 1024 * 1024;
1416 return (ISC_R_FAILURE
);
1418 if (value
> ISC_UINT64_MAX
/ unit
)
1419 return (ISC_R_FAILURE
);
1420 *valuep
= value
* unit
;
1421 return (ISC_R_SUCCESS
);
1425 parse_sizeval(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
1426 isc_result_t result
;
1427 cfg_obj_t
*obj
= NULL
;
1432 CHECK(cfg_gettoken(pctx
, 0));
1433 if (pctx
->token
.type
!= isc_tokentype_string
) {
1434 result
= ISC_R_UNEXPECTEDTOKEN
;
1437 CHECK(parse_unitstring(TOKEN_STRING(pctx
), &val
));
1439 CHECK(cfg_create_obj(pctx
, &cfg_type_uint64
, &obj
));
1440 obj
->value
.uint64
= val
;
1442 return (ISC_R_SUCCESS
);
1445 cfg_parser_error(pctx
, CFG_LOG_NEAR
, "expected integer and optional unit");
1450 * A size value (number + optional unit).
1452 static cfg_type_t cfg_type_sizeval
= {
1453 "sizeval", parse_sizeval
, cfg_print_uint64
, cfg_doc_terminal
,
1454 &cfg_rep_uint64
, NULL
};
1457 * A size, "unlimited", or "default".
1461 parse_size(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
1462 return (parse_enum_or_other(pctx
, type
, &cfg_type_sizeval
, ret
));
1465 static const char *size_enums
[] = { "unlimited", "default", NULL
};
1466 static cfg_type_t cfg_type_size
= {
1467 "size", parse_size
, cfg_print_ustring
, cfg_doc_terminal
,
1468 &cfg_rep_string
, size_enums
1472 * A size or "unlimited", but not "default".
1474 static const char *sizenodefault_enums
[] = { "unlimited", NULL
};
1475 static cfg_type_t cfg_type_sizenodefault
= {
1476 "size_no_default", parse_size
, cfg_print_ustring
, cfg_doc_terminal
,
1477 &cfg_rep_string
, sizenodefault_enums
1484 parse_maybe_optional_keyvalue(cfg_parser_t
*pctx
, const cfg_type_t
*type
,
1485 isc_boolean_t optional
, cfg_obj_t
**ret
)
1487 isc_result_t result
;
1488 cfg_obj_t
*obj
= NULL
;
1489 const keyword_type_t
*kw
= type
->of
;
1491 CHECK(cfg_peektoken(pctx
, 0));
1492 if (pctx
->token
.type
== isc_tokentype_string
&&
1493 strcasecmp(TOKEN_STRING(pctx
), kw
->name
) == 0) {
1494 CHECK(cfg_gettoken(pctx
, 0));
1495 CHECK(kw
->type
->parse(pctx
, kw
->type
, &obj
));
1496 obj
->type
= type
; /* XXX kludge */
1499 CHECK(cfg_parse_void(pctx
, NULL
, &obj
));
1501 cfg_parser_error(pctx
, CFG_LOG_NEAR
, "expected '%s'",
1503 result
= ISC_R_UNEXPECTEDTOKEN
;
1513 parse_enum_or_other(cfg_parser_t
*pctx
, const cfg_type_t
*enumtype
,
1514 const cfg_type_t
*othertype
, cfg_obj_t
**ret
)
1516 isc_result_t result
;
1517 CHECK(cfg_peektoken(pctx
, 0));
1518 if (pctx
->token
.type
== isc_tokentype_string
&&
1519 cfg_is_enum(TOKEN_STRING(pctx
), enumtype
->of
)) {
1520 CHECK(cfg_parse_enum(pctx
, enumtype
, ret
));
1522 CHECK(cfg_parse_obj(pctx
, othertype
, ret
));
1529 doc_enum_or_other(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
1530 cfg_doc_terminal(pctx
, type
);
1532 cfg_print_chars(pctx
, "( ", 2);...
1538 parse_keyvalue(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
1539 return (parse_maybe_optional_keyvalue(pctx
, type
, ISC_FALSE
, ret
));
1543 parse_optional_keyvalue(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
1544 return (parse_maybe_optional_keyvalue(pctx
, type
, ISC_TRUE
, ret
));
1548 print_keyvalue(cfg_printer_t
*pctx
, const cfg_obj_t
*obj
) {
1549 const keyword_type_t
*kw
= obj
->type
->of
;
1550 cfg_print_cstr(pctx
, kw
->name
);
1551 cfg_print_chars(pctx
, " ", 1);
1552 kw
->type
->print(pctx
, obj
);
1556 doc_keyvalue(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
1557 const keyword_type_t
*kw
= type
->of
;
1558 cfg_print_cstr(pctx
, kw
->name
);
1559 cfg_print_chars(pctx
, " ", 1);
1560 cfg_doc_obj(pctx
, kw
->type
);
1564 doc_optional_keyvalue(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
1565 const keyword_type_t
*kw
= type
->of
;
1566 cfg_print_chars(pctx
, "[ ", 2);
1567 cfg_print_cstr(pctx
, kw
->name
);
1568 cfg_print_chars(pctx
, " ", 1);
1569 cfg_doc_obj(pctx
, kw
->type
);
1570 cfg_print_chars(pctx
, " ]", 2);
1573 static const char *dialup_enums
[] = {
1574 "notify", "notify-passive", "refresh", "passive", NULL
};
1576 parse_dialup_type(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
1577 return (parse_enum_or_other(pctx
, type
, &cfg_type_boolean
, ret
));
1579 static cfg_type_t cfg_type_dialuptype
= {
1580 "dialuptype", parse_dialup_type
, cfg_print_ustring
, doc_enum_or_other
,
1581 &cfg_rep_string
, dialup_enums
1584 static const char *notify_enums
[] = { "explicit", "master-only", NULL
};
1586 parse_notify_type(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
1587 return (parse_enum_or_other(pctx
, type
, &cfg_type_boolean
, ret
));
1589 static cfg_type_t cfg_type_notifytype
= {
1590 "notifytype", parse_notify_type
, cfg_print_ustring
, doc_enum_or_other
,
1591 &cfg_rep_string
, notify_enums
,
1594 static const char *ixfrdiff_enums
[] = { "master", "slave", NULL
};
1596 parse_ixfrdiff_type(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
1597 return (parse_enum_or_other(pctx
, type
, &cfg_type_boolean
, ret
));
1599 static cfg_type_t cfg_type_ixfrdifftype
= {
1600 "ixfrdiff", parse_ixfrdiff_type
, cfg_print_ustring
, doc_enum_or_other
,
1601 &cfg_rep_string
, ixfrdiff_enums
,
1604 #ifdef ALLOW_FILTER_AAAA_ON_V4
1605 static const char *v4_aaaa_enums
[] = { "break-dnssec", NULL
};
1607 parse_v4_aaaa(cfg_parser_t
*pctx
, const cfg_type_t
*type
,
1609 return (parse_enum_or_other(pctx
, type
, &cfg_type_boolean
, ret
));
1611 static cfg_type_t cfg_type_v4_aaaa
= {
1612 "v4_aaaa", parse_v4_aaaa
, cfg_print_ustring
,
1613 doc_enum_or_other
, &cfg_rep_string
, v4_aaaa_enums
,
1617 static keyword_type_t key_kw
= { "key", &cfg_type_astring
};
1619 LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_keyref
= {
1620 "keyref", parse_keyvalue
, print_keyvalue
, doc_keyvalue
,
1621 &cfg_rep_string
, &key_kw
1624 static cfg_type_t cfg_type_optional_keyref
= {
1625 "optional_keyref", parse_optional_keyvalue
, print_keyvalue
,
1626 doc_optional_keyvalue
, &cfg_rep_string
, &key_kw
1630 * A "controls" statement is represented as a map with the multivalued
1631 * "inet" and "unix" clauses.
1634 static keyword_type_t controls_allow_kw
= {
1635 "allow", &cfg_type_bracketed_aml
};
1637 static cfg_type_t cfg_type_controls_allow
= {
1638 "controls_allow", parse_keyvalue
,
1639 print_keyvalue
, doc_keyvalue
,
1640 &cfg_rep_list
, &controls_allow_kw
1643 static keyword_type_t controls_keys_kw
= {
1644 "keys", &cfg_type_keylist
};
1646 static cfg_type_t cfg_type_controls_keys
= {
1647 "controls_keys", parse_optional_keyvalue
,
1648 print_keyvalue
, doc_optional_keyvalue
,
1649 &cfg_rep_list
, &controls_keys_kw
1652 static cfg_tuplefielddef_t inetcontrol_fields
[] = {
1653 { "address", &cfg_type_controls_sockaddr
, 0 },
1654 { "allow", &cfg_type_controls_allow
, 0 },
1655 { "keys", &cfg_type_controls_keys
, 0 },
1659 static cfg_type_t cfg_type_inetcontrol
= {
1660 "inetcontrol", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
,
1664 static keyword_type_t controls_perm_kw
= {
1665 "perm", &cfg_type_uint32
};
1667 static cfg_type_t cfg_type_controls_perm
= {
1668 "controls_perm", parse_keyvalue
,
1669 print_keyvalue
, doc_keyvalue
,
1670 &cfg_rep_uint32
, &controls_perm_kw
1673 static keyword_type_t controls_owner_kw
= {
1674 "owner", &cfg_type_uint32
};
1676 static cfg_type_t cfg_type_controls_owner
= {
1677 "controls_owner", parse_keyvalue
,
1678 print_keyvalue
, doc_keyvalue
,
1679 &cfg_rep_uint32
, &controls_owner_kw
1682 static keyword_type_t controls_group_kw
= {
1683 "group", &cfg_type_uint32
};
1685 static cfg_type_t cfg_type_controls_group
= {
1686 "controls_allow", parse_keyvalue
,
1687 print_keyvalue
, doc_keyvalue
,
1688 &cfg_rep_uint32
, &controls_group_kw
1691 static cfg_tuplefielddef_t unixcontrol_fields
[] = {
1692 { "path", &cfg_type_qstring
, 0 },
1693 { "perm", &cfg_type_controls_perm
, 0 },
1694 { "owner", &cfg_type_controls_owner
, 0 },
1695 { "group", &cfg_type_controls_group
, 0 },
1696 { "keys", &cfg_type_controls_keys
, 0 },
1700 static cfg_type_t cfg_type_unixcontrol
= {
1701 "unixcontrol", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
,
1705 static cfg_clausedef_t
1706 controls_clauses
[] = {
1707 { "inet", &cfg_type_inetcontrol
, CFG_CLAUSEFLAG_MULTI
},
1708 { "unix", &cfg_type_unixcontrol
, CFG_CLAUSEFLAG_MULTI
},
1712 static cfg_clausedef_t
*
1713 controls_clausesets
[] = {
1717 static cfg_type_t cfg_type_controls
= {
1718 "controls", cfg_parse_map
, cfg_print_map
, cfg_doc_map
, &cfg_rep_map
, &controls_clausesets
1722 * A "statistics-channels" statement is represented as a map with the
1723 * multivalued "inet" clauses.
1726 doc_optional_bracketed_list(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
1727 const keyword_type_t
*kw
= type
->of
;
1728 cfg_print_chars(pctx
, "[ ", 2);
1729 cfg_print_cstr(pctx
, kw
->name
);
1730 cfg_print_chars(pctx
, " ", 1);
1731 cfg_doc_obj(pctx
, kw
->type
);
1732 cfg_print_chars(pctx
, " ]", 2);
1735 static cfg_type_t cfg_type_optional_allow
= {
1736 "optional_allow", parse_optional_keyvalue
, print_keyvalue
,
1737 doc_optional_bracketed_list
, &cfg_rep_list
, &controls_allow_kw
1740 static cfg_tuplefielddef_t statserver_fields
[] = {
1741 { "address", &cfg_type_controls_sockaddr
, 0 }, /* reuse controls def */
1742 { "allow", &cfg_type_optional_allow
, 0 },
1746 static cfg_type_t cfg_type_statschannel
= {
1747 "statschannel", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
1748 &cfg_rep_tuple
, statserver_fields
1751 static cfg_clausedef_t
1752 statservers_clauses
[] = {
1753 { "inet", &cfg_type_statschannel
, CFG_CLAUSEFLAG_MULTI
},
1757 static cfg_clausedef_t
*
1758 statservers_clausesets
[] = {
1759 statservers_clauses
,
1763 static cfg_type_t cfg_type_statschannels
= {
1764 "statistics-channels", cfg_parse_map
, cfg_print_map
, cfg_doc_map
,
1765 &cfg_rep_map
, &statservers_clausesets
1769 * An optional class, as used in view and zone statements.
1772 parse_optional_class(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
1773 isc_result_t result
;
1775 CHECK(cfg_peektoken(pctx
, 0));
1776 if (pctx
->token
.type
== isc_tokentype_string
)
1777 CHECK(cfg_parse_obj(pctx
, &cfg_type_ustring
, ret
));
1779 CHECK(cfg_parse_obj(pctx
, &cfg_type_void
, ret
));
1784 static cfg_type_t cfg_type_optional_class
= {
1785 "optional_class", parse_optional_class
, NULL
, cfg_doc_terminal
,
1790 parse_querysource(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
1791 isc_result_t result
;
1792 cfg_obj_t
*obj
= NULL
;
1793 isc_netaddr_t netaddr
;
1795 unsigned int have_address
= 0;
1796 unsigned int have_port
= 0;
1797 const unsigned int *flagp
= type
->of
;
1799 if ((*flagp
& CFG_ADDR_V4OK
) != 0)
1800 isc_netaddr_any(&netaddr
);
1801 else if ((*flagp
& CFG_ADDR_V6OK
) != 0)
1802 isc_netaddr_any6(&netaddr
);
1809 CHECK(cfg_peektoken(pctx
, 0));
1810 if (pctx
->token
.type
== isc_tokentype_string
) {
1811 if (strcasecmp(TOKEN_STRING(pctx
),
1814 /* read "address" */
1815 CHECK(cfg_gettoken(pctx
, 0));
1816 CHECK(cfg_parse_rawaddr(pctx
, *flagp
,
1819 } else if (strcasecmp(TOKEN_STRING(pctx
), "port") == 0)
1822 CHECK(cfg_gettoken(pctx
, 0));
1823 CHECK(cfg_parse_rawport(pctx
,
1827 } else if (have_port
== 0 && have_address
== 0) {
1828 return (cfg_parse_sockaddr(pctx
, type
, ret
));
1830 cfg_parser_error(pctx
, CFG_LOG_NEAR
,
1831 "expected 'address' or 'port'");
1832 return (ISC_R_UNEXPECTEDTOKEN
);
1837 if (have_address
> 1 || have_port
> 1 ||
1838 have_address
+ have_port
== 0) {
1839 cfg_parser_error(pctx
, 0, "expected one address and/or port");
1840 return (ISC_R_UNEXPECTEDTOKEN
);
1843 CHECK(cfg_create_obj(pctx
, &cfg_type_querysource
, &obj
));
1844 isc_sockaddr_fromnetaddr(&obj
->value
.sockaddr
, &netaddr
, port
);
1846 return (ISC_R_SUCCESS
);
1849 cfg_parser_error(pctx
, CFG_LOG_NEAR
, "invalid query source");
1855 print_querysource(cfg_printer_t
*pctx
, const cfg_obj_t
*obj
) {
1857 isc_netaddr_fromsockaddr(&na
, &obj
->value
.sockaddr
);
1858 cfg_print_chars(pctx
, "address ", 8);
1859 cfg_print_rawaddr(pctx
, &na
);
1860 cfg_print_chars(pctx
, " port ", 6);
1861 cfg_print_rawuint(pctx
, isc_sockaddr_getport(&obj
->value
.sockaddr
));
1864 static unsigned int sockaddr4wild_flags
= CFG_ADDR_WILDOK
| CFG_ADDR_V4OK
;
1865 static unsigned int sockaddr6wild_flags
= CFG_ADDR_WILDOK
| CFG_ADDR_V6OK
;
1867 static cfg_type_t cfg_type_querysource4
= {
1868 "querysource4", parse_querysource
, NULL
, cfg_doc_terminal
,
1869 NULL
, &sockaddr4wild_flags
1872 static cfg_type_t cfg_type_querysource6
= {
1873 "querysource6", parse_querysource
, NULL
, cfg_doc_terminal
,
1874 NULL
, &sockaddr6wild_flags
1877 static cfg_type_t cfg_type_querysource
= {
1878 "querysource", NULL
, print_querysource
, NULL
, &cfg_rep_sockaddr
, NULL
1884 parse_addrmatchelt(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
1885 isc_result_t result
;
1888 CHECK(cfg_peektoken(pctx
, CFG_LEXOPT_QSTRING
));
1890 if (pctx
->token
.type
== isc_tokentype_string
||
1891 pctx
->token
.type
== isc_tokentype_qstring
) {
1892 if (pctx
->token
.type
== isc_tokentype_string
&&
1893 (strcasecmp(TOKEN_STRING(pctx
), "key") == 0)) {
1894 CHECK(cfg_parse_obj(pctx
, &cfg_type_keyref
, ret
));
1896 if (cfg_lookingat_netaddr(pctx
, CFG_ADDR_V4OK
|
1897 CFG_ADDR_V4PREFIXOK
|
1900 CHECK(cfg_parse_netprefix(pctx
, NULL
, ret
));
1902 CHECK(cfg_parse_astring(pctx
, NULL
, ret
));
1905 } else if (pctx
->token
.type
== isc_tokentype_special
) {
1906 if (pctx
->token
.value
.as_char
== '{') {
1907 /* Nested match list. */
1908 CHECK(cfg_parse_obj(pctx
, &cfg_type_bracketed_aml
, ret
));
1909 } else if (pctx
->token
.value
.as_char
== '!') {
1910 CHECK(cfg_gettoken(pctx
, 0)); /* read "!" */
1911 CHECK(cfg_parse_obj(pctx
, &cfg_type_negated
, ret
));
1917 cfg_parser_error(pctx
, CFG_LOG_NEAR
,
1918 "expected IP match list element");
1919 return (ISC_R_UNEXPECTEDTOKEN
);
1926 * A negated address match list element (like "! 10.0.0.1").
1927 * Somewhat sneakily, the caller is expected to parse the
1928 * "!", but not to print it.
1931 static cfg_tuplefielddef_t negated_fields
[] = {
1932 { "value", &cfg_type_addrmatchelt
, 0 },
1937 print_negated(cfg_printer_t
*pctx
, const cfg_obj_t
*obj
) {
1938 cfg_print_chars(pctx
, "!", 1);
1939 cfg_print_tuple(pctx
, obj
);
1942 static cfg_type_t cfg_type_negated
= {
1943 "negated", cfg_parse_tuple
, print_negated
, NULL
, &cfg_rep_tuple
,
1947 /*% An address match list element */
1949 static cfg_type_t cfg_type_addrmatchelt
= {
1950 "address_match_element", parse_addrmatchelt
, NULL
, cfg_doc_terminal
,
1954 /*% A bracketed address match list */
1956 static cfg_type_t cfg_type_bracketed_aml
= {
1957 "bracketed_aml", cfg_parse_bracketed_list
, cfg_print_bracketed_list
,
1958 cfg_doc_bracketed_list
, &cfg_rep_list
, &cfg_type_addrmatchelt
1962 * The socket address syntax in the "controls" statement is silly.
1963 * It allows both socket address families, but also allows "*",
1964 * whis is gratuitously interpreted as the IPv4 wildcard address.
1966 static unsigned int controls_sockaddr_flags
=
1967 CFG_ADDR_V4OK
| CFG_ADDR_V6OK
| CFG_ADDR_WILDOK
;
1968 static cfg_type_t cfg_type_controls_sockaddr
= {
1969 "controls_sockaddr", cfg_parse_sockaddr
, cfg_print_sockaddr
,
1970 cfg_doc_sockaddr
, &cfg_rep_sockaddr
, &controls_sockaddr_flags
1974 * Handle the special kludge syntax of the "keys" clause in the "server"
1975 * statement, which takes a single key with or without braces and semicolon.
1978 parse_server_key_kludge(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
)
1980 isc_result_t result
;
1981 isc_boolean_t braces
= ISC_FALSE
;
1984 /* Allow opening brace. */
1985 CHECK(cfg_peektoken(pctx
, 0));
1986 if (pctx
->token
.type
== isc_tokentype_special
&&
1987 pctx
->token
.value
.as_char
== '{') {
1988 result
= cfg_gettoken(pctx
, 0);
1992 CHECK(cfg_parse_obj(pctx
, &cfg_type_astring
, ret
));
1995 /* Skip semicolon if present. */
1996 CHECK(cfg_peektoken(pctx
, 0));
1997 if (pctx
->token
.type
== isc_tokentype_special
&&
1998 pctx
->token
.value
.as_char
== ';')
1999 CHECK(cfg_gettoken(pctx
, 0));
2001 CHECK(cfg_parse_special(pctx
, '}'));
2006 static cfg_type_t cfg_type_server_key_kludge
= {
2007 "server_key", parse_server_key_kludge
, NULL
, cfg_doc_terminal
,
2013 * An optional logging facility.
2017 parse_optional_facility(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
)
2019 isc_result_t result
;
2022 CHECK(cfg_peektoken(pctx
, CFG_LEXOPT_QSTRING
));
2023 if (pctx
->token
.type
== isc_tokentype_string
||
2024 pctx
->token
.type
== isc_tokentype_qstring
) {
2025 CHECK(cfg_parse_obj(pctx
, &cfg_type_astring
, ret
));
2027 CHECK(cfg_parse_obj(pctx
, &cfg_type_void
, ret
));
2033 static cfg_type_t cfg_type_optional_facility
= {
2034 "optional_facility", parse_optional_facility
, NULL
, cfg_doc_terminal
,
2039 * A log severity. Return as a string, except "debug N",
2040 * which is returned as a keyword object.
2043 static keyword_type_t debug_kw
= { "debug", &cfg_type_uint32
};
2044 static cfg_type_t cfg_type_debuglevel
= {
2045 "debuglevel", parse_keyvalue
,
2046 print_keyvalue
, doc_keyvalue
,
2047 &cfg_rep_uint32
, &debug_kw
2051 parse_logseverity(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
2052 isc_result_t result
;
2055 CHECK(cfg_peektoken(pctx
, 0));
2056 if (pctx
->token
.type
== isc_tokentype_string
&&
2057 strcasecmp(TOKEN_STRING(pctx
), "debug") == 0) {
2058 CHECK(cfg_gettoken(pctx
, 0)); /* read "debug" */
2059 CHECK(cfg_peektoken(pctx
, ISC_LEXOPT_NUMBER
));
2060 if (pctx
->token
.type
== isc_tokentype_number
) {
2061 CHECK(cfg_parse_uint32(pctx
, NULL
, ret
));
2064 * The debug level is optional and defaults to 1.
2065 * This makes little sense, but we support it for
2066 * compatibility with BIND 8.
2068 CHECK(cfg_create_obj(pctx
, &cfg_type_uint32
, ret
));
2069 (*ret
)->value
.uint32
= 1;
2071 (*ret
)->type
= &cfg_type_debuglevel
; /* XXX kludge */
2073 CHECK(cfg_parse_obj(pctx
, &cfg_type_loglevel
, ret
));
2079 static cfg_type_t cfg_type_logseverity
= {
2080 "log_severity", parse_logseverity
, NULL
, cfg_doc_terminal
,
2084 * The "file" clause of the "channel" statement.
2085 * This is yet another special case.
2088 static const char *logversions_enums
[] = { "unlimited", NULL
};
2090 parse_logversions(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
2091 return (parse_enum_or_other(pctx
, type
, &cfg_type_uint32
, ret
));
2094 static cfg_type_t cfg_type_logversions
= {
2095 "logversions", parse_logversions
, cfg_print_ustring
, cfg_doc_terminal
,
2096 &cfg_rep_string
, logversions_enums
2099 static cfg_tuplefielddef_t logfile_fields
[] = {
2100 { "file", &cfg_type_qstring
, 0 },
2101 { "versions", &cfg_type_logversions
, 0 },
2102 { "size", &cfg_type_size
, 0 },
2107 parse_logfile(cfg_parser_t
*pctx
, const cfg_type_t
*type
, cfg_obj_t
**ret
) {
2108 isc_result_t result
;
2109 cfg_obj_t
*obj
= NULL
;
2110 const cfg_tuplefielddef_t
*fields
= type
->of
;
2112 CHECK(cfg_create_tuple(pctx
, type
, &obj
));
2114 /* Parse the mandatory "file" field */
2115 CHECK(cfg_parse_obj(pctx
, fields
[0].type
, &obj
->value
.tuple
[0]));
2117 /* Parse "versions" and "size" fields in any order. */
2119 CHECK(cfg_peektoken(pctx
, 0));
2120 if (pctx
->token
.type
== isc_tokentype_string
) {
2121 CHECK(cfg_gettoken(pctx
, 0));
2122 if (strcasecmp(TOKEN_STRING(pctx
),
2124 obj
->value
.tuple
[1] == NULL
) {
2125 CHECK(cfg_parse_obj(pctx
, fields
[1].type
,
2126 &obj
->value
.tuple
[1]));
2127 } else if (strcasecmp(TOKEN_STRING(pctx
),
2129 obj
->value
.tuple
[2] == NULL
) {
2130 CHECK(cfg_parse_obj(pctx
, fields
[2].type
,
2131 &obj
->value
.tuple
[2]));
2140 /* Create void objects for missing optional values. */
2141 if (obj
->value
.tuple
[1] == NULL
)
2142 CHECK(cfg_parse_void(pctx
, NULL
, &obj
->value
.tuple
[1]));
2143 if (obj
->value
.tuple
[2] == NULL
)
2144 CHECK(cfg_parse_void(pctx
, NULL
, &obj
->value
.tuple
[2]));
2147 return (ISC_R_SUCCESS
);
2155 print_logfile(cfg_printer_t
*pctx
, const cfg_obj_t
*obj
) {
2156 cfg_print_obj(pctx
, obj
->value
.tuple
[0]); /* file */
2157 if (obj
->value
.tuple
[1]->type
->print
!= cfg_print_void
) {
2158 cfg_print_chars(pctx
, " versions ", 10);
2159 cfg_print_obj(pctx
, obj
->value
.tuple
[1]);
2161 if (obj
->value
.tuple
[2]->type
->print
!= cfg_print_void
) {
2162 cfg_print_chars(pctx
, " size ", 6);
2163 cfg_print_obj(pctx
, obj
->value
.tuple
[2]);
2169 doc_logfile(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
2171 cfg_print_cstr(pctx
, "<quoted_string>");
2172 cfg_print_chars(pctx
, " ", 1);
2173 cfg_print_cstr(pctx
, "[ versions ( \"unlimited\" | <integer> ) ]");
2174 cfg_print_chars(pctx
, " ", 1);
2175 cfg_print_cstr(pctx
, "[ size <size> ]");
2178 static cfg_type_t cfg_type_logfile
= {
2179 "log_file", parse_logfile
, print_logfile
, doc_logfile
,
2180 &cfg_rep_tuple
, logfile_fields
2183 /*% An IPv4 address with optional port, "*" accepted as wildcard. */
2184 static cfg_type_t cfg_type_sockaddr4wild
= {
2185 "sockaddr4wild", cfg_parse_sockaddr
, cfg_print_sockaddr
,
2186 cfg_doc_sockaddr
, &cfg_rep_sockaddr
, &sockaddr4wild_flags
2189 /*% An IPv6 address with optional port, "*" accepted as wildcard. */
2190 static cfg_type_t cfg_type_sockaddr6wild
= {
2191 "v6addrportwild", cfg_parse_sockaddr
, cfg_print_sockaddr
,
2192 cfg_doc_sockaddr
, &cfg_rep_sockaddr
, &sockaddr6wild_flags
2199 static cfg_tuplefielddef_t lwres_view_fields
[] = {
2200 { "name", &cfg_type_astring
, 0 },
2201 { "class", &cfg_type_optional_class
, 0 },
2204 static cfg_type_t cfg_type_lwres_view
= {
2205 "lwres_view", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
, &cfg_rep_tuple
,
2209 static cfg_type_t cfg_type_lwres_searchlist
= {
2210 "lwres_searchlist", cfg_parse_bracketed_list
, cfg_print_bracketed_list
,
2211 cfg_doc_bracketed_list
, &cfg_rep_list
, &cfg_type_astring
};
2213 static cfg_clausedef_t
2215 { "listen-on", &cfg_type_portiplist
, 0 },
2216 { "view", &cfg_type_lwres_view
, 0 },
2217 { "search", &cfg_type_lwres_searchlist
, 0 },
2218 { "ndots", &cfg_type_uint32
, 0 },
2222 static cfg_clausedef_t
*
2223 lwres_clausesets
[] = {
2227 static cfg_type_t cfg_type_lwres
= {
2228 "lwres", cfg_parse_map
, cfg_print_map
, cfg_doc_map
, &cfg_rep_map
,
2236 static cfg_clausedef_t
2237 rndcconf_options_clauses
[] = {
2238 { "default-key", &cfg_type_astring
, 0 },
2239 { "default-port", &cfg_type_uint32
, 0 },
2240 { "default-server", &cfg_type_astring
, 0 },
2241 { "default-source-address", &cfg_type_netaddr4wild
, 0 },
2242 { "default-source-address-v6", &cfg_type_netaddr6wild
, 0 },
2246 static cfg_clausedef_t
*
2247 rndcconf_options_clausesets
[] = {
2248 rndcconf_options_clauses
,
2252 static cfg_type_t cfg_type_rndcconf_options
= {
2253 "rndcconf_options", cfg_parse_map
, cfg_print_map
, cfg_doc_map
,
2254 &cfg_rep_map
, rndcconf_options_clausesets
2257 static cfg_clausedef_t
2258 rndcconf_server_clauses
[] = {
2259 { "key", &cfg_type_astring
, 0 },
2260 { "port", &cfg_type_uint32
, 0 },
2261 { "source-address", &cfg_type_netaddr4wild
, 0 },
2262 { "source-address-v6", &cfg_type_netaddr6wild
, 0 },
2263 { "addresses", &cfg_type_bracketed_sockaddrnameportlist
, 0 },
2267 static cfg_clausedef_t
*
2268 rndcconf_server_clausesets
[] = {
2269 rndcconf_server_clauses
,
2273 static cfg_type_t cfg_type_rndcconf_server
= {
2274 "rndcconf_server", cfg_parse_named_map
, cfg_print_map
, cfg_doc_map
,
2275 &cfg_rep_map
, rndcconf_server_clausesets
2278 static cfg_clausedef_t
2279 rndcconf_clauses
[] = {
2280 { "key", &cfg_type_key
, CFG_CLAUSEFLAG_MULTI
},
2281 { "server", &cfg_type_rndcconf_server
, CFG_CLAUSEFLAG_MULTI
},
2282 { "options", &cfg_type_rndcconf_options
, 0 },
2286 static cfg_clausedef_t
*
2287 rndcconf_clausesets
[] = {
2292 LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndcconf
= {
2293 "rndcconf", cfg_parse_mapbody
, cfg_print_mapbody
, cfg_doc_mapbody
,
2294 &cfg_rep_map
, rndcconf_clausesets
2297 static cfg_clausedef_t
2298 rndckey_clauses
[] = {
2299 { "key", &cfg_type_key
, 0 },
2303 static cfg_clausedef_t
*
2304 rndckey_clausesets
[] = {
2309 LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndckey
= {
2310 "rndckey", cfg_parse_mapbody
, cfg_print_mapbody
, cfg_doc_mapbody
,
2311 &cfg_rep_map
, rndckey_clausesets
2315 * session.key has exactly the same syntax as rndc.key, but it's defined
2316 * separately for clarity (and so we can extend it someday, if needed).
2318 LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_sessionkey
= {
2319 "sessionkey", cfg_parse_mapbody
, cfg_print_mapbody
, cfg_doc_mapbody
,
2320 &cfg_rep_map
, rndckey_clausesets
2323 static cfg_tuplefielddef_t nameport_fields
[] = {
2324 { "name", &cfg_type_astring
, 0 },
2325 { "port", &cfg_type_optional_port
, 0 },
2328 static cfg_type_t cfg_type_nameport
= {
2329 "nameport", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
2330 &cfg_rep_tuple
, nameport_fields
2334 doc_sockaddrnameport(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
2336 cfg_print_chars(pctx
, "( ", 2);
2337 cfg_print_cstr(pctx
, "<quoted_string>");
2338 cfg_print_chars(pctx
, " ", 1);
2339 cfg_print_cstr(pctx
, "[ port <integer> ]");
2340 cfg_print_chars(pctx
, " | ", 3);
2341 cfg_print_cstr(pctx
, "<ipv4_address>");
2342 cfg_print_chars(pctx
, " ", 1);
2343 cfg_print_cstr(pctx
, "[ port <integer> ]");
2344 cfg_print_chars(pctx
, " | ", 3);
2345 cfg_print_cstr(pctx
, "<ipv6_address>");
2346 cfg_print_chars(pctx
, " ", 1);
2347 cfg_print_cstr(pctx
, "[ port <integer> ]");
2348 cfg_print_chars(pctx
, " )", 2);
2352 parse_sockaddrnameport(cfg_parser_t
*pctx
, const cfg_type_t
*type
,
2355 isc_result_t result
;
2356 cfg_obj_t
*obj
= NULL
;
2359 CHECK(cfg_peektoken(pctx
, CFG_LEXOPT_QSTRING
));
2360 if (pctx
->token
.type
== isc_tokentype_string
||
2361 pctx
->token
.type
== isc_tokentype_qstring
) {
2362 if (cfg_lookingat_netaddr(pctx
, CFG_ADDR_V4OK
| CFG_ADDR_V6OK
))
2363 CHECK(cfg_parse_sockaddr(pctx
, &cfg_type_sockaddr
, ret
));
2365 const cfg_tuplefielddef_t
*fields
=
2366 cfg_type_nameport
.of
;
2367 CHECK(cfg_create_tuple(pctx
, &cfg_type_nameport
,
2369 CHECK(cfg_parse_obj(pctx
, fields
[0].type
,
2370 &obj
->value
.tuple
[0]));
2371 CHECK(cfg_parse_obj(pctx
, fields
[1].type
,
2372 &obj
->value
.tuple
[1]));
2377 cfg_parser_error(pctx
, CFG_LOG_NEAR
,
2378 "expected IP address or hostname");
2379 return (ISC_R_UNEXPECTEDTOKEN
);
2386 static cfg_type_t cfg_type_sockaddrnameport
= {
2387 "sockaddrnameport_element", parse_sockaddrnameport
, NULL
,
2388 doc_sockaddrnameport
, NULL
, NULL
2391 static cfg_type_t cfg_type_bracketed_sockaddrnameportlist
= {
2392 "bracketed_sockaddrnameportlist", cfg_parse_bracketed_list
,
2393 cfg_print_bracketed_list
, cfg_doc_bracketed_list
,
2394 &cfg_rep_list
, &cfg_type_sockaddrnameport
2398 * A list of socket addresses or name with an optional default port,
2399 * as used in the dual-stack-servers option. E.g.,
2400 * "port 1234 { dual-stack-servers.net; 10.0.0.1; 1::2 port 69; }"
2402 static cfg_tuplefielddef_t nameportiplist_fields
[] = {
2403 { "port", &cfg_type_optional_port
, 0 },
2404 { "addresses", &cfg_type_bracketed_sockaddrnameportlist
, 0 },
2408 static cfg_type_t cfg_type_nameportiplist
= {
2409 "nameportiplist", cfg_parse_tuple
, cfg_print_tuple
, cfg_doc_tuple
,
2410 &cfg_rep_tuple
, nameportiplist_fields
2418 doc_masterselement(cfg_printer_t
*pctx
, const cfg_type_t
*type
) {
2420 cfg_print_chars(pctx
, "( ", 2);
2421 cfg_print_cstr(pctx
, "<masters>");
2422 cfg_print_chars(pctx
, " | ", 3);
2423 cfg_print_cstr(pctx
, "<ipv4_address>");
2424 cfg_print_chars(pctx
, " ", 1);
2425 cfg_print_cstr(pctx
, "[ port <integer> ]");
2426 cfg_print_chars(pctx
, " | ", 3);
2427 cfg_print_cstr(pctx
, "<ipv6_address>");
2428 cfg_print_chars(pctx
, " ", 1);
2429 cfg_print_cstr(pctx
, "[ port <integer> ]");
2430 cfg_print_chars(pctx
, " )", 2);
2434 parse_masterselement(cfg_parser_t
*pctx
, const cfg_type_t
*type
,
2437 isc_result_t result
;
2438 cfg_obj_t
*obj
= NULL
;
2441 CHECK(cfg_peektoken(pctx
, CFG_LEXOPT_QSTRING
));
2442 if (pctx
->token
.type
== isc_tokentype_string
||
2443 pctx
->token
.type
== isc_tokentype_qstring
) {
2444 if (cfg_lookingat_netaddr(pctx
, CFG_ADDR_V4OK
| CFG_ADDR_V6OK
))
2445 CHECK(cfg_parse_sockaddr(pctx
, &cfg_type_sockaddr
, ret
));
2447 CHECK(cfg_parse_astring(pctx
, &cfg_type_astring
, ret
));
2449 cfg_parser_error(pctx
, CFG_LOG_NEAR
,
2450 "expected IP address or masters name");
2451 return (ISC_R_UNEXPECTEDTOKEN
);
2458 static cfg_type_t cfg_type_masterselement
= {
2459 "masters_element", parse_masterselement
, NULL
,
2460 doc_masterselement
, NULL
, NULL