namedconf.c revision 1.1 1 1.1 christos /* $NetBSD: namedconf.c,v 1.1 2018/08/12 12:08:28 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 1.1 christos *
6 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public
7 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this
8 1.1 christos * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 1.1 christos *
10 1.1 christos * See the COPYRIGHT file distributed with this work for additional
11 1.1 christos * information regarding copyright ownership.
12 1.1 christos */
13 1.1 christos
14 1.1 christos /*! \file */
15 1.1 christos
16 1.1 christos #include <config.h>
17 1.1 christos
18 1.1 christos #include <stdlib.h>
19 1.1 christos #include <string.h>
20 1.1 christos
21 1.1 christos #include <isc/lex.h>
22 1.1 christos #include <isc/mem.h>
23 1.1 christos #include <isc/result.h>
24 1.1 christos #include <isc/string.h>
25 1.1 christos #include <isc/util.h>
26 1.1 christos
27 1.1 christos #include <dns/ttl.h>
28 1.1 christos #include <dns/result.h>
29 1.1 christos
30 1.1 christos #include <isccfg/cfg.h>
31 1.1 christos #include <isccfg/grammar.h>
32 1.1 christos #include <isccfg/log.h>
33 1.1 christos #include <isccfg/namedconf.h>
34 1.1 christos
35 1.1 christos #define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)
36 1.1 christos
37 1.1 christos /*% Check a return value. */
38 1.1 christos #define CHECK(op) \
39 1.1 christos do { result = (op); \
40 1.1 christos if (result != ISC_R_SUCCESS) goto cleanup; \
41 1.1 christos } while (0)
42 1.1 christos
43 1.1 christos /*% Clean up a configuration object if non-NULL. */
44 1.1 christos #define CLEANUP_OBJ(obj) \
45 1.1 christos do { if ((obj) != NULL) cfg_obj_destroy(pctx, &(obj)); } while (0)
46 1.1 christos
47 1.1 christos
48 1.1 christos /*%
49 1.1 christos * Forward declarations of static functions.
50 1.1 christos */
51 1.1 christos
52 1.1 christos static isc_result_t
53 1.1 christos parse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype,
54 1.1 christos const cfg_type_t *othertype, cfg_obj_t **ret);
55 1.1 christos
56 1.1 christos static void
57 1.1 christos doc_enum_or_other(cfg_printer_t *pctx, const cfg_type_t *enumtype,
58 1.1 christos const cfg_type_t *othertype);
59 1.1 christos
60 1.1 christos static isc_result_t
61 1.1 christos parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
62 1.1 christos
63 1.1 christos static isc_result_t
64 1.1 christos parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
65 1.1 christos cfg_obj_t **ret);
66 1.1 christos
67 1.1 christos static isc_result_t
68 1.1 christos parse_updatepolicy(cfg_parser_t *pctx, const cfg_type_t *type,
69 1.1 christos cfg_obj_t **ret);
70 1.1 christos static void
71 1.1 christos print_updatepolicy(cfg_printer_t *pctx, const cfg_obj_t *obj);
72 1.1 christos
73 1.1 christos static void
74 1.1 christos doc_updatepolicy(cfg_printer_t *pctx, const cfg_type_t *type);
75 1.1 christos
76 1.1 christos static void
77 1.1 christos print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj);
78 1.1 christos
79 1.1 christos static void
80 1.1 christos doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type);
81 1.1 christos
82 1.1 christos static void
83 1.1 christos doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type);
84 1.1 christos
85 1.1 christos #ifdef HAVE_GEOIP
86 1.1 christos static isc_result_t
87 1.1 christos parse_geoip(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
88 1.1 christos
89 1.1 christos static void
90 1.1 christos print_geoip(cfg_printer_t *pctx, const cfg_obj_t *obj);
91 1.1 christos
92 1.1 christos static void
93 1.1 christos doc_geoip(cfg_printer_t *pctx, const cfg_type_t *type);
94 1.1 christos #endif /* HAVE_GEOIP */
95 1.1 christos
96 1.1 christos static cfg_type_t cfg_type_acl;
97 1.1 christos static cfg_type_t cfg_type_addrmatchelt;
98 1.1 christos static cfg_type_t cfg_type_bracketed_aml;
99 1.1 christos static cfg_type_t cfg_type_bracketed_dscpsockaddrlist;
100 1.1 christos static cfg_type_t cfg_type_bracketed_namesockaddrkeylist;
101 1.1 christos static cfg_type_t cfg_type_bracketed_sockaddrlist;
102 1.1 christos static cfg_type_t cfg_type_bracketed_sockaddrnameportlist;
103 1.1 christos static cfg_type_t cfg_type_controls;
104 1.1 christos static cfg_type_t cfg_type_controls_sockaddr;
105 1.1 christos static cfg_type_t cfg_type_destinationlist;
106 1.1 christos static cfg_type_t cfg_type_dialuptype;
107 1.1 christos static cfg_type_t cfg_type_dlz;
108 1.1 christos static cfg_type_t cfg_type_dnstap;
109 1.1 christos static cfg_type_t cfg_type_dnstapoutput;
110 1.1 christos static cfg_type_t cfg_type_dyndb;
111 1.1 christos static cfg_type_t cfg_type_filter_aaaa;
112 1.1 christos static cfg_type_t cfg_type_ixfrdifftype;
113 1.1 christos static cfg_type_t cfg_type_key;
114 1.1 christos static cfg_type_t cfg_type_logfile;
115 1.1 christos static cfg_type_t cfg_type_logging;
116 1.1 christos static cfg_type_t cfg_type_logseverity;
117 1.1 christos static cfg_type_t cfg_type_logsuffix;
118 1.1 christos static cfg_type_t cfg_type_logversions;
119 1.1 christos static cfg_type_t cfg_type_masterselement;
120 1.1 christos static cfg_type_t cfg_type_maxttl;
121 1.1 christos static cfg_type_t cfg_type_minimal;
122 1.1 christos static cfg_type_t cfg_type_nameportiplist;
123 1.1 christos static cfg_type_t cfg_type_negated;
124 1.1 christos static cfg_type_t cfg_type_notifytype;
125 1.1 christos static cfg_type_t cfg_type_optional_allow;
126 1.1 christos static cfg_type_t cfg_type_optional_class;
127 1.1 christos static cfg_type_t cfg_type_optional_dscp;
128 1.1 christos static cfg_type_t cfg_type_optional_facility;
129 1.1 christos static cfg_type_t cfg_type_optional_keyref;
130 1.1 christos static cfg_type_t cfg_type_optional_port;
131 1.1 christos static cfg_type_t cfg_type_optional_uint32;
132 1.1 christos static cfg_type_t cfg_type_options;
133 1.1 christos static cfg_type_t cfg_type_portiplist;
134 1.1 christos static cfg_type_t cfg_type_printtime;
135 1.1 christos static cfg_type_t cfg_type_querysource4;
136 1.1 christos static cfg_type_t cfg_type_querysource6;
137 1.1 christos static cfg_type_t cfg_type_querysource;
138 1.1 christos static cfg_type_t cfg_type_server;
139 1.1 christos static cfg_type_t cfg_type_server_key_kludge;
140 1.1 christos static cfg_type_t cfg_type_size;
141 1.1 christos static cfg_type_t cfg_type_sizenodefault;
142 1.1 christos static cfg_type_t cfg_type_sizeorpercent;
143 1.1 christos static cfg_type_t cfg_type_sizeval;
144 1.1 christos static cfg_type_t cfg_type_sockaddr4wild;
145 1.1 christos static cfg_type_t cfg_type_sockaddr6wild;
146 1.1 christos static cfg_type_t cfg_type_statschannels;
147 1.1 christos static cfg_type_t cfg_type_ttlval;
148 1.1 christos static cfg_type_t cfg_type_view;
149 1.1 christos static cfg_type_t cfg_type_viewopts;
150 1.1 christos static cfg_type_t cfg_type_zone;
151 1.1 christos
152 1.1 christos /*% tkey-dhkey */
153 1.1 christos
154 1.1 christos static cfg_tuplefielddef_t tkey_dhkey_fields[] = {
155 1.1 christos { "name", &cfg_type_qstring, 0 },
156 1.1 christos { "keyid", &cfg_type_uint32, 0 },
157 1.1 christos { NULL, NULL, 0 }
158 1.1 christos };
159 1.1 christos
160 1.1 christos static cfg_type_t cfg_type_tkey_dhkey = {
161 1.1 christos "tkey-dhkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
162 1.1 christos &cfg_rep_tuple, tkey_dhkey_fields
163 1.1 christos };
164 1.1 christos
165 1.1 christos /*% listen-on */
166 1.1 christos
167 1.1 christos static cfg_tuplefielddef_t listenon_fields[] = {
168 1.1 christos { "port", &cfg_type_optional_port, 0 },
169 1.1 christos { "dscp", &cfg_type_optional_dscp, 0 },
170 1.1 christos { "acl", &cfg_type_bracketed_aml, 0 },
171 1.1 christos { NULL, NULL, 0 }
172 1.1 christos };
173 1.1 christos
174 1.1 christos static cfg_type_t cfg_type_listenon = {
175 1.1 christos "listenon", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
176 1.1 christos &cfg_rep_tuple, listenon_fields
177 1.1 christos };
178 1.1 christos
179 1.1 christos /*% acl */
180 1.1 christos
181 1.1 christos static cfg_tuplefielddef_t acl_fields[] = {
182 1.1 christos { "name", &cfg_type_astring, 0 },
183 1.1 christos { "value", &cfg_type_bracketed_aml, 0 },
184 1.1 christos { NULL, NULL, 0 }
185 1.1 christos };
186 1.1 christos
187 1.1 christos static cfg_type_t cfg_type_acl = {
188 1.1 christos "acl", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
189 1.1 christos &cfg_rep_tuple, acl_fields
190 1.1 christos };
191 1.1 christos
192 1.1 christos /*% masters */
193 1.1 christos static cfg_tuplefielddef_t masters_fields[] = {
194 1.1 christos { "name", &cfg_type_astring, 0 },
195 1.1 christos { "port", &cfg_type_optional_port, 0 },
196 1.1 christos { "dscp", &cfg_type_optional_dscp, 0 },
197 1.1 christos { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
198 1.1 christos { NULL, NULL, 0 }
199 1.1 christos };
200 1.1 christos
201 1.1 christos static cfg_type_t cfg_type_masters = {
202 1.1 christos "masters", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
203 1.1 christos &cfg_rep_tuple, masters_fields
204 1.1 christos };
205 1.1 christos
206 1.1 christos /*%
207 1.1 christos * "sockaddrkeylist", a list of socket addresses with optional keys
208 1.1 christos * and an optional default port, as used in the masters option.
209 1.1 christos * E.g.,
210 1.1 christos * "port 1234 { mymasters; 10.0.0.1 key foo; 1::2 port 69; }"
211 1.1 christos */
212 1.1 christos
213 1.1 christos static cfg_tuplefielddef_t namesockaddrkey_fields[] = {
214 1.1 christos { "masterselement", &cfg_type_masterselement, 0 },
215 1.1 christos { "key", &cfg_type_optional_keyref, 0 },
216 1.1 christos { NULL, NULL, 0 },
217 1.1 christos };
218 1.1 christos
219 1.1 christos static cfg_type_t cfg_type_namesockaddrkey = {
220 1.1 christos "namesockaddrkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
221 1.1 christos &cfg_rep_tuple, namesockaddrkey_fields
222 1.1 christos };
223 1.1 christos
224 1.1 christos static cfg_type_t cfg_type_bracketed_namesockaddrkeylist = {
225 1.1 christos "bracketed_namesockaddrkeylist", cfg_parse_bracketed_list,
226 1.1 christos cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list,
227 1.1 christos &cfg_type_namesockaddrkey
228 1.1 christos };
229 1.1 christos
230 1.1 christos static cfg_tuplefielddef_t namesockaddrkeylist_fields[] = {
231 1.1 christos { "port", &cfg_type_optional_port, 0 },
232 1.1 christos { "dscp", &cfg_type_optional_dscp, 0 },
233 1.1 christos { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
234 1.1 christos { NULL, NULL, 0 }
235 1.1 christos };
236 1.1 christos static cfg_type_t cfg_type_namesockaddrkeylist = {
237 1.1 christos "sockaddrkeylist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
238 1.1 christos &cfg_rep_tuple, namesockaddrkeylist_fields
239 1.1 christos };
240 1.1 christos
241 1.1 christos /*%
242 1.1 christos * A list of socket addresses with an optional default port, as used
243 1.1 christos * in the 'listen-on' option. E.g., "{ 10.0.0.1; 1::2 port 69; }"
244 1.1 christos */
245 1.1 christos static cfg_tuplefielddef_t portiplist_fields[] = {
246 1.1 christos { "port", &cfg_type_optional_port, 0 },
247 1.1 christos { "dscp", &cfg_type_optional_dscp, 0 },
248 1.1 christos { "addresses", &cfg_type_bracketed_dscpsockaddrlist, 0 },
249 1.1 christos { NULL, NULL, 0 }
250 1.1 christos };
251 1.1 christos static cfg_type_t cfg_type_portiplist = {
252 1.1 christos "portiplist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
253 1.1 christos &cfg_rep_tuple, portiplist_fields
254 1.1 christos };
255 1.1 christos
256 1.1 christos /*%
257 1.1 christos * A public key, as in the "pubkey" statement.
258 1.1 christos */
259 1.1 christos static cfg_tuplefielddef_t pubkey_fields[] = {
260 1.1 christos { "flags", &cfg_type_uint32, 0 },
261 1.1 christos { "protocol", &cfg_type_uint32, 0 },
262 1.1 christos { "algorithm", &cfg_type_uint32, 0 },
263 1.1 christos { "key", &cfg_type_qstring, 0 },
264 1.1 christos { NULL, NULL, 0 }
265 1.1 christos };
266 1.1 christos static cfg_type_t cfg_type_pubkey = {
267 1.1 christos "pubkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
268 1.1 christos &cfg_rep_tuple, pubkey_fields
269 1.1 christos };
270 1.1 christos
271 1.1 christos /*%
272 1.1 christos * A list of RR types, used in grant statements.
273 1.1 christos * Note that the old parser allows quotes around the RR type names.
274 1.1 christos */
275 1.1 christos static cfg_type_t cfg_type_rrtypelist = {
276 1.1 christos "rrtypelist", cfg_parse_spacelist, cfg_print_spacelist,
277 1.1 christos cfg_doc_terminal, &cfg_rep_list, &cfg_type_astring
278 1.1 christos };
279 1.1 christos
280 1.1 christos static const char *mode_enums[] = { "deny", "grant", NULL };
281 1.1 christos static cfg_type_t cfg_type_mode = {
282 1.1 christos "mode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
283 1.1 christos &cfg_rep_string, &mode_enums
284 1.1 christos };
285 1.1 christos
286 1.1 christos static isc_result_t
287 1.1 christos parse_matchtype(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
288 1.1 christos isc_result_t result;
289 1.1 christos
290 1.1 christos CHECK(cfg_peektoken(pctx, 0));
291 1.1 christos if (pctx->token.type == isc_tokentype_string &&
292 1.1 christos strcasecmp(TOKEN_STRING(pctx), "zonesub") == 0) {
293 1.1 christos pctx->flags |= CFG_PCTX_SKIP;
294 1.1 christos }
295 1.1 christos return (cfg_parse_enum(pctx, type, ret));
296 1.1 christos
297 1.1 christos cleanup:
298 1.1 christos return (result);
299 1.1 christos }
300 1.1 christos
301 1.1 christos static isc_result_t
302 1.1 christos parse_matchname(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
303 1.1 christos isc_result_t result;
304 1.1 christos cfg_obj_t *obj = NULL;
305 1.1 christos
306 1.1 christos if ((pctx->flags & CFG_PCTX_SKIP) != 0) {
307 1.1 christos pctx->flags &= ~CFG_PCTX_SKIP;
308 1.1 christos CHECK(cfg_parse_void(pctx, NULL, &obj));
309 1.1 christos } else
310 1.1 christos result = cfg_parse_astring(pctx, type, &obj);
311 1.1 christos
312 1.1 christos *ret = obj;
313 1.1 christos cleanup:
314 1.1 christos return (result);
315 1.1 christos }
316 1.1 christos
317 1.1 christos static void
318 1.1 christos doc_matchname(cfg_printer_t *pctx, const cfg_type_t *type) {
319 1.1 christos cfg_print_cstr(pctx, "[ ");
320 1.1 christos cfg_doc_obj(pctx, type->of);
321 1.1 christos cfg_print_cstr(pctx, " ]");
322 1.1 christos }
323 1.1 christos
324 1.1 christos static const char *matchtype_enums[] = {
325 1.1 christos "6to4-self", "external", "krb5-self", "krb5-subdomain", "ms-self",
326 1.1 christos "ms-subdomain", "name", "self", "selfsub", "selfwild", "subdomain",
327 1.1 christos "tcp-self", "wildcard", "zonesub", NULL
328 1.1 christos };
329 1.1 christos
330 1.1 christos static cfg_type_t cfg_type_matchtype = {
331 1.1 christos "matchtype", parse_matchtype, cfg_print_ustring,
332 1.1 christos cfg_doc_enum, &cfg_rep_string, &matchtype_enums
333 1.1 christos };
334 1.1 christos
335 1.1 christos static cfg_type_t cfg_type_matchname = {
336 1.1 christos "optional_matchname", parse_matchname, cfg_print_ustring,
337 1.1 christos &doc_matchname, &cfg_rep_tuple, &cfg_type_ustring
338 1.1 christos };
339 1.1 christos
340 1.1 christos /*%
341 1.1 christos * A grant statement, used in the update policy.
342 1.1 christos */
343 1.1 christos static cfg_tuplefielddef_t grant_fields[] = {
344 1.1 christos { "mode", &cfg_type_mode, 0 },
345 1.1 christos { "identity", &cfg_type_astring, 0 }, /* domain name */
346 1.1 christos { "matchtype", &cfg_type_matchtype, 0 },
347 1.1 christos { "name", &cfg_type_matchname, 0 }, /* domain name */
348 1.1 christos { "types", &cfg_type_rrtypelist, 0 },
349 1.1 christos { NULL, NULL, 0 }
350 1.1 christos };
351 1.1 christos static cfg_type_t cfg_type_grant = {
352 1.1 christos "grant", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
353 1.1 christos &cfg_rep_tuple, grant_fields
354 1.1 christos };
355 1.1 christos
356 1.1 christos static cfg_type_t cfg_type_updatepolicy = {
357 1.1 christos "update_policy", parse_updatepolicy, print_updatepolicy,
358 1.1 christos doc_updatepolicy, &cfg_rep_list, &cfg_type_grant
359 1.1 christos };
360 1.1 christos
361 1.1 christos static isc_result_t
362 1.1 christos parse_updatepolicy(cfg_parser_t *pctx, const cfg_type_t *type,
363 1.1 christos cfg_obj_t **ret)
364 1.1 christos {
365 1.1 christos isc_result_t result;
366 1.1 christos CHECK(cfg_gettoken(pctx, 0));
367 1.1 christos if (pctx->token.type == isc_tokentype_special &&
368 1.1 christos pctx->token.value.as_char == '{') {
369 1.1 christos cfg_ungettoken(pctx);
370 1.1 christos return (cfg_parse_bracketed_list(pctx, type, ret));
371 1.1 christos }
372 1.1 christos
373 1.1 christos if (pctx->token.type == isc_tokentype_string &&
374 1.1 christos strcasecmp(TOKEN_STRING(pctx), "local") == 0) {
375 1.1 christos cfg_obj_t *obj = NULL;
376 1.1 christos CHECK(cfg_create_obj(pctx, &cfg_type_ustring, &obj));
377 1.1 christos obj->value.string.length = strlen("local");
378 1.1 christos obj->value.string.base = isc_mem_get(pctx->mctx,
379 1.1 christos obj->value.string.length + 1);
380 1.1 christos if (obj->value.string.base == NULL) {
381 1.1 christos isc_mem_put(pctx->mctx, obj, sizeof(*obj));
382 1.1 christos return (ISC_R_NOMEMORY);
383 1.1 christos }
384 1.1 christos memmove(obj->value.string.base, "local", 5);
385 1.1 christos obj->value.string.base[5] = '\0';
386 1.1 christos *ret = obj;
387 1.1 christos return (ISC_R_SUCCESS);
388 1.1 christos }
389 1.1 christos
390 1.1 christos cfg_ungettoken(pctx);
391 1.1 christos return (ISC_R_UNEXPECTEDTOKEN);
392 1.1 christos
393 1.1 christos cleanup:
394 1.1 christos return (result);
395 1.1 christos }
396 1.1 christos
397 1.1 christos static void
398 1.1 christos print_updatepolicy(cfg_printer_t *pctx, const cfg_obj_t *obj) {
399 1.1 christos if (cfg_obj_isstring(obj))
400 1.1 christos cfg_print_ustring(pctx, obj);
401 1.1 christos else
402 1.1 christos cfg_print_bracketed_list(pctx, obj);
403 1.1 christos }
404 1.1 christos
405 1.1 christos static void
406 1.1 christos doc_updatepolicy(cfg_printer_t *pctx, const cfg_type_t *type) {
407 1.1 christos cfg_print_cstr(pctx, "( local | { ");
408 1.1 christos cfg_doc_obj(pctx, type->of);
409 1.1 christos cfg_print_cstr(pctx, "; ... }");
410 1.1 christos }
411 1.1 christos
412 1.1 christos /*%
413 1.1 christos * A view statement.
414 1.1 christos */
415 1.1 christos static cfg_tuplefielddef_t view_fields[] = {
416 1.1 christos { "name", &cfg_type_astring, 0 },
417 1.1 christos { "class", &cfg_type_optional_class, 0 },
418 1.1 christos { "options", &cfg_type_viewopts, 0 },
419 1.1 christos { NULL, NULL, 0 }
420 1.1 christos };
421 1.1 christos static cfg_type_t cfg_type_view = {
422 1.1 christos "view", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
423 1.1 christos &cfg_rep_tuple, view_fields
424 1.1 christos };
425 1.1 christos
426 1.1 christos /*%
427 1.1 christos * A zone statement.
428 1.1 christos */
429 1.1 christos static cfg_tuplefielddef_t zone_fields[] = {
430 1.1 christos { "name", &cfg_type_astring, 0 },
431 1.1 christos { "class", &cfg_type_optional_class, 0 },
432 1.1 christos { "options", &cfg_type_zoneopts, 0 },
433 1.1 christos { NULL, NULL, 0 }
434 1.1 christos };
435 1.1 christos static cfg_type_t cfg_type_zone = {
436 1.1 christos "zone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
437 1.1 christos &cfg_rep_tuple, zone_fields
438 1.1 christos };
439 1.1 christos
440 1.1 christos /*%
441 1.1 christos * A "category" clause in the "logging" statement.
442 1.1 christos */
443 1.1 christos static cfg_tuplefielddef_t category_fields[] = {
444 1.1 christos { "name", &cfg_type_astring, 0 },
445 1.1 christos { "destinations", &cfg_type_destinationlist,0 },
446 1.1 christos { NULL, NULL, 0 }
447 1.1 christos };
448 1.1 christos static cfg_type_t cfg_type_category = {
449 1.1 christos "category", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
450 1.1 christos &cfg_rep_tuple, category_fields
451 1.1 christos };
452 1.1 christos
453 1.1 christos
454 1.1 christos /*%
455 1.1 christos * A dnssec key, as used in the "trusted-keys" statement.
456 1.1 christos */
457 1.1 christos static cfg_tuplefielddef_t dnsseckey_fields[] = {
458 1.1 christos { "name", &cfg_type_astring, 0 },
459 1.1 christos { "flags", &cfg_type_uint32, 0 },
460 1.1 christos { "protocol", &cfg_type_uint32, 0 },
461 1.1 christos { "algorithm", &cfg_type_uint32, 0 },
462 1.1 christos { "key", &cfg_type_qstring, 0 },
463 1.1 christos { NULL, NULL, 0 }
464 1.1 christos };
465 1.1 christos static cfg_type_t cfg_type_dnsseckey = {
466 1.1 christos "dnsseckey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
467 1.1 christos &cfg_rep_tuple, dnsseckey_fields
468 1.1 christos };
469 1.1 christos
470 1.1 christos /*%
471 1.1 christos * A managed key initialization specifier, as used in the
472 1.1 christos * "managed-keys" statement.
473 1.1 christos */
474 1.1 christos static cfg_tuplefielddef_t managedkey_fields[] = {
475 1.1 christos { "name", &cfg_type_astring, 0 },
476 1.1 christos { "init", &cfg_type_ustring, 0 }, /* must be literal "initial-key" */
477 1.1 christos { "flags", &cfg_type_uint32, 0 },
478 1.1 christos { "protocol", &cfg_type_uint32, 0 },
479 1.1 christos { "algorithm", &cfg_type_uint32, 0 },
480 1.1 christos { "key", &cfg_type_qstring, 0 },
481 1.1 christos { NULL, NULL, 0 }
482 1.1 christos };
483 1.1 christos static cfg_type_t cfg_type_managedkey = {
484 1.1 christos "managedkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
485 1.1 christos &cfg_rep_tuple, managedkey_fields
486 1.1 christos };
487 1.1 christos
488 1.1 christos static keyword_type_t wild_class_kw = { "class", &cfg_type_ustring };
489 1.1 christos
490 1.1 christos static cfg_type_t cfg_type_optional_wild_class = {
491 1.1 christos "optional_wild_class", parse_optional_keyvalue, print_keyvalue,
492 1.1 christos doc_optional_keyvalue, &cfg_rep_string, &wild_class_kw
493 1.1 christos };
494 1.1 christos
495 1.1 christos static keyword_type_t wild_type_kw = { "type", &cfg_type_ustring };
496 1.1 christos
497 1.1 christos static cfg_type_t cfg_type_optional_wild_type = {
498 1.1 christos "optional_wild_type", parse_optional_keyvalue,
499 1.1 christos print_keyvalue, doc_optional_keyvalue, &cfg_rep_string, &wild_type_kw
500 1.1 christos };
501 1.1 christos
502 1.1 christos static keyword_type_t wild_name_kw = { "name", &cfg_type_qstring };
503 1.1 christos
504 1.1 christos static cfg_type_t cfg_type_optional_wild_name = {
505 1.1 christos "optional_wild_name", parse_optional_keyvalue, print_keyvalue,
506 1.1 christos doc_optional_keyvalue, &cfg_rep_string, &wild_name_kw
507 1.1 christos };
508 1.1 christos
509 1.1 christos /*%
510 1.1 christos * An rrset ordering element.
511 1.1 christos */
512 1.1 christos static cfg_tuplefielddef_t rrsetorderingelement_fields[] = {
513 1.1 christos { "class", &cfg_type_optional_wild_class, 0 },
514 1.1 christos { "type", &cfg_type_optional_wild_type, 0 },
515 1.1 christos { "name", &cfg_type_optional_wild_name, 0 },
516 1.1 christos { "order", &cfg_type_ustring, 0 }, /* must be literal "order" */
517 1.1 christos { "ordering", &cfg_type_ustring, 0 },
518 1.1 christos { NULL, NULL, 0 }
519 1.1 christos };
520 1.1 christos static cfg_type_t cfg_type_rrsetorderingelement = {
521 1.1 christos "rrsetorderingelement", cfg_parse_tuple, cfg_print_tuple,
522 1.1 christos cfg_doc_tuple, &cfg_rep_tuple, rrsetorderingelement_fields
523 1.1 christos };
524 1.1 christos
525 1.1 christos /*%
526 1.1 christos * A global or view "check-names" option. Note that the zone
527 1.1 christos * "check-names" option has a different syntax.
528 1.1 christos */
529 1.1 christos
530 1.1 christos static const char *checktype_enums[] = { "master", "slave", "response", NULL };
531 1.1 christos static cfg_type_t cfg_type_checktype = {
532 1.1 christos "checktype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
533 1.1 christos &cfg_rep_string, &checktype_enums
534 1.1 christos };
535 1.1 christos
536 1.1 christos static const char *checkmode_enums[] = { "fail", "warn", "ignore", NULL };
537 1.1 christos static cfg_type_t cfg_type_checkmode = {
538 1.1 christos "checkmode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
539 1.1 christos &cfg_rep_string, &checkmode_enums
540 1.1 christos };
541 1.1 christos
542 1.1 christos static const char *warn_enums[] = { "warn", "ignore", NULL };
543 1.1 christos static cfg_type_t cfg_type_warn = {
544 1.1 christos "warn", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
545 1.1 christos &cfg_rep_string, &warn_enums
546 1.1 christos };
547 1.1 christos
548 1.1 christos static cfg_tuplefielddef_t checknames_fields[] = {
549 1.1 christos { "type", &cfg_type_checktype, 0 },
550 1.1 christos { "mode", &cfg_type_checkmode, 0 },
551 1.1 christos { NULL, NULL, 0 }
552 1.1 christos };
553 1.1 christos
554 1.1 christos static cfg_type_t cfg_type_checknames = {
555 1.1 christos "checknames", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
556 1.1 christos &cfg_rep_tuple, checknames_fields
557 1.1 christos };
558 1.1 christos
559 1.1 christos static cfg_type_t cfg_type_bracketed_dscpsockaddrlist = {
560 1.1 christos "bracketed_sockaddrlist", cfg_parse_bracketed_list,
561 1.1 christos cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list,
562 1.1 christos &cfg_type_sockaddrdscp
563 1.1 christos };
564 1.1 christos
565 1.1 christos static cfg_type_t cfg_type_bracketed_sockaddrlist = {
566 1.1 christos "bracketed_sockaddrlist", cfg_parse_bracketed_list,
567 1.1 christos cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list,
568 1.1 christos &cfg_type_sockaddr
569 1.1 christos };
570 1.1 christos
571 1.1 christos static const char *autodnssec_enums[] = {
572 1.1 christos "allow", "maintain", "off", NULL
573 1.1 christos };
574 1.1 christos static cfg_type_t cfg_type_autodnssec = {
575 1.1 christos "autodnssec", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
576 1.1 christos &cfg_rep_string, &autodnssec_enums
577 1.1 christos };
578 1.1 christos
579 1.1 christos static const char *dnssecupdatemode_enums[] = {
580 1.1 christos "maintain", "no-resign", NULL
581 1.1 christos };
582 1.1 christos static cfg_type_t cfg_type_dnssecupdatemode = {
583 1.1 christos "dnssecupdatemode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
584 1.1 christos &cfg_rep_string, &dnssecupdatemode_enums
585 1.1 christos };
586 1.1 christos
587 1.1 christos static const char *updatemethods_enums[] = {
588 1.1 christos "date", "increment", "unixtime", NULL
589 1.1 christos };
590 1.1 christos static cfg_type_t cfg_type_updatemethod = {
591 1.1 christos "updatemethod", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
592 1.1 christos &cfg_rep_string, &updatemethods_enums
593 1.1 christos };
594 1.1 christos
595 1.1 christos /*
596 1.1 christos * zone-statistics: full, terse, or none.
597 1.1 christos *
598 1.1 christos * for backward compatibility, we also support boolean values.
599 1.1 christos * yes represents "full", no represents "terse". in the future we
600 1.1 christos * may change no to mean "none".
601 1.1 christos */
602 1.1 christos static const char *zonestat_enums[] = { "full", "terse", "none", NULL };
603 1.1 christos static isc_result_t
604 1.1 christos parse_zonestat(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
605 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
606 1.1 christos }
607 1.1 christos static void
608 1.1 christos doc_zonestat(cfg_printer_t *pctx, const cfg_type_t *type) {
609 1.1 christos doc_enum_or_other(pctx, type, &cfg_type_boolean);
610 1.1 christos }
611 1.1 christos static cfg_type_t cfg_type_zonestat = {
612 1.1 christos "zonestat", parse_zonestat, cfg_print_ustring, doc_zonestat,
613 1.1 christos &cfg_rep_string, zonestat_enums
614 1.1 christos };
615 1.1 christos
616 1.1 christos static cfg_type_t cfg_type_rrsetorder = {
617 1.1 christos "rrsetorder", cfg_parse_bracketed_list, cfg_print_bracketed_list,
618 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_rrsetorderingelement
619 1.1 christos };
620 1.1 christos
621 1.1 christos static keyword_type_t dscp_kw = { "dscp", &cfg_type_uint32 };
622 1.1 christos
623 1.1 christos static cfg_type_t cfg_type_optional_dscp = {
624 1.1 christos "optional_dscp", parse_optional_keyvalue, print_keyvalue,
625 1.1 christos doc_optional_keyvalue, &cfg_rep_uint32, &dscp_kw
626 1.1 christos };
627 1.1 christos
628 1.1 christos static keyword_type_t port_kw = { "port", &cfg_type_uint32 };
629 1.1 christos
630 1.1 christos static cfg_type_t cfg_type_optional_port = {
631 1.1 christos "optional_port", parse_optional_keyvalue, print_keyvalue,
632 1.1 christos doc_optional_keyvalue, &cfg_rep_uint32, &port_kw
633 1.1 christos };
634 1.1 christos
635 1.1 christos /*% A list of keys, as in the "key" clause of the controls statement. */
636 1.1 christos static cfg_type_t cfg_type_keylist = {
637 1.1 christos "keylist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
638 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring
639 1.1 christos };
640 1.1 christos
641 1.1 christos /*% A list of dnssec keys, as in "trusted-keys" */
642 1.1 christos static cfg_type_t cfg_type_dnsseckeys = {
643 1.1 christos "dnsseckeys", cfg_parse_bracketed_list, cfg_print_bracketed_list,
644 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_dnsseckey
645 1.1 christos };
646 1.1 christos
647 1.1 christos /*%
648 1.1 christos * A list of managed key entries, as in "trusted-keys". Currently
649 1.1 christos * (9.7.0) this has a format similar to dnssec keys, except the keyname
650 1.1 christos * is followed by the keyword "initial-key". In future releases, this
651 1.1 christos * keyword may take other values indicating different methods for the
652 1.1 christos * key to be initialized.
653 1.1 christos */
654 1.1 christos
655 1.1 christos static cfg_type_t cfg_type_managedkeys = {
656 1.1 christos "managedkeys", cfg_parse_bracketed_list, cfg_print_bracketed_list,
657 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_managedkey
658 1.1 christos };
659 1.1 christos
660 1.1 christos static const char *forwardtype_enums[] = { "first", "only", NULL };
661 1.1 christos static cfg_type_t cfg_type_forwardtype = {
662 1.1 christos "forwardtype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
663 1.1 christos &cfg_rep_string, &forwardtype_enums
664 1.1 christos };
665 1.1 christos
666 1.1 christos static const char *zonetype_enums[] = {
667 1.1 christos "delegation-only", "forward", "hint", "master", "redirect",
668 1.1 christos "slave", "static-stub", "stub", NULL
669 1.1 christos };
670 1.1 christos static cfg_type_t cfg_type_zonetype = {
671 1.1 christos "zonetype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
672 1.1 christos &cfg_rep_string, &zonetype_enums
673 1.1 christos };
674 1.1 christos
675 1.1 christos static const char *loglevel_enums[] = {
676 1.1 christos "critical", "error", "warning", "notice", "info", "dynamic", NULL
677 1.1 christos };
678 1.1 christos static cfg_type_t cfg_type_loglevel = {
679 1.1 christos "loglevel", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
680 1.1 christos &cfg_rep_string, &loglevel_enums
681 1.1 christos };
682 1.1 christos
683 1.1 christos static const char *transferformat_enums[] = {
684 1.1 christos "many-answers", "one-answer", NULL
685 1.1 christos };
686 1.1 christos static cfg_type_t cfg_type_transferformat = {
687 1.1 christos "transferformat", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
688 1.1 christos &cfg_rep_string, &transferformat_enums
689 1.1 christos };
690 1.1 christos
691 1.1 christos /*%
692 1.1 christos * The special keyword "none", as used in the pid-file option.
693 1.1 christos */
694 1.1 christos
695 1.1 christos static void
696 1.1 christos print_none(cfg_printer_t *pctx, const cfg_obj_t *obj) {
697 1.1 christos UNUSED(obj);
698 1.1 christos cfg_print_cstr(pctx, "none");
699 1.1 christos }
700 1.1 christos
701 1.1 christos static cfg_type_t cfg_type_none = {
702 1.1 christos "none", NULL, print_none, NULL, &cfg_rep_void, NULL
703 1.1 christos };
704 1.1 christos
705 1.1 christos /*%
706 1.1 christos * A quoted string or the special keyword "none". Used in the pid-file option.
707 1.1 christos */
708 1.1 christos static isc_result_t
709 1.1 christos parse_qstringornone(cfg_parser_t *pctx, const cfg_type_t *type,
710 1.1 christos cfg_obj_t **ret)
711 1.1 christos {
712 1.1 christos isc_result_t result;
713 1.1 christos
714 1.1 christos CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
715 1.1 christos if (pctx->token.type == isc_tokentype_string &&
716 1.1 christos strcasecmp(TOKEN_STRING(pctx), "none") == 0)
717 1.1 christos return (cfg_create_obj(pctx, &cfg_type_none, ret));
718 1.1 christos cfg_ungettoken(pctx);
719 1.1 christos return (cfg_parse_qstring(pctx, type, ret));
720 1.1 christos cleanup:
721 1.1 christos return (result);
722 1.1 christos }
723 1.1 christos
724 1.1 christos static void
725 1.1 christos doc_qstringornone(cfg_printer_t *pctx, const cfg_type_t *type) {
726 1.1 christos UNUSED(type);
727 1.1 christos cfg_print_cstr(pctx, "( <quoted_string> | none )");
728 1.1 christos }
729 1.1 christos
730 1.1 christos static cfg_type_t cfg_type_qstringornone = {
731 1.1 christos "qstringornone", parse_qstringornone, NULL, doc_qstringornone,
732 1.1 christos NULL, NULL
733 1.1 christos };
734 1.1 christos
735 1.1 christos /*%
736 1.1 christos * A boolean ("yes" or "no"), or the special keyword "auto".
737 1.1 christos * Used in the dnssec-validation option.
738 1.1 christos */
739 1.1 christos static void
740 1.1 christos print_auto(cfg_printer_t *pctx, const cfg_obj_t *obj) {
741 1.1 christos UNUSED(obj);
742 1.1 christos cfg_print_cstr(pctx, "auto");
743 1.1 christos }
744 1.1 christos
745 1.1 christos static cfg_type_t cfg_type_auto = {
746 1.1 christos "auto", NULL, print_auto, NULL, &cfg_rep_void, NULL
747 1.1 christos };
748 1.1 christos
749 1.1 christos static isc_result_t
750 1.1 christos parse_boolorauto(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
751 1.1 christos isc_result_t result;
752 1.1 christos
753 1.1 christos CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
754 1.1 christos if (pctx->token.type == isc_tokentype_string &&
755 1.1 christos strcasecmp(TOKEN_STRING(pctx), "auto") == 0)
756 1.1 christos return (cfg_create_obj(pctx, &cfg_type_auto, ret));
757 1.1 christos cfg_ungettoken(pctx);
758 1.1 christos return (cfg_parse_boolean(pctx, type, ret));
759 1.1 christos cleanup:
760 1.1 christos return (result);
761 1.1 christos }
762 1.1 christos
763 1.1 christos static void
764 1.1 christos print_boolorauto(cfg_printer_t *pctx, const cfg_obj_t *obj) {
765 1.1 christos if (obj->type->rep == &cfg_rep_void)
766 1.1 christos cfg_print_cstr(pctx, "auto");
767 1.1 christos else if (obj->value.boolean)
768 1.1 christos cfg_print_cstr(pctx, "yes");
769 1.1 christos else
770 1.1 christos cfg_print_cstr(pctx, "no");
771 1.1 christos }
772 1.1 christos
773 1.1 christos static void
774 1.1 christos doc_boolorauto(cfg_printer_t *pctx, const cfg_type_t *type) {
775 1.1 christos UNUSED(type);
776 1.1 christos cfg_print_cstr(pctx, "( yes | no | auto )");
777 1.1 christos }
778 1.1 christos
779 1.1 christos static cfg_type_t cfg_type_boolorauto = {
780 1.1 christos "boolorauto", parse_boolorauto, print_boolorauto,
781 1.1 christos doc_boolorauto, NULL, NULL
782 1.1 christos };
783 1.1 christos
784 1.1 christos /*%
785 1.1 christos * keyword hostname
786 1.1 christos */
787 1.1 christos static void
788 1.1 christos print_hostname(cfg_printer_t *pctx, const cfg_obj_t *obj) {
789 1.1 christos UNUSED(obj);
790 1.1 christos cfg_print_cstr(pctx, "hostname");
791 1.1 christos }
792 1.1 christos
793 1.1 christos static cfg_type_t cfg_type_hostname = {
794 1.1 christos "hostname", NULL, print_hostname, NULL, &cfg_rep_boolean, NULL
795 1.1 christos };
796 1.1 christos
797 1.1 christos /*%
798 1.1 christos * "server-id" argument.
799 1.1 christos */
800 1.1 christos
801 1.1 christos static isc_result_t
802 1.1 christos parse_serverid(cfg_parser_t *pctx, const cfg_type_t *type,
803 1.1 christos cfg_obj_t **ret)
804 1.1 christos {
805 1.1 christos isc_result_t result;
806 1.1 christos CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
807 1.1 christos if (pctx->token.type == isc_tokentype_string &&
808 1.1 christos strcasecmp(TOKEN_STRING(pctx), "none") == 0)
809 1.1 christos return (cfg_create_obj(pctx, &cfg_type_none, ret));
810 1.1 christos if (pctx->token.type == isc_tokentype_string &&
811 1.1 christos strcasecmp(TOKEN_STRING(pctx), "hostname") == 0) {
812 1.1 christos result = cfg_create_obj(pctx, &cfg_type_hostname, ret);
813 1.1 christos if (result == ISC_R_SUCCESS)
814 1.1 christos (*ret)->value.boolean = ISC_TRUE;
815 1.1 christos return (result);
816 1.1 christos }
817 1.1 christos cfg_ungettoken(pctx);
818 1.1 christos return (cfg_parse_qstring(pctx, type, ret));
819 1.1 christos cleanup:
820 1.1 christos return (result);
821 1.1 christos }
822 1.1 christos
823 1.1 christos static void
824 1.1 christos doc_serverid(cfg_printer_t *pctx, const cfg_type_t *type) {
825 1.1 christos UNUSED(type);
826 1.1 christos cfg_print_cstr(pctx, "( <quoted_string> | none | hostname )");
827 1.1 christos }
828 1.1 christos
829 1.1 christos static cfg_type_t cfg_type_serverid = {
830 1.1 christos "serverid", parse_serverid, NULL, doc_serverid, NULL, NULL };
831 1.1 christos
832 1.1 christos /*%
833 1.1 christos * Port list.
834 1.1 christos */
835 1.1 christos static void
836 1.1 christos print_porttuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
837 1.1 christos cfg_print_cstr(pctx, "range ");
838 1.1 christos cfg_print_tuple(pctx, obj);
839 1.1 christos }
840 1.1 christos static cfg_tuplefielddef_t porttuple_fields[] = {
841 1.1 christos { "loport", &cfg_type_uint32, 0 },
842 1.1 christos { "hiport", &cfg_type_uint32, 0 },
843 1.1 christos { NULL, NULL, 0 }
844 1.1 christos };
845 1.1 christos static cfg_type_t cfg_type_porttuple = {
846 1.1 christos "porttuple", cfg_parse_tuple, print_porttuple, cfg_doc_tuple,
847 1.1 christos &cfg_rep_tuple, porttuple_fields
848 1.1 christos };
849 1.1 christos
850 1.1 christos static isc_result_t
851 1.1 christos parse_port(cfg_parser_t *pctx, cfg_obj_t **ret) {
852 1.1 christos isc_result_t result;
853 1.1 christos
854 1.1 christos CHECK(cfg_parse_uint32(pctx, NULL, ret));
855 1.1 christos if ((*ret)->value.uint32 > 0xffff) {
856 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR, "invalid port");
857 1.1 christos cfg_obj_destroy(pctx, ret);
858 1.1 christos result = ISC_R_RANGE;
859 1.1 christos }
860 1.1 christos
861 1.1 christos cleanup:
862 1.1 christos return (result);
863 1.1 christos }
864 1.1 christos
865 1.1 christos static isc_result_t
866 1.1 christos parse_portrange(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
867 1.1 christos isc_result_t result;
868 1.1 christos cfg_obj_t *obj = NULL;
869 1.1 christos
870 1.1 christos UNUSED(type);
871 1.1 christos
872 1.1 christos CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
873 1.1 christos if (pctx->token.type == isc_tokentype_number)
874 1.1 christos CHECK(parse_port(pctx, ret));
875 1.1 christos else {
876 1.1 christos CHECK(cfg_gettoken(pctx, 0));
877 1.1 christos if (pctx->token.type != isc_tokentype_string ||
878 1.1 christos strcasecmp(TOKEN_STRING(pctx), "range") != 0) {
879 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR,
880 1.1 christos "expected integer or 'range'");
881 1.1 christos return (ISC_R_UNEXPECTEDTOKEN);
882 1.1 christos }
883 1.1 christos CHECK(cfg_create_tuple(pctx, &cfg_type_porttuple, &obj));
884 1.1 christos CHECK(parse_port(pctx, &obj->value.tuple[0]));
885 1.1 christos CHECK(parse_port(pctx, &obj->value.tuple[1]));
886 1.1 christos if (obj->value.tuple[0]->value.uint32 >
887 1.1 christos obj->value.tuple[1]->value.uint32) {
888 1.1 christos cfg_parser_error(pctx, CFG_LOG_NOPREP,
889 1.1 christos "low port '%u' must not be larger "
890 1.1 christos "than high port",
891 1.1 christos obj->value.tuple[0]->value.uint32);
892 1.1 christos result = ISC_R_RANGE;
893 1.1 christos goto cleanup;
894 1.1 christos }
895 1.1 christos *ret = obj;
896 1.1 christos obj = NULL;
897 1.1 christos }
898 1.1 christos
899 1.1 christos cleanup:
900 1.1 christos if (obj != NULL)
901 1.1 christos cfg_obj_destroy(pctx, &obj);
902 1.1 christos return (result);
903 1.1 christos }
904 1.1 christos
905 1.1 christos static cfg_type_t cfg_type_portrange = {
906 1.1 christos "portrange", parse_portrange, NULL, cfg_doc_terminal,
907 1.1 christos NULL, NULL
908 1.1 christos };
909 1.1 christos
910 1.1 christos static cfg_type_t cfg_type_bracketed_portlist = {
911 1.1 christos "bracketed_sockaddrlist", cfg_parse_bracketed_list,
912 1.1 christos cfg_print_bracketed_list, cfg_doc_bracketed_list,
913 1.1 christos &cfg_rep_list, &cfg_type_portrange
914 1.1 christos };
915 1.1 christos
916 1.1 christos static const char *cookiealg_enums[] = { "aes", "sha1", "sha256", NULL };
917 1.1 christos static cfg_type_t cfg_type_cookiealg = {
918 1.1 christos "cookiealg", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
919 1.1 christos &cfg_rep_string, &cookiealg_enums
920 1.1 christos };
921 1.1 christos
922 1.1 christos /*%
923 1.1 christos * fetch-quota-params
924 1.1 christos */
925 1.1 christos
926 1.1 christos static cfg_tuplefielddef_t fetchquota_fields[] = {
927 1.1 christos { "frequency", &cfg_type_uint32, 0 },
928 1.1 christos { "low", &cfg_type_fixedpoint, 0 },
929 1.1 christos { "high", &cfg_type_fixedpoint, 0 },
930 1.1 christos { "discount", &cfg_type_fixedpoint, 0 },
931 1.1 christos { NULL, NULL, 0 }
932 1.1 christos };
933 1.1 christos
934 1.1 christos static cfg_type_t cfg_type_fetchquota = {
935 1.1 christos "fetchquota", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
936 1.1 christos &cfg_rep_tuple, fetchquota_fields
937 1.1 christos };
938 1.1 christos
939 1.1 christos /*%
940 1.1 christos * fetches-per-server or fetches-per-zone
941 1.1 christos */
942 1.1 christos
943 1.1 christos static const char *response_enums[] = { "drop", "fail", NULL };
944 1.1 christos
945 1.1 christos static isc_result_t
946 1.1 christos parse_optional_enum(cfg_parser_t *pctx, const cfg_type_t *type,
947 1.1 christos cfg_obj_t **ret)
948 1.1 christos {
949 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_void, ret));
950 1.1 christos }
951 1.1 christos
952 1.1 christos static void
953 1.1 christos doc_optional_enum(cfg_printer_t *pctx, const cfg_type_t *type) {
954 1.1 christos UNUSED(type);
955 1.1 christos cfg_print_cstr(pctx, "[ ");
956 1.1 christos cfg_doc_enum(pctx, type);
957 1.1 christos cfg_print_cstr(pctx, " ]");
958 1.1 christos }
959 1.1 christos
960 1.1 christos static cfg_type_t cfg_type_responsetype = {
961 1.1 christos "responsetype", parse_optional_enum, cfg_print_ustring,
962 1.1 christos doc_optional_enum, &cfg_rep_string, response_enums
963 1.1 christos };
964 1.1 christos
965 1.1 christos static cfg_tuplefielddef_t fetchesper_fields[] = {
966 1.1 christos { "fetches", &cfg_type_uint32, 0 },
967 1.1 christos { "response", &cfg_type_responsetype, 0 },
968 1.1 christos { NULL, NULL, 0 }
969 1.1 christos };
970 1.1 christos
971 1.1 christos static cfg_type_t cfg_type_fetchesper = {
972 1.1 christos "fetchesper", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
973 1.1 christos &cfg_rep_tuple, fetchesper_fields
974 1.1 christos };
975 1.1 christos
976 1.1 christos /*%
977 1.1 christos * Clauses that can be found within the top level of the named.conf
978 1.1 christos * file only.
979 1.1 christos */
980 1.1 christos static cfg_clausedef_t
981 1.1 christos namedconf_clauses[] = {
982 1.1 christos { "acl", &cfg_type_acl, CFG_CLAUSEFLAG_MULTI },
983 1.1 christos { "controls", &cfg_type_controls, CFG_CLAUSEFLAG_MULTI },
984 1.1 christos { "logging", &cfg_type_logging, 0 },
985 1.1 christos { "lwres", &cfg_type_bracketed_text,
986 1.1 christos CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_OBSOLETE },
987 1.1 christos { "masters", &cfg_type_masters, CFG_CLAUSEFLAG_MULTI },
988 1.1 christos { "options", &cfg_type_options, 0 },
989 1.1 christos { "statistics-channels", &cfg_type_statschannels,
990 1.1 christos CFG_CLAUSEFLAG_MULTI },
991 1.1 christos { "view", &cfg_type_view, CFG_CLAUSEFLAG_MULTI },
992 1.1 christos { NULL, NULL, 0 }
993 1.1 christos };
994 1.1 christos
995 1.1 christos /*%
996 1.1 christos * Clauses that can occur at the top level or in the view
997 1.1 christos * statement, but not in the options block.
998 1.1 christos */
999 1.1 christos static cfg_clausedef_t
1000 1.1 christos namedconf_or_view_clauses[] = {
1001 1.1 christos { "dlz", &cfg_type_dlz, CFG_CLAUSEFLAG_MULTI },
1002 1.1 christos { "dyndb", &cfg_type_dyndb, CFG_CLAUSEFLAG_MULTI },
1003 1.1 christos { "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
1004 1.1 christos { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI },
1005 1.1 christos { "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI },
1006 1.1 christos { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
1007 1.1 christos { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI },
1008 1.1 christos { NULL, NULL, 0 }
1009 1.1 christos };
1010 1.1 christos
1011 1.1 christos /*%
1012 1.1 christos * Clauses that can occur in the bind.keys file.
1013 1.1 christos */
1014 1.1 christos static cfg_clausedef_t
1015 1.1 christos bindkeys_clauses[] = {
1016 1.1 christos { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI },
1017 1.1 christos { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
1018 1.1 christos { NULL, NULL, 0 }
1019 1.1 christos };
1020 1.1 christos
1021 1.1 christos static const char *fstrm_model_enums[] = { "mpsc", "spsc", NULL };
1022 1.1 christos static cfg_type_t cfg_type_fstrm_model = {
1023 1.1 christos "model", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
1024 1.1 christos &cfg_rep_string, &fstrm_model_enums
1025 1.1 christos };
1026 1.1 christos
1027 1.1 christos /*%
1028 1.1 christos * Clauses that can be found within the 'options' statement.
1029 1.1 christos */
1030 1.1 christos static cfg_clausedef_t
1031 1.1 christos options_clauses[] = {
1032 1.1 christos { "answer-cookie", &cfg_type_boolean, 0 },
1033 1.1 christos { "automatic-interface-scan", &cfg_type_boolean, 0 },
1034 1.1 christos { "avoid-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
1035 1.1 christos { "avoid-v6-udp-ports", &cfg_type_bracketed_portlist, 0 },
1036 1.1 christos { "bindkeys-file", &cfg_type_qstring, 0 },
1037 1.1 christos { "blackhole", &cfg_type_bracketed_aml, 0 },
1038 1.1 christos { "cookie-algorithm", &cfg_type_cookiealg, 0 },
1039 1.1 christos { "cookie-secret", &cfg_type_sstring, CFG_CLAUSEFLAG_MULTI },
1040 1.1 christos { "coresize", &cfg_type_size, 0 },
1041 1.1 christos { "datasize", &cfg_type_size, 0 },
1042 1.1 christos { "deallocate-on-exit", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
1043 1.1 christos { "directory", &cfg_type_qstring, CFG_CLAUSEFLAG_CALLBACK },
1044 1.1 christos #ifdef HAVE_DNSTAP
1045 1.1 christos { "dnstap-output", &cfg_type_dnstapoutput, 0 },
1046 1.1 christos { "dnstap-identity", &cfg_type_serverid, 0 },
1047 1.1 christos { "dnstap-version", &cfg_type_qstringornone, 0 },
1048 1.1 christos #else
1049 1.1 christos { "dnstap-output", &cfg_type_dnstapoutput,
1050 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1051 1.1 christos { "dnstap-identity", &cfg_type_serverid,
1052 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1053 1.1 christos { "dnstap-version", &cfg_type_qstringornone,
1054 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1055 1.1 christos #endif
1056 1.1 christos { "dscp", &cfg_type_uint32, 0 },
1057 1.1 christos { "dump-file", &cfg_type_qstring, 0 },
1058 1.1 christos { "fake-iquery", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
1059 1.1 christos { "files", &cfg_type_size, 0 },
1060 1.1 christos { "flush-zones-on-shutdown", &cfg_type_boolean, 0 },
1061 1.1 christos #ifdef HAVE_DNSTAP
1062 1.1 christos { "fstrm-set-buffer-hint", &cfg_type_uint32, 0 },
1063 1.1 christos { "fstrm-set-flush-timeout", &cfg_type_uint32, 0 },
1064 1.1 christos { "fstrm-set-input-queue-size", &cfg_type_uint32, 0 },
1065 1.1 christos { "fstrm-set-output-notify-threshold", &cfg_type_uint32, 0 },
1066 1.1 christos { "fstrm-set-output-queue-model", &cfg_type_fstrm_model, 0 },
1067 1.1 christos { "fstrm-set-output-queue-size", &cfg_type_uint32, 0 },
1068 1.1 christos { "fstrm-set-reopen-interval", &cfg_type_uint32, 0 },
1069 1.1 christos #else
1070 1.1 christos { "fstrm-set-buffer-hint", &cfg_type_uint32,
1071 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1072 1.1 christos { "fstrm-set-flush-timeout", &cfg_type_uint32,
1073 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1074 1.1 christos { "fstrm-set-input-queue-size", &cfg_type_uint32,
1075 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1076 1.1 christos { "fstrm-set-output-notify-threshold", &cfg_type_uint32,
1077 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1078 1.1 christos { "fstrm-set-output-queue-model", &cfg_type_fstrm_model,
1079 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1080 1.1 christos { "fstrm-set-output-queue-size", &cfg_type_uint32,
1081 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1082 1.1 christos { "fstrm-set-reopen-interval", &cfg_type_uint32,
1083 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1084 1.1 christos #endif /* HAVE_DNSTAP */
1085 1.1 christos #ifdef HAVE_GEOIP
1086 1.1 christos { "geoip-directory", &cfg_type_qstringornone, 0 },
1087 1.1 christos { "geoip-use-ecs", &cfg_type_boolean, 0 },
1088 1.1 christos #else
1089 1.1 christos { "geoip-directory", &cfg_type_qstringornone,
1090 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1091 1.1 christos { "geoip-use-ecs", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTCONFIGURED },
1092 1.1 christos #endif /* HAVE_GEOIP */
1093 1.1 christos { "has-old-clients", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
1094 1.1 christos { "heartbeat-interval", &cfg_type_uint32, 0 },
1095 1.1 christos { "host-statistics", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTIMP },
1096 1.1 christos { "host-statistics-max", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
1097 1.1 christos { "hostname", &cfg_type_qstringornone, 0 },
1098 1.1 christos { "interface-interval", &cfg_type_uint32, 0 },
1099 1.1 christos { "keep-response-order", &cfg_type_bracketed_aml, 0 },
1100 1.1 christos { "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
1101 1.1 christos { "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
1102 1.1 christos { "lock-file", &cfg_type_qstringornone, 0 },
1103 1.1 christos { "managed-keys-directory", &cfg_type_qstring, 0 },
1104 1.1 christos { "match-mapped-addresses", &cfg_type_boolean, 0 },
1105 1.1 christos { "max-rsa-exponent-size", &cfg_type_uint32, 0 },
1106 1.1 christos { "memstatistics", &cfg_type_boolean, 0 },
1107 1.1 christos { "memstatistics-file", &cfg_type_qstring, 0 },
1108 1.1 christos { "multiple-cnames", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
1109 1.1 christos { "named-xfer", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
1110 1.1 christos { "notify-rate", &cfg_type_uint32, 0 },
1111 1.1 christos { "pid-file", &cfg_type_qstringornone, 0 },
1112 1.1 christos { "port", &cfg_type_uint32, 0 },
1113 1.1 christos { "querylog", &cfg_type_boolean, 0 },
1114 1.1 christos { "random-device", &cfg_type_qstringornone, 0 },
1115 1.1 christos { "recursing-file", &cfg_type_qstring, 0 },
1116 1.1 christos { "recursive-clients", &cfg_type_uint32, 0 },
1117 1.1 christos { "reserved-sockets", &cfg_type_uint32, 0 },
1118 1.1 christos { "secroots-file", &cfg_type_qstring, 0 },
1119 1.1 christos { "serial-queries", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
1120 1.1 christos { "serial-query-rate", &cfg_type_uint32, 0 },
1121 1.1 christos { "server-id", &cfg_type_serverid, 0 },
1122 1.1 christos { "session-keyalg", &cfg_type_astring, 0 },
1123 1.1 christos { "session-keyfile", &cfg_type_qstringornone, 0 },
1124 1.1 christos { "session-keyname", &cfg_type_astring, 0 },
1125 1.1 christos { "sit-secret", &cfg_type_sstring, CFG_CLAUSEFLAG_OBSOLETE },
1126 1.1 christos { "stacksize", &cfg_type_size, 0 },
1127 1.1 christos { "startup-notify-rate", &cfg_type_uint32, 0 },
1128 1.1 christos { "statistics-file", &cfg_type_qstring, 0 },
1129 1.1 christos { "statistics-interval", &cfg_type_uint32, CFG_CLAUSEFLAG_NYI },
1130 1.1 christos { "tcp-advertised-timeout", &cfg_type_uint32, 0 },
1131 1.1 christos { "tcp-clients", &cfg_type_uint32, 0 },
1132 1.1 christos { "tcp-idle-timeout", &cfg_type_uint32, 0 },
1133 1.1 christos { "tcp-initial-timeout", &cfg_type_uint32, 0 },
1134 1.1 christos { "tcp-keepalive-timeout", &cfg_type_uint32, 0 },
1135 1.1 christos { "tcp-listen-queue", &cfg_type_uint32, 0 },
1136 1.1 christos { "tkey-dhkey", &cfg_type_tkey_dhkey, 0 },
1137 1.1 christos { "tkey-domain", &cfg_type_qstring, 0 },
1138 1.1 christos { "tkey-gssapi-credential", &cfg_type_qstring, 0 },
1139 1.1 christos { "tkey-gssapi-keytab", &cfg_type_qstring, 0 },
1140 1.1 christos { "transfer-message-size", &cfg_type_uint32, 0 },
1141 1.1 christos { "transfers-in", &cfg_type_uint32, 0 },
1142 1.1 christos { "transfers-out", &cfg_type_uint32, 0 },
1143 1.1 christos { "transfers-per-ns", &cfg_type_uint32, 0 },
1144 1.1 christos { "treat-cr-as-space", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
1145 1.1 christos { "use-id-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
1146 1.1 christos { "use-ixfr", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
1147 1.1 christos { "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
1148 1.1 christos { "use-v6-udp-ports", &cfg_type_bracketed_portlist, 0 },
1149 1.1 christos { "version", &cfg_type_qstringornone, 0 },
1150 1.1 christos { NULL, NULL, 0 }
1151 1.1 christos };
1152 1.1 christos
1153 1.1 christos static cfg_type_t cfg_type_namelist = {
1154 1.1 christos "namelist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
1155 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_qstring
1156 1.1 christos };
1157 1.1 christos
1158 1.1 christos static keyword_type_t exclude_kw = { "exclude", &cfg_type_namelist };
1159 1.1 christos
1160 1.1 christos static cfg_type_t cfg_type_optional_exclude = {
1161 1.1 christos "optional_exclude", parse_optional_keyvalue, print_keyvalue,
1162 1.1 christos doc_optional_keyvalue, &cfg_rep_list, &exclude_kw
1163 1.1 christos };
1164 1.1 christos
1165 1.1 christos static keyword_type_t exceptionnames_kw = {
1166 1.1 christos "except-from", &cfg_type_namelist
1167 1.1 christos };
1168 1.1 christos
1169 1.1 christos static cfg_type_t cfg_type_optional_exceptionnames = {
1170 1.1 christos "optional_allow", parse_optional_keyvalue, print_keyvalue,
1171 1.1 christos doc_optional_keyvalue, &cfg_rep_list, &exceptionnames_kw
1172 1.1 christos };
1173 1.1 christos
1174 1.1 christos static cfg_tuplefielddef_t denyaddresses_fields[] = {
1175 1.1 christos { "acl", &cfg_type_bracketed_aml, 0 },
1176 1.1 christos { "except-from", &cfg_type_optional_exceptionnames, 0 },
1177 1.1 christos { NULL, NULL, 0 }
1178 1.1 christos };
1179 1.1 christos
1180 1.1 christos static cfg_type_t cfg_type_denyaddresses = {
1181 1.1 christos "denyaddresses", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
1182 1.1 christos &cfg_rep_tuple, denyaddresses_fields
1183 1.1 christos };
1184 1.1 christos
1185 1.1 christos static cfg_tuplefielddef_t denyaliases_fields[] = {
1186 1.1 christos { "name", &cfg_type_namelist, 0 },
1187 1.1 christos { "except-from", &cfg_type_optional_exceptionnames, 0 },
1188 1.1 christos { NULL, NULL, 0 }
1189 1.1 christos };
1190 1.1 christos
1191 1.1 christos static cfg_type_t cfg_type_denyaliases = {
1192 1.1 christos "denyaliases", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
1193 1.1 christos &cfg_rep_tuple, denyaliases_fields
1194 1.1 christos };
1195 1.1 christos
1196 1.1 christos static cfg_type_t cfg_type_algorithmlist = {
1197 1.1 christos "algorithmlist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
1198 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring
1199 1.1 christos };
1200 1.1 christos
1201 1.1 christos static cfg_tuplefielddef_t disablealgorithm_fields[] = {
1202 1.1 christos { "name", &cfg_type_astring, 0 },
1203 1.1 christos { "algorithms", &cfg_type_algorithmlist, 0 },
1204 1.1 christos { NULL, NULL, 0 }
1205 1.1 christos };
1206 1.1 christos
1207 1.1 christos static cfg_type_t cfg_type_disablealgorithm = {
1208 1.1 christos "disablealgorithm", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
1209 1.1 christos &cfg_rep_tuple, disablealgorithm_fields
1210 1.1 christos };
1211 1.1 christos
1212 1.1 christos static cfg_type_t cfg_type_dsdigestlist = {
1213 1.1 christos "dsdigestlist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
1214 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring
1215 1.1 christos };
1216 1.1 christos
1217 1.1 christos static cfg_tuplefielddef_t disabledsdigest_fields[] = {
1218 1.1 christos { "name", &cfg_type_astring, 0 },
1219 1.1 christos { "digests", &cfg_type_dsdigestlist, 0 },
1220 1.1 christos { NULL, NULL, 0 }
1221 1.1 christos };
1222 1.1 christos
1223 1.1 christos static cfg_type_t cfg_type_disabledsdigest = {
1224 1.1 christos "disabledsdigest", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
1225 1.1 christos &cfg_rep_tuple, disabledsdigest_fields
1226 1.1 christos };
1227 1.1 christos
1228 1.1 christos static cfg_tuplefielddef_t mustbesecure_fields[] = {
1229 1.1 christos { "name", &cfg_type_astring, 0 },
1230 1.1 christos { "value", &cfg_type_boolean, 0 },
1231 1.1 christos { NULL, NULL, 0 }
1232 1.1 christos };
1233 1.1 christos
1234 1.1 christos static cfg_type_t cfg_type_mustbesecure = {
1235 1.1 christos "mustbesecure", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
1236 1.1 christos &cfg_rep_tuple, mustbesecure_fields
1237 1.1 christos };
1238 1.1 christos
1239 1.1 christos static const char *masterformat_enums[] = { "map", "raw", "text", NULL };
1240 1.1 christos static cfg_type_t cfg_type_masterformat = {
1241 1.1 christos "masterformat", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
1242 1.1 christos &cfg_rep_string, &masterformat_enums
1243 1.1 christos };
1244 1.1 christos
1245 1.1 christos static const char *masterstyle_enums[] = { "full", "relative", NULL };
1246 1.1 christos static cfg_type_t cfg_type_masterstyle = {
1247 1.1 christos "masterstyle", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
1248 1.1 christos &cfg_rep_string, &masterstyle_enums
1249 1.1 christos };
1250 1.1 christos
1251 1.1 christos static keyword_type_t blocksize_kw = { "block-size", &cfg_type_uint32 };
1252 1.1 christos
1253 1.1 christos static cfg_type_t cfg_type_blocksize = {
1254 1.1 christos "blocksize", parse_keyvalue, print_keyvalue,
1255 1.1 christos doc_keyvalue, &cfg_rep_uint32, &blocksize_kw
1256 1.1 christos };
1257 1.1 christos
1258 1.1 christos static cfg_tuplefielddef_t resppadding_fields[] = {
1259 1.1 christos { "acl", &cfg_type_bracketed_aml, 0 },
1260 1.1 christos { "block-size", &cfg_type_blocksize, 0 },
1261 1.1 christos { NULL, NULL, 0 }
1262 1.1 christos };
1263 1.1 christos
1264 1.1 christos static cfg_type_t cfg_type_resppadding = {
1265 1.1 christos "resppadding", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
1266 1.1 christos &cfg_rep_tuple, resppadding_fields
1267 1.1 christos };
1268 1.1 christos
1269 1.1 christos /*%
1270 1.1 christos * dnstap {
1271 1.1 christos * <message type> [query | response] ;
1272 1.1 christos * ...
1273 1.1 christos * }
1274 1.1 christos *
1275 1.1 christos * ... where message type is one of: client, resolver, auth, forwarder, all
1276 1.1 christos */
1277 1.1 christos static const char *dnstap_types[] = {
1278 1.1 christos "all", "auth", "client", "forwarder", "resolver", NULL
1279 1.1 christos };
1280 1.1 christos
1281 1.1 christos static const char *dnstap_modes[] = { "query", "response", NULL };
1282 1.1 christos
1283 1.1 christos static cfg_type_t cfg_type_dnstap_type = {
1284 1.1 christos "dnstap_type", cfg_parse_enum, cfg_print_ustring,
1285 1.1 christos cfg_doc_enum, &cfg_rep_string, dnstap_types
1286 1.1 christos };
1287 1.1 christos
1288 1.1 christos static cfg_type_t cfg_type_dnstap_mode = {
1289 1.1 christos "dnstap_mode", parse_optional_enum, cfg_print_ustring,
1290 1.1 christos doc_optional_enum, &cfg_rep_string, dnstap_modes
1291 1.1 christos };
1292 1.1 christos
1293 1.1 christos static cfg_tuplefielddef_t dnstap_fields[] = {
1294 1.1 christos { "type", &cfg_type_dnstap_type, 0 },
1295 1.1 christos { "mode", &cfg_type_dnstap_mode, 0 },
1296 1.1 christos { NULL, NULL, 0 }
1297 1.1 christos };
1298 1.1 christos
1299 1.1 christos static cfg_type_t cfg_type_dnstap_entry = {
1300 1.1 christos "dnstap_value", cfg_parse_tuple, cfg_print_tuple,
1301 1.1 christos cfg_doc_tuple, &cfg_rep_tuple, dnstap_fields
1302 1.1 christos };
1303 1.1 christos
1304 1.1 christos static cfg_type_t cfg_type_dnstap = {
1305 1.1 christos "dnstap", cfg_parse_bracketed_list, cfg_print_bracketed_list,
1306 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_dnstap_entry
1307 1.1 christos };
1308 1.1 christos
1309 1.1 christos /*%
1310 1.1 christos * dnstap-output
1311 1.1 christos */
1312 1.1 christos static isc_result_t
1313 1.1 christos parse_dtout(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
1314 1.1 christos isc_result_t result;
1315 1.1 christos cfg_obj_t *obj = NULL;
1316 1.1 christos const cfg_tuplefielddef_t *fields = type->of;
1317 1.1 christos
1318 1.1 christos CHECK(cfg_create_tuple(pctx, type, &obj));
1319 1.1 christos
1320 1.1 christos /* Parse the mandatory "mode" and "path" fields */
1321 1.1 christos CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
1322 1.1 christos CHECK(cfg_parse_obj(pctx, fields[1].type, &obj->value.tuple[1]));
1323 1.1 christos
1324 1.1 christos /* Parse "versions" and "size" fields in any order. */
1325 1.1 christos for (;;) {
1326 1.1 christos CHECK(cfg_peektoken(pctx, 0));
1327 1.1 christos if (pctx->token.type == isc_tokentype_string) {
1328 1.1 christos CHECK(cfg_gettoken(pctx, 0));
1329 1.1 christos if (strcasecmp(TOKEN_STRING(pctx),
1330 1.1 christos "size") == 0 &&
1331 1.1 christos obj->value.tuple[2] == NULL)
1332 1.1 christos {
1333 1.1 christos CHECK(cfg_parse_obj(pctx, fields[2].type,
1334 1.1 christos &obj->value.tuple[2]));
1335 1.1 christos } else if (strcasecmp(TOKEN_STRING(pctx),
1336 1.1 christos "versions") == 0 &&
1337 1.1 christos obj->value.tuple[3] == NULL)
1338 1.1 christos {
1339 1.1 christos CHECK(cfg_parse_obj(pctx, fields[3].type,
1340 1.1 christos &obj->value.tuple[3]));
1341 1.1 christos } else if (strcasecmp(TOKEN_STRING(pctx),
1342 1.1 christos "suffix") == 0 &&
1343 1.1 christos obj->value.tuple[4] == NULL) {
1344 1.1 christos CHECK(cfg_parse_obj(pctx, fields[4].type,
1345 1.1 christos &obj->value.tuple[4]));
1346 1.1 christos } else {
1347 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR,
1348 1.1 christos "unexpected token");
1349 1.1 christos result = ISC_R_UNEXPECTEDTOKEN;
1350 1.1 christos goto cleanup;
1351 1.1 christos }
1352 1.1 christos } else {
1353 1.1 christos break;
1354 1.1 christos }
1355 1.1 christos }
1356 1.1 christos
1357 1.1 christos /* Create void objects for missing optional values. */
1358 1.1 christos if (obj->value.tuple[2] == NULL)
1359 1.1 christos CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[2]));
1360 1.1 christos if (obj->value.tuple[3] == NULL)
1361 1.1 christos CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[3]));
1362 1.1 christos if (obj->value.tuple[4] == NULL)
1363 1.1 christos CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[4]));
1364 1.1 christos
1365 1.1 christos *ret = obj;
1366 1.1 christos return (ISC_R_SUCCESS);
1367 1.1 christos
1368 1.1 christos cleanup:
1369 1.1 christos CLEANUP_OBJ(obj);
1370 1.1 christos return (result);
1371 1.1 christos }
1372 1.1 christos
1373 1.1 christos static void
1374 1.1 christos print_dtout(cfg_printer_t *pctx, const cfg_obj_t *obj) {
1375 1.1 christos cfg_print_obj(pctx, obj->value.tuple[0]); /* mode */
1376 1.1 christos cfg_print_obj(pctx, obj->value.tuple[1]); /* file */
1377 1.1 christos if (obj->value.tuple[2]->type->print != cfg_print_void) {
1378 1.1 christos cfg_print_cstr(pctx, " size ");
1379 1.1 christos cfg_print_obj(pctx, obj->value.tuple[2]);
1380 1.1 christos }
1381 1.1 christos if (obj->value.tuple[3]->type->print != cfg_print_void) {
1382 1.1 christos cfg_print_cstr(pctx, " versions ");
1383 1.1 christos cfg_print_obj(pctx, obj->value.tuple[3]);
1384 1.1 christos }
1385 1.1 christos if (obj->value.tuple[4]->type->print != cfg_print_void) {
1386 1.1 christos cfg_print_cstr(pctx, " suffix ");
1387 1.1 christos cfg_print_obj(pctx, obj->value.tuple[4]);
1388 1.1 christos }
1389 1.1 christos }
1390 1.1 christos
1391 1.1 christos
1392 1.1 christos static void
1393 1.1 christos doc_dtout(cfg_printer_t *pctx, const cfg_type_t *type) {
1394 1.1 christos UNUSED(type);
1395 1.1 christos cfg_print_cstr(pctx, "( file | unix ) <quoted_string>");
1396 1.1 christos cfg_print_cstr(pctx, " ");
1397 1.1 christos cfg_print_cstr(pctx, "[ size ( unlimited | <size> ) ]");
1398 1.1 christos cfg_print_cstr(pctx, " ");
1399 1.1 christos cfg_print_cstr(pctx, "[ versions ( unlimited | <integer> ) ]");
1400 1.1 christos cfg_print_cstr(pctx, " ");
1401 1.1 christos cfg_print_cstr(pctx, "[ suffix ( increment | timestamp ) ]");
1402 1.1 christos }
1403 1.1 christos
1404 1.1 christos static const char *dtoutmode_enums[] = { "file", "unix", NULL };
1405 1.1 christos static cfg_type_t cfg_type_dtmode = {
1406 1.1 christos "dtmode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
1407 1.1 christos &cfg_rep_string, &dtoutmode_enums
1408 1.1 christos };
1409 1.1 christos
1410 1.1 christos static cfg_tuplefielddef_t dtout_fields[] = {
1411 1.1 christos { "mode", &cfg_type_dtmode, 0 },
1412 1.1 christos { "path", &cfg_type_qstring, 0 },
1413 1.1 christos { "size", &cfg_type_sizenodefault, 0 },
1414 1.1 christos { "versions", &cfg_type_logversions, 0 },
1415 1.1 christos { "suffix", &cfg_type_logsuffix, 0 },
1416 1.1 christos { NULL, NULL, 0 }
1417 1.1 christos };
1418 1.1 christos
1419 1.1 christos static cfg_type_t cfg_type_dnstapoutput = {
1420 1.1 christos "dnstapoutput", parse_dtout, print_dtout, doc_dtout,
1421 1.1 christos &cfg_rep_tuple, dtout_fields
1422 1.1 christos };
1423 1.1 christos
1424 1.1 christos /*%
1425 1.1 christos * response-policy {
1426 1.1 christos * zone <string> [ policy (given|disabled|passthru|drop|tcp-only|
1427 1.1 christos * nxdomain|nodata|cname <domain> ) ]
1428 1.1 christos * [ recursive-only yes|no ] [ log yes|no ]
1429 1.1 christos * [ max-policy-ttl number ]
1430 1.1 christos * [ nsip-enable yes|no ] [ nsdname-enable yes|no ];
1431 1.1 christos * } [ recursive-only yes|no ] [ max-policy-ttl number ]
1432 1.1 christos * [ min-update-interval number ]
1433 1.1 christos * [ break-dnssec yes|no ] [ min-ns-dots number ]
1434 1.1 christos * [ qname-wait-recurse yes|no ]
1435 1.1 christos * [ nsip-enable yes|no ] [ nsdname-enable yes|no ]
1436 1.1 christos * [ dnsrps-enable yes|no ]
1437 1.1 christos * [ dnsrps-options { DNSRPS configuration string } ];
1438 1.1 christos */
1439 1.1 christos
1440 1.1 christos static void
1441 1.1 christos doc_rpz_policy(cfg_printer_t *pctx, const cfg_type_t *type) {
1442 1.1 christos const char * const *p;
1443 1.1 christos /*
1444 1.1 christos * This is cfg_doc_enum() without the trailing " )".
1445 1.1 christos */
1446 1.1 christos cfg_print_cstr(pctx, "( ");
1447 1.1 christos for (p = type->of; *p != NULL; p++) {
1448 1.1 christos cfg_print_cstr(pctx, *p);
1449 1.1 christos if (p[1] != NULL)
1450 1.1 christos cfg_print_cstr(pctx, " | ");
1451 1.1 christos }
1452 1.1 christos }
1453 1.1 christos
1454 1.1 christos static void
1455 1.1 christos doc_rpz_cname(cfg_printer_t *pctx, const cfg_type_t *type) {
1456 1.1 christos cfg_doc_terminal(pctx, type);
1457 1.1 christos cfg_print_cstr(pctx, " )");
1458 1.1 christos }
1459 1.1 christos
1460 1.1 christos /*
1461 1.1 christos * Parse
1462 1.1 christos * given|disabled|passthru|drop|tcp-only|nxdomain|nodata|cname <domain>
1463 1.1 christos */
1464 1.1 christos static isc_result_t
1465 1.1 christos cfg_parse_rpz_policy(cfg_parser_t *pctx, const cfg_type_t *type,
1466 1.1 christos cfg_obj_t **ret)
1467 1.1 christos {
1468 1.1 christos isc_result_t result;
1469 1.1 christos cfg_obj_t *obj = NULL;
1470 1.1 christos const cfg_tuplefielddef_t *fields;
1471 1.1 christos
1472 1.1 christos CHECK(cfg_create_tuple(pctx, type, &obj));
1473 1.1 christos
1474 1.1 christos fields = type->of;
1475 1.1 christos CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
1476 1.1 christos /*
1477 1.1 christos * parse cname domain only after "policy cname"
1478 1.1 christos */
1479 1.1 christos if (strcasecmp("cname", cfg_obj_asstring(obj->value.tuple[0])) != 0) {
1480 1.1 christos CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[1]));
1481 1.1 christos } else {
1482 1.1 christos CHECK(cfg_parse_obj(pctx, fields[1].type,
1483 1.1 christos &obj->value.tuple[1]));
1484 1.1 christos }
1485 1.1 christos
1486 1.1 christos *ret = obj;
1487 1.1 christos return (ISC_R_SUCCESS);
1488 1.1 christos
1489 1.1 christos cleanup:
1490 1.1 christos CLEANUP_OBJ(obj);
1491 1.1 christos return (result);
1492 1.1 christos }
1493 1.1 christos
1494 1.1 christos /*
1495 1.1 christos * Parse a tuple consisting of any kind of required field followed
1496 1.1 christos * by 2 or more optional keyvalues that can be in any order.
1497 1.1 christos */
1498 1.1 christos static isc_result_t
1499 1.1 christos cfg_parse_kv_tuple(cfg_parser_t *pctx, const cfg_type_t *type,
1500 1.1 christos cfg_obj_t **ret)
1501 1.1 christos {
1502 1.1 christos const cfg_tuplefielddef_t *fields, *f;
1503 1.1 christos cfg_obj_t *obj = NULL;
1504 1.1 christos int fn;
1505 1.1 christos isc_result_t result;
1506 1.1 christos
1507 1.1 christos CHECK(cfg_create_tuple(pctx, type, &obj));
1508 1.1 christos
1509 1.1 christos /*
1510 1.1 christos * The zone first field is required and always first.
1511 1.1 christos */
1512 1.1 christos fields = type->of;
1513 1.1 christos CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
1514 1.1 christos
1515 1.1 christos for (;;) {
1516 1.1 christos CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
1517 1.1 christos if (pctx->token.type != isc_tokentype_string)
1518 1.1 christos break;
1519 1.1 christos
1520 1.1 christos for (fn = 1, f = &fields[1]; ; ++fn, ++f) {
1521 1.1 christos if (f->name == NULL) {
1522 1.1 christos cfg_parser_error(pctx, 0, "unexpected '%s'",
1523 1.1 christos TOKEN_STRING(pctx));
1524 1.1 christos result = ISC_R_UNEXPECTEDTOKEN;
1525 1.1 christos goto cleanup;
1526 1.1 christos }
1527 1.1 christos if (obj->value.tuple[fn] == NULL &&
1528 1.1 christos strcasecmp(f->name, TOKEN_STRING(pctx)) == 0)
1529 1.1 christos break;
1530 1.1 christos }
1531 1.1 christos
1532 1.1 christos CHECK(cfg_gettoken(pctx, 0));
1533 1.1 christos CHECK(cfg_parse_obj(pctx, f->type, &obj->value.tuple[fn]));
1534 1.1 christos }
1535 1.1 christos
1536 1.1 christos for (fn = 1, f = &fields[1]; f->name != NULL; ++fn, ++f) {
1537 1.1 christos if (obj->value.tuple[fn] == NULL)
1538 1.1 christos CHECK(cfg_parse_void(pctx, NULL,
1539 1.1 christos &obj->value.tuple[fn]));
1540 1.1 christos }
1541 1.1 christos
1542 1.1 christos *ret = obj;
1543 1.1 christos return (ISC_R_SUCCESS);
1544 1.1 christos
1545 1.1 christos cleanup:
1546 1.1 christos CLEANUP_OBJ(obj);
1547 1.1 christos return (result);
1548 1.1 christos }
1549 1.1 christos
1550 1.1 christos static void
1551 1.1 christos cfg_print_kv_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
1552 1.1 christos unsigned int i;
1553 1.1 christos const cfg_tuplefielddef_t *fields, *f;
1554 1.1 christos const cfg_obj_t *fieldobj;
1555 1.1 christos
1556 1.1 christos fields = obj->type->of;
1557 1.1 christos for (f = fields, i = 0; f->name != NULL; f++, i++) {
1558 1.1 christos fieldobj = obj->value.tuple[i];
1559 1.1 christos if (fieldobj->type->print == cfg_print_void)
1560 1.1 christos continue;
1561 1.1 christos if (i != 0) {
1562 1.1 christos cfg_print_cstr(pctx, " ");
1563 1.1 christos cfg_print_cstr(pctx, f->name);
1564 1.1 christos cfg_print_cstr(pctx, " ");
1565 1.1 christos }
1566 1.1 christos cfg_print_obj(pctx, fieldobj);
1567 1.1 christos }
1568 1.1 christos }
1569 1.1 christos
1570 1.1 christos static void
1571 1.1 christos cfg_doc_kv_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
1572 1.1 christos const cfg_tuplefielddef_t *fields, *f;
1573 1.1 christos
1574 1.1 christos fields = type->of;
1575 1.1 christos for (f = fields; f->name != NULL; f++) {
1576 1.1 christos if (f != fields) {
1577 1.1 christos cfg_print_cstr(pctx, " [ ");
1578 1.1 christos cfg_print_cstr(pctx, f->name);
1579 1.1 christos if (f->type->doc != cfg_doc_void)
1580 1.1 christos cfg_print_cstr(pctx, " ");
1581 1.1 christos }
1582 1.1 christos cfg_doc_obj(pctx, f->type);
1583 1.1 christos if (f != fields)
1584 1.1 christos cfg_print_cstr(pctx, " ]");
1585 1.1 christos }
1586 1.1 christos }
1587 1.1 christos
1588 1.1 christos static keyword_type_t zone_kw = {"zone", &cfg_type_qstring};
1589 1.1 christos static cfg_type_t cfg_type_rpz_zone = {
1590 1.1 christos "zone", parse_keyvalue, print_keyvalue,
1591 1.1 christos doc_keyvalue, &cfg_rep_string,
1592 1.1 christos &zone_kw
1593 1.1 christos };
1594 1.1 christos /*
1595 1.1 christos * "no-op" is an obsolete equivalent of "passthru".
1596 1.1 christos */
1597 1.1 christos static const char *rpz_policies[] = {
1598 1.1 christos "cname", "disabled", "drop", "given", "no-op", "nodata",
1599 1.1 christos "nxdomain", "passthru", "tcp-only", NULL
1600 1.1 christos };
1601 1.1 christos static cfg_type_t cfg_type_rpz_policy_name = {
1602 1.1 christos "policy name", cfg_parse_enum, cfg_print_ustring,
1603 1.1 christos doc_rpz_policy, &cfg_rep_string,
1604 1.1 christos &rpz_policies
1605 1.1 christos };
1606 1.1 christos static cfg_type_t cfg_type_rpz_cname = {
1607 1.1 christos "quoted_string", cfg_parse_astring, NULL,
1608 1.1 christos doc_rpz_cname, &cfg_rep_string,
1609 1.1 christos NULL
1610 1.1 christos };
1611 1.1 christos static cfg_tuplefielddef_t rpz_policy_fields[] = {
1612 1.1 christos { "policy name", &cfg_type_rpz_policy_name, 0 },
1613 1.1 christos { "cname", &cfg_type_rpz_cname, 0 },
1614 1.1 christos { NULL, NULL, 0 }
1615 1.1 christos };
1616 1.1 christos static cfg_type_t cfg_type_rpz_policy = {
1617 1.1 christos "policy tuple", cfg_parse_rpz_policy,
1618 1.1 christos cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
1619 1.1 christos rpz_policy_fields
1620 1.1 christos };
1621 1.1 christos static cfg_tuplefielddef_t rpz_zone_fields[] = {
1622 1.1 christos { "zone name", &cfg_type_rpz_zone, 0 },
1623 1.1 christos { "log", &cfg_type_boolean, 0 },
1624 1.1 christos { "max-policy-ttl", &cfg_type_uint32, 0 },
1625 1.1 christos { "min-update-interval", &cfg_type_uint32, 0 },
1626 1.1 christos { "policy", &cfg_type_rpz_policy, 0 },
1627 1.1 christos { "recursive-only", &cfg_type_boolean, 0 },
1628 1.1 christos { "nsip-enable", &cfg_type_boolean, 0 },
1629 1.1 christos { "nsdname-enable", &cfg_type_boolean, 0 },
1630 1.1 christos { NULL, NULL, 0 }
1631 1.1 christos };
1632 1.1 christos static cfg_type_t cfg_type_rpz_tuple = {
1633 1.1 christos "rpz tuple", cfg_parse_kv_tuple,
1634 1.1 christos cfg_print_kv_tuple, cfg_doc_kv_tuple, &cfg_rep_tuple,
1635 1.1 christos rpz_zone_fields
1636 1.1 christos };
1637 1.1 christos static cfg_type_t cfg_type_rpz_list = {
1638 1.1 christos "zone list", cfg_parse_bracketed_list, cfg_print_bracketed_list,
1639 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list,
1640 1.1 christos &cfg_type_rpz_tuple
1641 1.1 christos };
1642 1.1 christos static cfg_tuplefielddef_t rpz_fields[] = {
1643 1.1 christos { "zone list", &cfg_type_rpz_list, 0 },
1644 1.1 christos { "break-dnssec", &cfg_type_boolean, 0 },
1645 1.1 christos { "max-policy-ttl", &cfg_type_uint32, 0 },
1646 1.1 christos { "min-update-interval", &cfg_type_uint32, 0 },
1647 1.1 christos { "min-ns-dots", &cfg_type_uint32, 0 },
1648 1.1 christos { "nsip-wait-recurse", &cfg_type_boolean, 0 },
1649 1.1 christos { "qname-wait-recurse", &cfg_type_boolean, 0 },
1650 1.1 christos { "recursive-only", &cfg_type_boolean, 0 },
1651 1.1 christos { "nsip-enable", &cfg_type_boolean, 0 },
1652 1.1 christos { "nsdname-enable", &cfg_type_boolean, 0 },
1653 1.1 christos #ifdef USE_DNSRPS
1654 1.1 christos { "dnsrps-enable", &cfg_type_boolean, 0 },
1655 1.1 christos { "dnsrps-options", &cfg_type_bracketed_text, 0 },
1656 1.1 christos #else
1657 1.1 christos { "dnsrps-enable", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTCONFIGURED },
1658 1.1 christos { "dnsrps-options", &cfg_type_bracketed_text,
1659 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1660 1.1 christos #endif
1661 1.1 christos { NULL, NULL, 0 }
1662 1.1 christos };
1663 1.1 christos static cfg_type_t cfg_type_rpz = {
1664 1.1 christos "rpz", cfg_parse_kv_tuple,
1665 1.1 christos cfg_print_kv_tuple, cfg_doc_kv_tuple, &cfg_rep_tuple,
1666 1.1 christos rpz_fields
1667 1.1 christos };
1668 1.1 christos
1669 1.1 christos /*
1670 1.1 christos * Catalog zones
1671 1.1 christos */
1672 1.1 christos static cfg_type_t cfg_type_catz_zone = {
1673 1.1 christos "zone", parse_keyvalue, print_keyvalue,
1674 1.1 christos doc_keyvalue, &cfg_rep_string,
1675 1.1 christos &zone_kw
1676 1.1 christos };
1677 1.1 christos
1678 1.1 christos static cfg_tuplefielddef_t catz_zone_fields[] = {
1679 1.1 christos { "zone name", &cfg_type_catz_zone, 0 },
1680 1.1 christos { "default-masters", &cfg_type_namesockaddrkeylist, 0 },
1681 1.1 christos { "zone-directory", &cfg_type_qstring, 0 },
1682 1.1 christos { "in-memory", &cfg_type_boolean, 0 },
1683 1.1 christos { "min-update-interval", &cfg_type_uint32, 0 },
1684 1.1 christos { NULL, NULL, 0 }
1685 1.1 christos };
1686 1.1 christos static cfg_type_t cfg_type_catz_tuple = {
1687 1.1 christos "catz tuple", cfg_parse_kv_tuple,
1688 1.1 christos cfg_print_kv_tuple, cfg_doc_kv_tuple, &cfg_rep_tuple,
1689 1.1 christos catz_zone_fields
1690 1.1 christos };
1691 1.1 christos static cfg_type_t cfg_type_catz_list = {
1692 1.1 christos "zone list", cfg_parse_bracketed_list, cfg_print_bracketed_list,
1693 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list,
1694 1.1 christos &cfg_type_catz_tuple
1695 1.1 christos };
1696 1.1 christos static cfg_tuplefielddef_t catz_fields[] = {
1697 1.1 christos { "zone list", &cfg_type_catz_list, 0 },
1698 1.1 christos { NULL, NULL, 0 }
1699 1.1 christos };
1700 1.1 christos static cfg_type_t cfg_type_catz = {
1701 1.1 christos "catz", cfg_parse_kv_tuple, cfg_print_kv_tuple,
1702 1.1 christos cfg_doc_kv_tuple, &cfg_rep_tuple, catz_fields
1703 1.1 christos };
1704 1.1 christos
1705 1.1 christos /*
1706 1.1 christos * rate-limit
1707 1.1 christos */
1708 1.1 christos static cfg_clausedef_t rrl_clauses[] = {
1709 1.1 christos { "all-per-second", &cfg_type_uint32, 0 },
1710 1.1 christos { "errors-per-second", &cfg_type_uint32, 0 },
1711 1.1 christos { "exempt-clients", &cfg_type_bracketed_aml, 0 },
1712 1.1 christos { "ipv4-prefix-length", &cfg_type_uint32, 0 },
1713 1.1 christos { "ipv6-prefix-length", &cfg_type_uint32, 0 },
1714 1.1 christos { "log-only", &cfg_type_boolean, 0 },
1715 1.1 christos { "max-table-size", &cfg_type_uint32, 0 },
1716 1.1 christos { "min-table-size", &cfg_type_uint32, 0 },
1717 1.1 christos { "nodata-per-second", &cfg_type_uint32, 0 },
1718 1.1 christos { "nxdomains-per-second", &cfg_type_uint32, 0 },
1719 1.1 christos { "qps-scale", &cfg_type_uint32, 0 },
1720 1.1 christos { "referrals-per-second", &cfg_type_uint32, 0 },
1721 1.1 christos { "responses-per-second", &cfg_type_uint32, 0 },
1722 1.1 christos { "slip", &cfg_type_uint32, 0 },
1723 1.1 christos { "window", &cfg_type_uint32, 0 },
1724 1.1 christos { NULL, NULL, 0 }
1725 1.1 christos };
1726 1.1 christos
1727 1.1 christos static cfg_clausedef_t *rrl_clausesets[] = {
1728 1.1 christos rrl_clauses, NULL
1729 1.1 christos };
1730 1.1 christos
1731 1.1 christos static cfg_type_t cfg_type_rrl = {
1732 1.1 christos "rate-limit", cfg_parse_map, cfg_print_map, cfg_doc_map,
1733 1.1 christos &cfg_rep_map, rrl_clausesets
1734 1.1 christos };
1735 1.1 christos
1736 1.1 christos /*%
1737 1.1 christos * dnssec-lookaside
1738 1.1 christos */
1739 1.1 christos
1740 1.1 christos static void
1741 1.1 christos print_lookaside(cfg_printer_t *pctx, const cfg_obj_t *obj) {
1742 1.1 christos const cfg_obj_t *domain = obj->value.tuple[0];
1743 1.1 christos
1744 1.1 christos if (domain->value.string.length == 4 &&
1745 1.1 christos strncmp(domain->value.string.base, "auto", 4) == 0)
1746 1.1 christos cfg_print_cstr(pctx, "auto");
1747 1.1 christos else
1748 1.1 christos cfg_print_tuple(pctx, obj);
1749 1.1 christos }
1750 1.1 christos
1751 1.1 christos static void
1752 1.1 christos doc_lookaside(cfg_printer_t *pctx, const cfg_type_t *type) {
1753 1.1 christos UNUSED(type);
1754 1.1 christos cfg_print_cstr(pctx, "( <string> trust-anchor <string> | auto | no )");
1755 1.1 christos }
1756 1.1 christos
1757 1.1 christos static keyword_type_t trustanchor_kw = { "trust-anchor", &cfg_type_astring };
1758 1.1 christos
1759 1.1 christos static cfg_type_t cfg_type_optional_trustanchor = {
1760 1.1 christos "optional_trustanchor", parse_optional_keyvalue, print_keyvalue,
1761 1.1 christos doc_keyvalue, &cfg_rep_string, &trustanchor_kw
1762 1.1 christos };
1763 1.1 christos
1764 1.1 christos static cfg_tuplefielddef_t lookaside_fields[] = {
1765 1.1 christos { "domain", &cfg_type_astring, 0 },
1766 1.1 christos { "trust-anchor", &cfg_type_optional_trustanchor, 0 },
1767 1.1 christos { NULL, NULL, 0 }
1768 1.1 christos };
1769 1.1 christos
1770 1.1 christos static cfg_type_t cfg_type_lookaside = {
1771 1.1 christos "lookaside", cfg_parse_tuple, print_lookaside, doc_lookaside,
1772 1.1 christos &cfg_rep_tuple, lookaside_fields
1773 1.1 christos };
1774 1.1 christos
1775 1.1 christos static isc_result_t
1776 1.1 christos parse_optional_uint32(cfg_parser_t *pctx, const cfg_type_t *type,
1777 1.1 christos cfg_obj_t **ret)
1778 1.1 christos {
1779 1.1 christos isc_result_t result;
1780 1.1 christos UNUSED(type);
1781 1.1 christos
1782 1.1 christos CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
1783 1.1 christos if (pctx->token.type == isc_tokentype_number) {
1784 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_uint32, ret));
1785 1.1 christos } else {
1786 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
1787 1.1 christos }
1788 1.1 christos cleanup:
1789 1.1 christos return (result);
1790 1.1 christos }
1791 1.1 christos
1792 1.1 christos static void
1793 1.1 christos doc_optional_uint32(cfg_printer_t *pctx, const cfg_type_t *type) {
1794 1.1 christos UNUSED(type);
1795 1.1 christos cfg_print_cstr(pctx, "[ <integer> ]");
1796 1.1 christos }
1797 1.1 christos
1798 1.1 christos static cfg_type_t cfg_type_optional_uint32 = {
1799 1.1 christos "optional_uint32", parse_optional_uint32, NULL, doc_optional_uint32,
1800 1.1 christos NULL, NULL
1801 1.1 christos };
1802 1.1 christos
1803 1.1 christos static cfg_tuplefielddef_t prefetch_fields[] = {
1804 1.1 christos { "trigger", &cfg_type_uint32, 0 },
1805 1.1 christos { "eligible", &cfg_type_optional_uint32, 0 },
1806 1.1 christos { NULL, NULL, 0 }
1807 1.1 christos };
1808 1.1 christos
1809 1.1 christos static cfg_type_t cfg_type_prefetch = {
1810 1.1 christos "prefetch", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
1811 1.1 christos &cfg_rep_tuple, prefetch_fields
1812 1.1 christos };
1813 1.1 christos /*
1814 1.1 christos * DNS64.
1815 1.1 christos */
1816 1.1 christos static cfg_clausedef_t
1817 1.1 christos dns64_clauses[] = {
1818 1.1 christos { "break-dnssec", &cfg_type_boolean, 0 },
1819 1.1 christos { "clients", &cfg_type_bracketed_aml, 0 },
1820 1.1 christos { "exclude", &cfg_type_bracketed_aml, 0 },
1821 1.1 christos { "mapped", &cfg_type_bracketed_aml, 0 },
1822 1.1 christos { "recursive-only", &cfg_type_boolean, 0 },
1823 1.1 christos { "suffix", &cfg_type_netaddr6, 0 },
1824 1.1 christos { NULL, NULL, 0 },
1825 1.1 christos };
1826 1.1 christos
1827 1.1 christos static cfg_clausedef_t *
1828 1.1 christos dns64_clausesets[] = {
1829 1.1 christos dns64_clauses,
1830 1.1 christos NULL
1831 1.1 christos };
1832 1.1 christos
1833 1.1 christos static cfg_type_t cfg_type_dns64 = {
1834 1.1 christos "dns64", cfg_parse_netprefix_map, cfg_print_map, cfg_doc_map,
1835 1.1 christos &cfg_rep_map, dns64_clausesets
1836 1.1 christos };
1837 1.1 christos
1838 1.1 christos /*%
1839 1.1 christos * Clauses that can be found within the 'view' statement,
1840 1.1 christos * with defaults in the 'options' statement.
1841 1.1 christos */
1842 1.1 christos
1843 1.1 christos static cfg_clausedef_t
1844 1.1 christos view_clauses[] = {
1845 1.1 christos { "acache-cleaning-interval", &cfg_type_uint32,
1846 1.1 christos CFG_CLAUSEFLAG_OBSOLETE },
1847 1.1 christos { "acache-enable", &cfg_type_boolean,
1848 1.1 christos CFG_CLAUSEFLAG_OBSOLETE },
1849 1.1 christos { "additional-from-auth", &cfg_type_boolean,
1850 1.1 christos CFG_CLAUSEFLAG_OBSOLETE },
1851 1.1 christos { "additional-from-cache", &cfg_type_boolean,
1852 1.1 christos CFG_CLAUSEFLAG_OBSOLETE },
1853 1.1 christos { "allow-new-zones", &cfg_type_boolean, 0 },
1854 1.1 christos { "allow-query-cache", &cfg_type_bracketed_aml, 0 },
1855 1.1 christos { "allow-query-cache-on", &cfg_type_bracketed_aml, 0 },
1856 1.1 christos { "allow-recursion", &cfg_type_bracketed_aml, 0 },
1857 1.1 christos { "allow-recursion-on", &cfg_type_bracketed_aml, 0 },
1858 1.1 christos { "allow-v6-synthesis", &cfg_type_bracketed_aml,
1859 1.1 christos CFG_CLAUSEFLAG_OBSOLETE },
1860 1.1 christos { "attach-cache", &cfg_type_astring, 0 },
1861 1.1 christos { "auth-nxdomain", &cfg_type_boolean, CFG_CLAUSEFLAG_NEWDEFAULT },
1862 1.1 christos { "cache-file", &cfg_type_qstring, 0 },
1863 1.1 christos { "catalog-zones", &cfg_type_catz, 0 },
1864 1.1 christos { "check-names", &cfg_type_checknames, CFG_CLAUSEFLAG_MULTI },
1865 1.1 christos { "cleaning-interval", &cfg_type_uint32, 0 },
1866 1.1 christos { "clients-per-query", &cfg_type_uint32, 0 },
1867 1.1 christos { "deny-answer-addresses", &cfg_type_denyaddresses, 0 },
1868 1.1 christos { "deny-answer-aliases", &cfg_type_denyaliases, 0 },
1869 1.1 christos { "disable-algorithms", &cfg_type_disablealgorithm,
1870 1.1 christos CFG_CLAUSEFLAG_MULTI },
1871 1.1 christos { "disable-ds-digests", &cfg_type_disabledsdigest,
1872 1.1 christos CFG_CLAUSEFLAG_MULTI },
1873 1.1 christos { "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
1874 1.1 christos { "dns64", &cfg_type_dns64, CFG_CLAUSEFLAG_MULTI },
1875 1.1 christos { "dns64-contact", &cfg_type_astring, 0 },
1876 1.1 christos { "dns64-server", &cfg_type_astring, 0 },
1877 1.1 christos #ifdef USE_DNSRPS
1878 1.1 christos { "dnsrps-enable", &cfg_type_boolean, 0 },
1879 1.1 christos { "dnsrps-options", &cfg_type_bracketed_text, 0 },
1880 1.1 christos #else
1881 1.1 christos { "dnsrps-enable", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTCONFIGURED },
1882 1.1 christos { "dnsrps-options", &cfg_type_bracketed_text,
1883 1.1 christos CFG_CLAUSEFLAG_NOTCONFIGURED },
1884 1.1 christos #endif
1885 1.1 christos { "dnssec-accept-expired", &cfg_type_boolean, 0 },
1886 1.1 christos { "dnssec-enable", &cfg_type_boolean, 0 },
1887 1.1 christos { "dnssec-lookaside", &cfg_type_lookaside, CFG_CLAUSEFLAG_MULTI },
1888 1.1 christos { "dnssec-must-be-secure", &cfg_type_mustbesecure,
1889 1.1 christos CFG_CLAUSEFLAG_MULTI },
1890 1.1 christos { "dnssec-validation", &cfg_type_boolorauto, 0 },
1891 1.1 christos #ifdef HAVE_DNSTAP
1892 1.1 christos { "dnstap", &cfg_type_dnstap, 0 },
1893 1.1 christos #else
1894 1.1 christos { "dnstap", &cfg_type_dnstap, CFG_CLAUSEFLAG_NOTCONFIGURED },
1895 1.1 christos #endif /* HAVE_DNSTAP */
1896 1.1 christos { "dual-stack-servers", &cfg_type_nameportiplist, 0 },
1897 1.1 christos { "edns-udp-size", &cfg_type_uint32, 0 },
1898 1.1 christos { "empty-contact", &cfg_type_astring, 0 },
1899 1.1 christos { "empty-server", &cfg_type_astring, 0 },
1900 1.1 christos { "empty-zones-enable", &cfg_type_boolean, 0 },
1901 1.1 christos { "fetch-glue", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
1902 1.1 christos { "fetch-quota-params", &cfg_type_fetchquota, 0 },
1903 1.1 christos { "fetches-per-server", &cfg_type_fetchesper, 0 },
1904 1.1 christos { "fetches-per-zone", &cfg_type_fetchesper, 0 },
1905 1.1 christos { "filter-aaaa", &cfg_type_bracketed_aml, 0 },
1906 1.1 christos { "filter-aaaa-on-v4", &cfg_type_filter_aaaa, 0 },
1907 1.1 christos { "filter-aaaa-on-v6", &cfg_type_filter_aaaa, 0 },
1908 1.1 christos { "glue-cache", &cfg_type_boolean, 0 },
1909 1.1 christos { "ixfr-from-differences", &cfg_type_ixfrdifftype, 0 },
1910 1.1 christos { "lame-ttl", &cfg_type_ttlval, 0 },
1911 1.1 christos #ifdef HAVE_LMDB
1912 1.1 christos { "lmdb-mapsize", &cfg_type_sizeval, 0 },
1913 1.1 christos #else
1914 1.1 christos { "lmdb-mapsize", &cfg_type_sizeval, CFG_CLAUSEFLAG_NOOP },
1915 1.1 christos #endif
1916 1.1 christos { "max-acache-size", &cfg_type_sizenodefault,
1917 1.1 christos CFG_CLAUSEFLAG_OBSOLETE },
1918 1.1 christos { "max-cache-size", &cfg_type_sizeorpercent, 0 },
1919 1.1 christos { "max-cache-ttl", &cfg_type_uint32, 0 },
1920 1.1 christos { "max-clients-per-query", &cfg_type_uint32, 0 },
1921 1.1 christos { "max-ncache-ttl", &cfg_type_uint32, 0 },
1922 1.1 christos { "max-recursion-depth", &cfg_type_uint32, 0 },
1923 1.1 christos { "max-recursion-queries", &cfg_type_uint32, 0 },
1924 1.1 christos { "max-stale-ttl", &cfg_type_ttlval, 0 },
1925 1.1 christos { "max-udp-size", &cfg_type_uint32, 0 },
1926 1.1 christos { "message-compression", &cfg_type_boolean, 0 },
1927 1.1 christos { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
1928 1.1 christos { "minimal-any", &cfg_type_boolean, 0 },
1929 1.1 christos { "minimal-responses", &cfg_type_minimal, 0 },
1930 1.1 christos { "new-zones-directory", &cfg_type_qstring, 0 },
1931 1.1 christos { "no-case-compress", &cfg_type_bracketed_aml, 0 },
1932 1.1 christos { "nocookie-udp-size", &cfg_type_uint32, 0 },
1933 1.1 christos { "nosit-udp-size", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
1934 1.1 christos { "nta-lifetime", &cfg_type_ttlval, 0 },
1935 1.1 christos { "nta-recheck", &cfg_type_ttlval, 0 },
1936 1.1 christos { "nxdomain-redirect", &cfg_type_astring, 0 },
1937 1.1 christos { "preferred-glue", &cfg_type_astring, 0 },
1938 1.1 christos { "prefetch", &cfg_type_prefetch, 0 },
1939 1.1 christos { "provide-ixfr", &cfg_type_boolean, 0 },
1940 1.1 christos /*
1941 1.1 christos * Note that the query-source option syntax is different
1942 1.1 christos * from the other -source options.
1943 1.1 christos */
1944 1.1 christos { "query-source", &cfg_type_querysource4, 0 },
1945 1.1 christos { "query-source-v6", &cfg_type_querysource6, 0 },
1946 1.1 christos { "queryport-pool-ports", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
1947 1.1 christos { "queryport-pool-updateinterval", &cfg_type_uint32,
1948 1.1 christos CFG_CLAUSEFLAG_OBSOLETE },
1949 1.1 christos { "rate-limit", &cfg_type_rrl, 0 },
1950 1.1 christos { "recursion", &cfg_type_boolean, 0 },
1951 1.1 christos { "request-nsid", &cfg_type_boolean, 0 },
1952 1.1 christos { "request-sit", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
1953 1.1 christos { "require-server-cookie", &cfg_type_boolean, 0 },
1954 1.1 christos { "resolver-nonbackoff-tries", &cfg_type_uint32, 0 },
1955 1.1 christos { "resolver-query-timeout", &cfg_type_uint32, 0 },
1956 1.1 christos { "resolver-retry-interval", &cfg_type_uint32, 0 },
1957 1.1 christos { "response-padding", &cfg_type_resppadding, 0 },
1958 1.1 christos { "response-policy", &cfg_type_rpz, 0 },
1959 1.1 christos { "rfc2308-type1", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
1960 1.1 christos { "root-delegation-only", &cfg_type_optional_exclude, 0 },
1961 1.1 christos { "root-key-sentinel", &cfg_type_boolean, 0 },
1962 1.1 christos { "rrset-order", &cfg_type_rrsetorder, 0 },
1963 1.1 christos { "send-cookie", &cfg_type_boolean, 0 },
1964 1.1 christos { "servfail-ttl", &cfg_type_ttlval, 0 },
1965 1.1 christos { "sortlist", &cfg_type_bracketed_aml, 0 },
1966 1.1 christos { "stale-answer-enable", &cfg_type_boolean, 0 },
1967 1.1 christos { "stale-answer-ttl", &cfg_type_ttlval, 0 },
1968 1.1 christos { "suppress-initial-notify", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
1969 1.1 christos { "synth-from-dnssec", &cfg_type_boolean, 0 },
1970 1.1 christos { "topology", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_NOTIMP },
1971 1.1 christos { "transfer-format", &cfg_type_transferformat, 0 },
1972 1.1 christos { "trust-anchor-telemetry", &cfg_type_boolean,
1973 1.1 christos CFG_CLAUSEFLAG_EXPERIMENTAL },
1974 1.1 christos { "use-queryport-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
1975 1.1 christos { "v6-bias", &cfg_type_uint32, 0 },
1976 1.1 christos { "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 },
1977 1.1 christos { NULL, NULL, 0 }
1978 1.1 christos };
1979 1.1 christos
1980 1.1 christos /*%
1981 1.1 christos * Clauses that can be found within the 'view' statement only.
1982 1.1 christos */
1983 1.1 christos static cfg_clausedef_t
1984 1.1 christos view_only_clauses[] = {
1985 1.1 christos { "match-clients", &cfg_type_bracketed_aml, 0 },
1986 1.1 christos { "match-destinations", &cfg_type_bracketed_aml, 0 },
1987 1.1 christos { "match-recursive-only", &cfg_type_boolean, 0 },
1988 1.1 christos { NULL, NULL, 0 }
1989 1.1 christos };
1990 1.1 christos
1991 1.1 christos /*%
1992 1.1 christos * Sig-validity-interval.
1993 1.1 christos */
1994 1.1 christos
1995 1.1 christos static cfg_tuplefielddef_t validityinterval_fields[] = {
1996 1.1 christos { "validity", &cfg_type_uint32, 0 },
1997 1.1 christos { "re-sign", &cfg_type_optional_uint32, 0 },
1998 1.1 christos { NULL, NULL, 0 }
1999 1.1 christos };
2000 1.1 christos
2001 1.1 christos static cfg_type_t cfg_type_validityinterval = {
2002 1.1 christos "validityinterval", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
2003 1.1 christos &cfg_rep_tuple, validityinterval_fields
2004 1.1 christos };
2005 1.1 christos
2006 1.1 christos /*%
2007 1.1 christos * Clauses that can be found in a 'zone' statement,
2008 1.1 christos * with defaults in the 'view' or 'options' statement.
2009 1.1 christos *
2010 1.1 christos * Note: CFG_ZONE_* options indicate in which zone types this clause is
2011 1.1 christos * legal.
2012 1.1 christos */
2013 1.1 christos static cfg_clausedef_t
2014 1.1 christos zone_clauses[] = {
2015 1.1 christos { "allow-notify", &cfg_type_bracketed_aml,
2016 1.1 christos CFG_ZONE_SLAVE
2017 1.1 christos },
2018 1.1 christos { "allow-query", &cfg_type_bracketed_aml,
2019 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB |
2020 1.1 christos CFG_ZONE_REDIRECT | CFG_ZONE_STATICSTUB
2021 1.1 christos },
2022 1.1 christos { "allow-query-on", &cfg_type_bracketed_aml,
2023 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB |
2024 1.1 christos CFG_ZONE_REDIRECT | CFG_ZONE_STATICSTUB
2025 1.1 christos },
2026 1.1 christos { "allow-transfer", &cfg_type_bracketed_aml,
2027 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2028 1.1 christos },
2029 1.1 christos { "allow-update", &cfg_type_bracketed_aml,
2030 1.1 christos CFG_ZONE_MASTER
2031 1.1 christos },
2032 1.1 christos { "allow-update-forwarding", &cfg_type_bracketed_aml,
2033 1.1 christos CFG_ZONE_SLAVE
2034 1.1 christos },
2035 1.1 christos { "also-notify", &cfg_type_namesockaddrkeylist,
2036 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2037 1.1 christos },
2038 1.1 christos { "alt-transfer-source", &cfg_type_sockaddr4wild,
2039 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2040 1.1 christos },
2041 1.1 christos { "alt-transfer-source-v6", &cfg_type_sockaddr6wild,
2042 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2043 1.1 christos },
2044 1.1 christos { "auto-dnssec", &cfg_type_autodnssec,
2045 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2046 1.1 christos },
2047 1.1 christos { "check-dup-records", &cfg_type_checkmode,
2048 1.1 christos CFG_ZONE_MASTER
2049 1.1 christos },
2050 1.1 christos { "check-integrity", &cfg_type_boolean,
2051 1.1 christos CFG_ZONE_MASTER
2052 1.1 christos },
2053 1.1 christos { "check-mx", &cfg_type_checkmode,
2054 1.1 christos CFG_ZONE_MASTER
2055 1.1 christos },
2056 1.1 christos { "check-mx-cname", &cfg_type_checkmode,
2057 1.1 christos CFG_ZONE_MASTER
2058 1.1 christos },
2059 1.1 christos { "check-sibling", &cfg_type_boolean,
2060 1.1 christos CFG_ZONE_MASTER
2061 1.1 christos },
2062 1.1 christos { "check-spf", &cfg_type_warn,
2063 1.1 christos CFG_ZONE_MASTER
2064 1.1 christos },
2065 1.1 christos { "check-srv-cname", &cfg_type_checkmode,
2066 1.1 christos CFG_ZONE_MASTER
2067 1.1 christos },
2068 1.1 christos { "check-wildcard", &cfg_type_boolean,
2069 1.1 christos CFG_ZONE_MASTER
2070 1.1 christos },
2071 1.1 christos { "dialup", &cfg_type_dialuptype,
2072 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB
2073 1.1 christos },
2074 1.1 christos { "dnssec-dnskey-kskonly", &cfg_type_boolean,
2075 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2076 1.1 christos },
2077 1.1 christos { "dnssec-loadkeys-interval", &cfg_type_uint32,
2078 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2079 1.1 christos },
2080 1.1 christos { "dnssec-secure-to-insecure", &cfg_type_boolean,
2081 1.1 christos CFG_ZONE_MASTER
2082 1.1 christos },
2083 1.1 christos { "dnssec-update-mode", &cfg_type_dnssecupdatemode,
2084 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2085 1.1 christos },
2086 1.1 christos { "forward", &cfg_type_forwardtype,
2087 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB |
2088 1.1 christos CFG_ZONE_STATICSTUB | CFG_ZONE_FORWARD
2089 1.1 christos },
2090 1.1 christos { "forwarders", &cfg_type_portiplist,
2091 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB |
2092 1.1 christos CFG_ZONE_STATICSTUB | CFG_ZONE_FORWARD
2093 1.1 christos },
2094 1.1 christos { "inline-signing", &cfg_type_boolean,
2095 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2096 1.1 christos },
2097 1.1 christos { "key-directory", &cfg_type_qstring,
2098 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2099 1.1 christos },
2100 1.1 christos { "maintain-ixfr-base", &cfg_type_boolean,
2101 1.1 christos CFG_CLAUSEFLAG_OBSOLETE
2102 1.1 christos },
2103 1.1 christos { "masterfile-format", &cfg_type_masterformat,
2104 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE |
2105 1.1 christos CFG_ZONE_STUB | CFG_ZONE_REDIRECT
2106 1.1 christos },
2107 1.1 christos { "masterfile-style", &cfg_type_masterstyle,
2108 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE |
2109 1.1 christos CFG_ZONE_STUB | CFG_ZONE_REDIRECT
2110 1.1 christos },
2111 1.1 christos { "max-ixfr-log-size", &cfg_type_size,
2112 1.1 christos CFG_CLAUSEFLAG_OBSOLETE
2113 1.1 christos },
2114 1.1 christos { "max-journal-size", &cfg_type_size,
2115 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2116 1.1 christos },
2117 1.1 christos { "max-records", &cfg_type_uint32,
2118 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB |
2119 1.1 christos CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT
2120 1.1 christos },
2121 1.1 christos { "max-refresh-time", &cfg_type_uint32,
2122 1.1 christos CFG_ZONE_SLAVE | CFG_ZONE_STUB
2123 1.1 christos },
2124 1.1 christos { "max-retry-time", &cfg_type_uint32,
2125 1.1 christos CFG_ZONE_SLAVE | CFG_ZONE_STUB
2126 1.1 christos },
2127 1.1 christos { "max-transfer-idle-in", &cfg_type_uint32,
2128 1.1 christos CFG_ZONE_SLAVE | CFG_ZONE_STUB
2129 1.1 christos },
2130 1.1 christos { "max-transfer-idle-out", &cfg_type_uint32,
2131 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2132 1.1 christos },
2133 1.1 christos { "max-transfer-time-in", &cfg_type_uint32,
2134 1.1 christos CFG_ZONE_SLAVE | CFG_ZONE_STUB
2135 1.1 christos },
2136 1.1 christos { "max-transfer-time-out", &cfg_type_uint32,
2137 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2138 1.1 christos },
2139 1.1 christos { "max-zone-ttl", &cfg_type_maxttl,
2140 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_REDIRECT
2141 1.1 christos },
2142 1.1 christos { "min-refresh-time", &cfg_type_uint32,
2143 1.1 christos CFG_ZONE_SLAVE | CFG_ZONE_STUB
2144 1.1 christos },
2145 1.1 christos { "min-retry-time", &cfg_type_uint32,
2146 1.1 christos CFG_ZONE_SLAVE | CFG_ZONE_STUB
2147 1.1 christos },
2148 1.1 christos { "multi-master", &cfg_type_boolean,
2149 1.1 christos CFG_ZONE_SLAVE | CFG_ZONE_STUB
2150 1.1 christos },
2151 1.1 christos { "notify", &cfg_type_notifytype,
2152 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2153 1.1 christos },
2154 1.1 christos { "notify-delay", &cfg_type_uint32,
2155 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2156 1.1 christos },
2157 1.1 christos { "notify-source", &cfg_type_sockaddr4wild,
2158 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2159 1.1 christos },
2160 1.1 christos { "notify-source-v6", &cfg_type_sockaddr6wild,
2161 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2162 1.1 christos },
2163 1.1 christos { "notify-to-soa", &cfg_type_boolean,
2164 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2165 1.1 christos },
2166 1.1 christos { "nsec3-test-zone", &cfg_type_boolean,
2167 1.1 christos CFG_CLAUSEFLAG_TESTONLY |
2168 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2169 1.1 christos },
2170 1.1 christos { "request-expire", &cfg_type_boolean,
2171 1.1 christos CFG_ZONE_SLAVE
2172 1.1 christos },
2173 1.1 christos { "request-ixfr", &cfg_type_boolean,
2174 1.1 christos CFG_ZONE_SLAVE
2175 1.1 christos },
2176 1.1 christos { "serial-update-method", &cfg_type_updatemethod,
2177 1.1 christos CFG_ZONE_MASTER
2178 1.1 christos },
2179 1.1 christos { "sig-signing-nodes", &cfg_type_uint32,
2180 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2181 1.1 christos },
2182 1.1 christos { "sig-signing-signatures", &cfg_type_uint32,
2183 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2184 1.1 christos },
2185 1.1 christos { "sig-signing-type", &cfg_type_uint32,
2186 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2187 1.1 christos },
2188 1.1 christos { "sig-validity-interval", &cfg_type_validityinterval,
2189 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2190 1.1 christos },
2191 1.1 christos { "transfer-source", &cfg_type_sockaddr4wild,
2192 1.1 christos CFG_ZONE_SLAVE | CFG_ZONE_STUB
2193 1.1 christos },
2194 1.1 christos { "transfer-source-v6", &cfg_type_sockaddr6wild,
2195 1.1 christos CFG_ZONE_SLAVE | CFG_ZONE_STUB
2196 1.1 christos },
2197 1.1 christos { "try-tcp-refresh", &cfg_type_boolean,
2198 1.1 christos CFG_ZONE_SLAVE
2199 1.1 christos },
2200 1.1 christos { "update-check-ksk", &cfg_type_boolean,
2201 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2202 1.1 christos },
2203 1.1 christos { "use-alt-transfer-source", &cfg_type_boolean,
2204 1.1 christos CFG_ZONE_SLAVE | CFG_ZONE_STUB
2205 1.1 christos },
2206 1.1 christos { "zero-no-soa-ttl", &cfg_type_boolean,
2207 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2208 1.1 christos },
2209 1.1 christos { "zone-statistics", &cfg_type_zonestat,
2210 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB |
2211 1.1 christos CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT
2212 1.1 christos },
2213 1.1 christos { NULL, NULL, 0 }
2214 1.1 christos };
2215 1.1 christos
2216 1.1 christos /*%
2217 1.1 christos * Clauses that can be found in a 'zone' statement only.
2218 1.1 christos *
2219 1.1 christos * Note: CFG_ZONE_* options indicate in which zone types this clause is
2220 1.1 christos * legal.
2221 1.1 christos */
2222 1.1 christos static cfg_clausedef_t
2223 1.1 christos zone_only_clauses[] = {
2224 1.1 christos /*
2225 1.1 christos * Note that the format of the check-names option is different between
2226 1.1 christos * the zone options and the global/view options. Ugh.
2227 1.1 christos */
2228 1.1 christos { "type", &cfg_type_zonetype,
2229 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB |
2230 1.1 christos CFG_ZONE_STATICSTUB | CFG_ZONE_DELEGATION | CFG_ZONE_HINT |
2231 1.1 christos CFG_ZONE_REDIRECT | CFG_ZONE_FORWARD
2232 1.1 christos },
2233 1.1 christos { "check-names", &cfg_type_checkmode,
2234 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE |
2235 1.1 christos CFG_ZONE_HINT | CFG_ZONE_STUB
2236 1.1 christos },
2237 1.1 christos { "database", &cfg_type_astring,
2238 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB
2239 1.1 christos },
2240 1.1 christos { "delegation-only", &cfg_type_boolean,
2241 1.1 christos CFG_ZONE_HINT | CFG_ZONE_STUB | CFG_ZONE_FORWARD
2242 1.1 christos },
2243 1.1 christos { "dlz", &cfg_type_astring,
2244 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_REDIRECT
2245 1.1 christos },
2246 1.1 christos { "file", &cfg_type_qstring,
2247 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB |
2248 1.1 christos CFG_ZONE_HINT | CFG_ZONE_REDIRECT
2249 1.1 christos },
2250 1.1 christos { "in-view", &cfg_type_astring,
2251 1.1 christos CFG_ZONE_INVIEW
2252 1.1 christos },
2253 1.1 christos { "ixfr-base", &cfg_type_qstring,
2254 1.1 christos CFG_CLAUSEFLAG_OBSOLETE
2255 1.1 christos },
2256 1.1 christos { "ixfr-from-differences", &cfg_type_boolean,
2257 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2258 1.1 christos },
2259 1.1 christos { "ixfr-tmp-file", &cfg_type_qstring,
2260 1.1 christos CFG_CLAUSEFLAG_OBSOLETE
2261 1.1 christos },
2262 1.1 christos { "journal", &cfg_type_qstring,
2263 1.1 christos CFG_ZONE_MASTER | CFG_ZONE_SLAVE
2264 1.1 christos },
2265 1.1 christos { "masters", &cfg_type_namesockaddrkeylist,
2266 1.1 christos CFG_ZONE_SLAVE | CFG_ZONE_STUB | CFG_ZONE_REDIRECT
2267 1.1 christos },
2268 1.1 christos { "pubkey", &cfg_type_pubkey,
2269 1.1 christos CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_OBSOLETE
2270 1.1 christos },
2271 1.1 christos { "server-addresses", &cfg_type_bracketed_sockaddrlist,
2272 1.1 christos CFG_ZONE_STATICSTUB
2273 1.1 christos },
2274 1.1 christos { "server-names", &cfg_type_namelist,
2275 1.1 christos CFG_ZONE_STATICSTUB
2276 1.1 christos },
2277 1.1 christos { "update-policy", &cfg_type_updatepolicy,
2278 1.1 christos CFG_ZONE_MASTER
2279 1.1 christos },
2280 1.1 christos { NULL, NULL, 0 }
2281 1.1 christos };
2282 1.1 christos
2283 1.1 christos /*% The top-level named.conf syntax. */
2284 1.1 christos
2285 1.1 christos static cfg_clausedef_t *
2286 1.1 christos namedconf_clausesets[] = {
2287 1.1 christos namedconf_clauses,
2288 1.1 christos namedconf_or_view_clauses,
2289 1.1 christos NULL
2290 1.1 christos };
2291 1.1 christos LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_namedconf = {
2292 1.1 christos "namedconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
2293 1.1 christos &cfg_rep_map, namedconf_clausesets
2294 1.1 christos };
2295 1.1 christos
2296 1.1 christos /*% The bind.keys syntax (trusted-keys/managed-keys only). */
2297 1.1 christos static cfg_clausedef_t *
2298 1.1 christos bindkeys_clausesets[] = {
2299 1.1 christos bindkeys_clauses,
2300 1.1 christos NULL
2301 1.1 christos };
2302 1.1 christos LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_bindkeys = {
2303 1.1 christos "bindkeys", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
2304 1.1 christos &cfg_rep_map, bindkeys_clausesets
2305 1.1 christos };
2306 1.1 christos
2307 1.1 christos /*% The "options" statement syntax. */
2308 1.1 christos
2309 1.1 christos static cfg_clausedef_t *
2310 1.1 christos options_clausesets[] = {
2311 1.1 christos options_clauses,
2312 1.1 christos view_clauses,
2313 1.1 christos zone_clauses,
2314 1.1 christos NULL
2315 1.1 christos };
2316 1.1 christos static cfg_type_t cfg_type_options = {
2317 1.1 christos "options", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map,
2318 1.1 christos options_clausesets
2319 1.1 christos };
2320 1.1 christos
2321 1.1 christos /*% The "view" statement syntax. */
2322 1.1 christos
2323 1.1 christos static cfg_clausedef_t *
2324 1.1 christos view_clausesets[] = {
2325 1.1 christos view_only_clauses,
2326 1.1 christos namedconf_or_view_clauses,
2327 1.1 christos view_clauses,
2328 1.1 christos zone_clauses,
2329 1.1 christos NULL
2330 1.1 christos };
2331 1.1 christos
2332 1.1 christos static cfg_type_t cfg_type_viewopts = {
2333 1.1 christos "view", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map,
2334 1.1 christos view_clausesets
2335 1.1 christos };
2336 1.1 christos
2337 1.1 christos /*% The "zone" statement syntax. */
2338 1.1 christos
2339 1.1 christos static cfg_clausedef_t *
2340 1.1 christos zone_clausesets[] = {
2341 1.1 christos zone_only_clauses,
2342 1.1 christos zone_clauses,
2343 1.1 christos NULL
2344 1.1 christos };
2345 1.1 christos LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_zoneopts = {
2346 1.1 christos "zoneopts", cfg_parse_map, cfg_print_map,
2347 1.1 christos cfg_doc_map, &cfg_rep_map, zone_clausesets };
2348 1.1 christos
2349 1.1 christos /*% The "dynamically loadable zones" statement syntax. */
2350 1.1 christos
2351 1.1 christos static cfg_clausedef_t
2352 1.1 christos dlz_clauses[] = {
2353 1.1 christos { "database", &cfg_type_astring, 0 },
2354 1.1 christos { "search", &cfg_type_boolean, 0 },
2355 1.1 christos { NULL, NULL, 0 }
2356 1.1 christos };
2357 1.1 christos static cfg_clausedef_t *
2358 1.1 christos dlz_clausesets[] = {
2359 1.1 christos dlz_clauses,
2360 1.1 christos NULL
2361 1.1 christos };
2362 1.1 christos static cfg_type_t cfg_type_dlz = {
2363 1.1 christos "dlz", cfg_parse_named_map, cfg_print_map, cfg_doc_map,
2364 1.1 christos &cfg_rep_map, dlz_clausesets
2365 1.1 christos };
2366 1.1 christos
2367 1.1 christos /*%
2368 1.1 christos * The "dyndb" statement syntax.
2369 1.1 christos */
2370 1.1 christos
2371 1.1 christos static cfg_tuplefielddef_t dyndb_fields[] = {
2372 1.1 christos { "name", &cfg_type_astring, 0 },
2373 1.1 christos { "library", &cfg_type_qstring, 0 },
2374 1.1 christos { "parameters", &cfg_type_bracketed_text, 0 },
2375 1.1 christos { NULL, NULL, 0 }
2376 1.1 christos };
2377 1.1 christos
2378 1.1 christos static cfg_type_t cfg_type_dyndb = {
2379 1.1 christos "dyndb", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
2380 1.1 christos &cfg_rep_tuple, dyndb_fields
2381 1.1 christos };
2382 1.1 christos
2383 1.1 christos /*%
2384 1.1 christos * Clauses that can be found within the 'key' statement.
2385 1.1 christos */
2386 1.1 christos static cfg_clausedef_t
2387 1.1 christos key_clauses[] = {
2388 1.1 christos { "algorithm", &cfg_type_astring, 0 },
2389 1.1 christos { "secret", &cfg_type_sstring, 0 },
2390 1.1 christos { NULL, NULL, 0 }
2391 1.1 christos };
2392 1.1 christos
2393 1.1 christos static cfg_clausedef_t *
2394 1.1 christos key_clausesets[] = {
2395 1.1 christos key_clauses,
2396 1.1 christos NULL
2397 1.1 christos };
2398 1.1 christos static cfg_type_t cfg_type_key = {
2399 1.1 christos "key", cfg_parse_named_map, cfg_print_map,
2400 1.1 christos cfg_doc_map, &cfg_rep_map, key_clausesets
2401 1.1 christos };
2402 1.1 christos
2403 1.1 christos
2404 1.1 christos /*%
2405 1.1 christos * Clauses that can be found in a 'server' statement.
2406 1.1 christos */
2407 1.1 christos static cfg_clausedef_t
2408 1.1 christos server_clauses[] = {
2409 1.1 christos { "bogus", &cfg_type_boolean, 0 },
2410 1.1 christos { "edns", &cfg_type_boolean, 0 },
2411 1.1 christos { "edns-udp-size", &cfg_type_uint32, 0 },
2412 1.1 christos { "edns-version", &cfg_type_uint32, 0 },
2413 1.1 christos { "keys", &cfg_type_server_key_kludge, 0 },
2414 1.1 christos { "max-udp-size", &cfg_type_uint32, 0 },
2415 1.1 christos { "notify-source", &cfg_type_sockaddr4wild, 0 },
2416 1.1 christos { "notify-source-v6", &cfg_type_sockaddr6wild, 0 },
2417 1.1 christos { "padding", &cfg_type_uint32, 0 },
2418 1.1 christos { "provide-ixfr", &cfg_type_boolean, 0 },
2419 1.1 christos { "query-source", &cfg_type_querysource4, 0 },
2420 1.1 christos { "query-source-v6", &cfg_type_querysource6, 0 },
2421 1.1 christos { "request-expire", &cfg_type_boolean, 0 },
2422 1.1 christos { "request-ixfr", &cfg_type_boolean, 0 },
2423 1.1 christos { "request-nsid", &cfg_type_boolean, 0 },
2424 1.1 christos { "request-sit", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
2425 1.1 christos { "send-cookie", &cfg_type_boolean, 0 },
2426 1.1 christos { "support-ixfr", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
2427 1.1 christos { "tcp-keepalive", &cfg_type_boolean, 0 },
2428 1.1 christos { "tcp-only", &cfg_type_boolean, 0 },
2429 1.1 christos { "transfer-format", &cfg_type_transferformat, 0 },
2430 1.1 christos { "transfer-source", &cfg_type_sockaddr4wild, 0 },
2431 1.1 christos { "transfer-source-v6", &cfg_type_sockaddr6wild, 0 },
2432 1.1 christos { "transfers", &cfg_type_uint32, 0 },
2433 1.1 christos { NULL, NULL, 0 }
2434 1.1 christos };
2435 1.1 christos static cfg_clausedef_t *
2436 1.1 christos server_clausesets[] = {
2437 1.1 christos server_clauses,
2438 1.1 christos NULL
2439 1.1 christos };
2440 1.1 christos static cfg_type_t cfg_type_server = {
2441 1.1 christos "server", cfg_parse_netprefix_map, cfg_print_map, cfg_doc_map,
2442 1.1 christos &cfg_rep_map, server_clausesets
2443 1.1 christos };
2444 1.1 christos
2445 1.1 christos /*%
2446 1.1 christos * Clauses that can be found in a 'channel' clause in the
2447 1.1 christos * 'logging' statement.
2448 1.1 christos *
2449 1.1 christos * These have some additional constraints that need to be
2450 1.1 christos * checked after parsing:
2451 1.1 christos * - There must exactly one of file/syslog/null/stderr
2452 1.1 christos */
2453 1.1 christos
2454 1.1 christos static const char *printtime_enums[] = {
2455 1.1 christos "iso8601", "iso8601-utc", "local", NULL
2456 1.1 christos };
2457 1.1 christos static isc_result_t
2458 1.1 christos parse_printtime(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
2459 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
2460 1.1 christos }
2461 1.1 christos static void
2462 1.1 christos doc_printtime(cfg_printer_t *pctx, const cfg_type_t *type) {
2463 1.1 christos doc_enum_or_other(pctx, type, &cfg_type_boolean);
2464 1.1 christos }
2465 1.1 christos static cfg_type_t cfg_type_printtime = {
2466 1.1 christos "printtime", parse_printtime, cfg_print_ustring, doc_printtime,
2467 1.1 christos &cfg_rep_string, printtime_enums
2468 1.1 christos };
2469 1.1 christos
2470 1.1 christos static cfg_clausedef_t
2471 1.1 christos channel_clauses[] = {
2472 1.1 christos /* Destinations. We no longer require these to be first. */
2473 1.1 christos { "file", &cfg_type_logfile, 0 },
2474 1.1 christos { "syslog", &cfg_type_optional_facility, 0 },
2475 1.1 christos { "null", &cfg_type_void, 0 },
2476 1.1 christos { "stderr", &cfg_type_void, 0 },
2477 1.1 christos /* Options. We now accept these for the null channel, too. */
2478 1.1 christos { "severity", &cfg_type_logseverity, 0 },
2479 1.1 christos { "print-time", &cfg_type_printtime, 0 },
2480 1.1 christos { "print-severity", &cfg_type_boolean, 0 },
2481 1.1 christos { "print-category", &cfg_type_boolean, 0 },
2482 1.1 christos { "buffered", &cfg_type_boolean, 0 },
2483 1.1 christos { NULL, NULL, 0 }
2484 1.1 christos };
2485 1.1 christos static cfg_clausedef_t *
2486 1.1 christos channel_clausesets[] = {
2487 1.1 christos channel_clauses,
2488 1.1 christos NULL
2489 1.1 christos };
2490 1.1 christos static cfg_type_t cfg_type_channel = {
2491 1.1 christos "channel", cfg_parse_named_map, cfg_print_map, cfg_doc_map,
2492 1.1 christos &cfg_rep_map, channel_clausesets
2493 1.1 christos };
2494 1.1 christos
2495 1.1 christos /*% A list of log destination, used in the "category" clause. */
2496 1.1 christos static cfg_type_t cfg_type_destinationlist = {
2497 1.1 christos "destinationlist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
2498 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring
2499 1.1 christos };
2500 1.1 christos
2501 1.1 christos /*%
2502 1.1 christos * Clauses that can be found in a 'logging' statement.
2503 1.1 christos */
2504 1.1 christos static cfg_clausedef_t logging_clauses[] = {
2505 1.1 christos { "channel", &cfg_type_channel, CFG_CLAUSEFLAG_MULTI },
2506 1.1 christos { "category", &cfg_type_category, CFG_CLAUSEFLAG_MULTI },
2507 1.1 christos { NULL, NULL, 0 }
2508 1.1 christos };
2509 1.1 christos static cfg_clausedef_t * logging_clausesets[] = {
2510 1.1 christos logging_clauses, NULL
2511 1.1 christos };
2512 1.1 christos static cfg_type_t cfg_type_logging = {
2513 1.1 christos "logging", cfg_parse_map, cfg_print_map, cfg_doc_map,
2514 1.1 christos &cfg_rep_map, logging_clausesets
2515 1.1 christos };
2516 1.1 christos
2517 1.1 christos /*%
2518 1.1 christos * For parsing an 'addzone' statement
2519 1.1 christos */
2520 1.1 christos static cfg_tuplefielddef_t addzone_fields[] = {
2521 1.1 christos { "name", &cfg_type_astring, 0 },
2522 1.1 christos { "class", &cfg_type_optional_class, 0 },
2523 1.1 christos { "view", &cfg_type_optional_class, 0 },
2524 1.1 christos { "options", &cfg_type_zoneopts, 0 },
2525 1.1 christos { NULL, NULL, 0 }
2526 1.1 christos };
2527 1.1 christos static cfg_type_t cfg_type_addzone = {
2528 1.1 christos "zone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
2529 1.1 christos &cfg_rep_tuple, addzone_fields
2530 1.1 christos };
2531 1.1 christos
2532 1.1 christos static cfg_clausedef_t
2533 1.1 christos addzoneconf_clauses[] = {
2534 1.1 christos { "zone", &cfg_type_addzone, CFG_CLAUSEFLAG_MULTI },
2535 1.1 christos { NULL, NULL, 0 }
2536 1.1 christos };
2537 1.1 christos
2538 1.1 christos static cfg_clausedef_t *
2539 1.1 christos addzoneconf_clausesets[] = {
2540 1.1 christos addzoneconf_clauses,
2541 1.1 christos NULL
2542 1.1 christos };
2543 1.1 christos
2544 1.1 christos LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_addzoneconf = {
2545 1.1 christos "addzoneconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
2546 1.1 christos &cfg_rep_map, addzoneconf_clausesets
2547 1.1 christos };
2548 1.1 christos
2549 1.1 christos static isc_result_t
2550 1.1 christos parse_unitstring(char *str, isc_resourcevalue_t *valuep) {
2551 1.1 christos char *endp;
2552 1.1 christos unsigned int len;
2553 1.1 christos isc_uint64_t value;
2554 1.1 christos isc_uint64_t unit;
2555 1.1 christos
2556 1.1 christos value = isc_string_touint64(str, &endp, 10);
2557 1.1 christos if (*endp == 0) {
2558 1.1 christos *valuep = value;
2559 1.1 christos return (ISC_R_SUCCESS);
2560 1.1 christos }
2561 1.1 christos
2562 1.1 christos len = strlen(str);
2563 1.1 christos if (len < 2 || endp[1] != '\0')
2564 1.1 christos return (ISC_R_FAILURE);
2565 1.1 christos
2566 1.1 christos switch (str[len - 1]) {
2567 1.1 christos case 'k':
2568 1.1 christos case 'K':
2569 1.1 christos unit = 1024;
2570 1.1 christos break;
2571 1.1 christos case 'm':
2572 1.1 christos case 'M':
2573 1.1 christos unit = 1024 * 1024;
2574 1.1 christos break;
2575 1.1 christos case 'g':
2576 1.1 christos case 'G':
2577 1.1 christos unit = 1024 * 1024 * 1024;
2578 1.1 christos break;
2579 1.1 christos default:
2580 1.1 christos return (ISC_R_FAILURE);
2581 1.1 christos }
2582 1.1 christos if (value > ISC_UINT64_MAX / unit)
2583 1.1 christos return (ISC_R_FAILURE);
2584 1.1 christos *valuep = value * unit;
2585 1.1 christos return (ISC_R_SUCCESS);
2586 1.1 christos }
2587 1.1 christos
2588 1.1 christos static isc_result_t
2589 1.1 christos parse_sizeval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
2590 1.1 christos isc_result_t result;
2591 1.1 christos cfg_obj_t *obj = NULL;
2592 1.1 christos isc_uint64_t val;
2593 1.1 christos
2594 1.1 christos UNUSED(type);
2595 1.1 christos
2596 1.1 christos CHECK(cfg_gettoken(pctx, 0));
2597 1.1 christos if (pctx->token.type != isc_tokentype_string) {
2598 1.1 christos result = ISC_R_UNEXPECTEDTOKEN;
2599 1.1 christos goto cleanup;
2600 1.1 christos }
2601 1.1 christos CHECK(parse_unitstring(TOKEN_STRING(pctx), &val));
2602 1.1 christos
2603 1.1 christos CHECK(cfg_create_obj(pctx, &cfg_type_uint64, &obj));
2604 1.1 christos obj->value.uint64 = val;
2605 1.1 christos *ret = obj;
2606 1.1 christos return (ISC_R_SUCCESS);
2607 1.1 christos
2608 1.1 christos cleanup:
2609 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR,
2610 1.1 christos "expected integer and optional unit");
2611 1.1 christos return (result);
2612 1.1 christos }
2613 1.1 christos
2614 1.1 christos static isc_result_t
2615 1.1 christos parse_sizeval_percent(cfg_parser_t *pctx, const cfg_type_t *type,
2616 1.1 christos cfg_obj_t **ret)
2617 1.1 christos {
2618 1.1 christos char *endp;
2619 1.1 christos isc_result_t result;
2620 1.1 christos cfg_obj_t *obj = NULL;
2621 1.1 christos isc_uint64_t val;
2622 1.1 christos isc_uint64_t percent;
2623 1.1 christos
2624 1.1 christos UNUSED(type);
2625 1.1 christos
2626 1.1 christos CHECK(cfg_gettoken(pctx, 0));
2627 1.1 christos if (pctx->token.type != isc_tokentype_string) {
2628 1.1 christos result = ISC_R_UNEXPECTEDTOKEN;
2629 1.1 christos goto cleanup;
2630 1.1 christos }
2631 1.1 christos
2632 1.1 christos percent = isc_string_touint64(TOKEN_STRING(pctx), &endp, 10);
2633 1.1 christos
2634 1.1 christos if (*endp == '%' && *(endp+1) == 0) {
2635 1.1 christos CHECK(cfg_create_obj(pctx, &cfg_type_percentage, &obj));
2636 1.1 christos obj->value.uint32 = (isc_uint32_t)percent;
2637 1.1 christos *ret = obj;
2638 1.1 christos return (ISC_R_SUCCESS);
2639 1.1 christos } else {
2640 1.1 christos CHECK(parse_unitstring(TOKEN_STRING(pctx), &val));
2641 1.1 christos CHECK(cfg_create_obj(pctx, &cfg_type_uint64, &obj));
2642 1.1 christos obj->value.uint64 = val;
2643 1.1 christos *ret = obj;
2644 1.1 christos return (ISC_R_SUCCESS);
2645 1.1 christos }
2646 1.1 christos
2647 1.1 christos cleanup:
2648 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR,
2649 1.1 christos "expected integer and optional unit or percent");
2650 1.1 christos return (result);
2651 1.1 christos }
2652 1.1 christos
2653 1.1 christos static void
2654 1.1 christos doc_sizeval_percent(cfg_printer_t *pctx, const cfg_type_t *type) {
2655 1.1 christos
2656 1.1 christos UNUSED(type);
2657 1.1 christos
2658 1.1 christos cfg_print_cstr(pctx, "( ");
2659 1.1 christos cfg_doc_terminal(pctx, &cfg_type_size);
2660 1.1 christos cfg_print_cstr(pctx, " | ");
2661 1.1 christos cfg_doc_terminal(pctx, &cfg_type_percentage);
2662 1.1 christos cfg_print_cstr(pctx, " )");
2663 1.1 christos }
2664 1.1 christos
2665 1.1 christos /*%
2666 1.1 christos * A size value (number + optional unit).
2667 1.1 christos */
2668 1.1 christos static cfg_type_t cfg_type_sizeval = {
2669 1.1 christos "sizeval", parse_sizeval, cfg_print_uint64, cfg_doc_terminal,
2670 1.1 christos &cfg_rep_uint64, NULL
2671 1.1 christos };
2672 1.1 christos
2673 1.1 christos /*%
2674 1.1 christos * A size, "unlimited", or "default".
2675 1.1 christos */
2676 1.1 christos
2677 1.1 christos static isc_result_t
2678 1.1 christos parse_size(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
2679 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_sizeval, ret));
2680 1.1 christos }
2681 1.1 christos
2682 1.1 christos static void
2683 1.1 christos doc_size(cfg_printer_t *pctx, const cfg_type_t *type) {
2684 1.1 christos doc_enum_or_other(pctx, type, &cfg_type_sizeval);
2685 1.1 christos }
2686 1.1 christos
2687 1.1 christos static const char *size_enums[] = { "default", "unlimited", NULL };
2688 1.1 christos static cfg_type_t cfg_type_size = {
2689 1.1 christos "size", parse_size, cfg_print_ustring, doc_size,
2690 1.1 christos &cfg_rep_string, size_enums
2691 1.1 christos };
2692 1.1 christos
2693 1.1 christos /*%
2694 1.1 christos * A size or "unlimited", but not "default".
2695 1.1 christos */
2696 1.1 christos static const char *sizenodefault_enums[] = { "unlimited", NULL };
2697 1.1 christos static cfg_type_t cfg_type_sizenodefault = {
2698 1.1 christos "size_no_default", parse_size, cfg_print_ustring, doc_size,
2699 1.1 christos &cfg_rep_string, sizenodefault_enums
2700 1.1 christos };
2701 1.1 christos
2702 1.1 christos /*%
2703 1.1 christos * A size in absolute values or percents.
2704 1.1 christos */
2705 1.1 christos static cfg_type_t cfg_type_sizeval_percent = {
2706 1.1 christos "sizeval_percent", parse_sizeval_percent, cfg_print_ustring,
2707 1.1 christos doc_sizeval_percent, &cfg_rep_string, NULL
2708 1.1 christos };
2709 1.1 christos
2710 1.1 christos /*%
2711 1.1 christos * A size in absolute values or percents, or "unlimited", or "default"
2712 1.1 christos */
2713 1.1 christos
2714 1.1 christos static isc_result_t
2715 1.1 christos parse_size_or_percent(cfg_parser_t *pctx, const cfg_type_t *type,
2716 1.1 christos cfg_obj_t **ret)
2717 1.1 christos {
2718 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_sizeval_percent,
2719 1.1 christos ret));
2720 1.1 christos }
2721 1.1 christos
2722 1.1 christos static void
2723 1.1 christos doc_parse_size_or_percent(cfg_printer_t *pctx, const cfg_type_t *type) {
2724 1.1 christos doc_enum_or_other(pctx, type, &cfg_type_sizeval_percent);
2725 1.1 christos }
2726 1.1 christos
2727 1.1 christos static const char *sizeorpercent_enums[] = { "default", "unlimited", NULL };
2728 1.1 christos static cfg_type_t cfg_type_sizeorpercent = {
2729 1.1 christos "size_or_percent", parse_size_or_percent, cfg_print_ustring,
2730 1.1 christos doc_parse_size_or_percent, &cfg_rep_string, sizeorpercent_enums
2731 1.1 christos };
2732 1.1 christos
2733 1.1 christos /*%
2734 1.1 christos * optional_keyvalue
2735 1.1 christos */
2736 1.1 christos static isc_result_t
2737 1.1 christos parse_maybe_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
2738 1.1 christos isc_boolean_t optional, cfg_obj_t **ret)
2739 1.1 christos {
2740 1.1 christos isc_result_t result;
2741 1.1 christos cfg_obj_t *obj = NULL;
2742 1.1 christos const keyword_type_t *kw = type->of;
2743 1.1 christos
2744 1.1 christos CHECK(cfg_peektoken(pctx, 0));
2745 1.1 christos if (pctx->token.type == isc_tokentype_string &&
2746 1.1 christos strcasecmp(TOKEN_STRING(pctx), kw->name) == 0) {
2747 1.1 christos CHECK(cfg_gettoken(pctx, 0));
2748 1.1 christos CHECK(kw->type->parse(pctx, kw->type, &obj));
2749 1.1 christos obj->type = type; /* XXX kludge */
2750 1.1 christos } else {
2751 1.1 christos if (optional) {
2752 1.1 christos CHECK(cfg_parse_void(pctx, NULL, &obj));
2753 1.1 christos } else {
2754 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR, "expected '%s'",
2755 1.1 christos kw->name);
2756 1.1 christos result = ISC_R_UNEXPECTEDTOKEN;
2757 1.1 christos goto cleanup;
2758 1.1 christos }
2759 1.1 christos }
2760 1.1 christos *ret = obj;
2761 1.1 christos cleanup:
2762 1.1 christos return (result);
2763 1.1 christos }
2764 1.1 christos
2765 1.1 christos static isc_result_t
2766 1.1 christos parse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype,
2767 1.1 christos const cfg_type_t *othertype, cfg_obj_t **ret)
2768 1.1 christos {
2769 1.1 christos isc_result_t result;
2770 1.1 christos CHECK(cfg_peektoken(pctx, 0));
2771 1.1 christos if (pctx->token.type == isc_tokentype_string &&
2772 1.1 christos cfg_is_enum(TOKEN_STRING(pctx), enumtype->of)) {
2773 1.1 christos CHECK(cfg_parse_enum(pctx, enumtype, ret));
2774 1.1 christos } else {
2775 1.1 christos CHECK(cfg_parse_obj(pctx, othertype, ret));
2776 1.1 christos }
2777 1.1 christos cleanup:
2778 1.1 christos return (result);
2779 1.1 christos }
2780 1.1 christos
2781 1.1 christos static void
2782 1.1 christos doc_enum_or_other(cfg_printer_t *pctx, const cfg_type_t *enumtype,
2783 1.1 christos const cfg_type_t *othertype)
2784 1.1 christos {
2785 1.1 christos const char * const *p;
2786 1.1 christos isc_boolean_t first = ISC_TRUE;
2787 1.1 christos
2788 1.1 christos /*
2789 1.1 christos * If othertype is cfg_type_void, it means that enumtype is
2790 1.1 christos * optional.
2791 1.1 christos */
2792 1.1 christos
2793 1.1 christos if (othertype == &cfg_type_void)
2794 1.1 christos cfg_print_cstr(pctx, "[ ");
2795 1.1 christos cfg_print_cstr(pctx, "( ");
2796 1.1 christos for (p = enumtype->of; *p != NULL; p++) {
2797 1.1 christos if (!first)
2798 1.1 christos cfg_print_cstr(pctx, " | ");
2799 1.1 christos first = ISC_FALSE;
2800 1.1 christos cfg_print_cstr(pctx, *p);
2801 1.1 christos }
2802 1.1 christos if (othertype == &cfg_type_sizeval_percent) {
2803 1.1 christos if (!first)
2804 1.1 christos cfg_print_cstr(pctx, " | ");
2805 1.1 christos cfg_doc_terminal(pctx, &cfg_type_sizeval);
2806 1.1 christos cfg_print_cstr(pctx, " | ");
2807 1.1 christos cfg_doc_terminal(pctx, &cfg_type_percentage);
2808 1.1 christos } else if (othertype != &cfg_type_void) {
2809 1.1 christos if (!first)
2810 1.1 christos cfg_print_cstr(pctx, " | ");
2811 1.1 christos cfg_doc_terminal(pctx, othertype);
2812 1.1 christos }
2813 1.1 christos cfg_print_cstr(pctx, " )");
2814 1.1 christos if (othertype == &cfg_type_void)
2815 1.1 christos cfg_print_cstr(pctx, " ]");
2816 1.1 christos }
2817 1.1 christos
2818 1.1 christos static isc_result_t
2819 1.1 christos parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
2820 1.1 christos return (parse_maybe_optional_keyvalue(pctx, type, ISC_FALSE, ret));
2821 1.1 christos }
2822 1.1 christos
2823 1.1 christos static isc_result_t
2824 1.1 christos parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
2825 1.1 christos cfg_obj_t **ret)
2826 1.1 christos {
2827 1.1 christos return (parse_maybe_optional_keyvalue(pctx, type, ISC_TRUE, ret));
2828 1.1 christos }
2829 1.1 christos
2830 1.1 christos static void
2831 1.1 christos print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj) {
2832 1.1 christos const keyword_type_t *kw = obj->type->of;
2833 1.1 christos cfg_print_cstr(pctx, kw->name);
2834 1.1 christos cfg_print_cstr(pctx, " ");
2835 1.1 christos kw->type->print(pctx, obj);
2836 1.1 christos }
2837 1.1 christos
2838 1.1 christos static void
2839 1.1 christos doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) {
2840 1.1 christos const keyword_type_t *kw = type->of;
2841 1.1 christos cfg_print_cstr(pctx, kw->name);
2842 1.1 christos cfg_print_cstr(pctx, " ");
2843 1.1 christos cfg_doc_obj(pctx, kw->type);
2844 1.1 christos }
2845 1.1 christos
2846 1.1 christos static void
2847 1.1 christos doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) {
2848 1.1 christos const keyword_type_t *kw = type->of;
2849 1.1 christos cfg_print_cstr(pctx, "[ ");
2850 1.1 christos cfg_print_cstr(pctx, kw->name);
2851 1.1 christos cfg_print_cstr(pctx, " ");
2852 1.1 christos cfg_doc_obj(pctx, kw->type);
2853 1.1 christos cfg_print_cstr(pctx, " ]");
2854 1.1 christos }
2855 1.1 christos
2856 1.1 christos static const char *dialup_enums[] = {
2857 1.1 christos "notify", "notify-passive", "passive", "refresh", NULL
2858 1.1 christos };
2859 1.1 christos static isc_result_t
2860 1.1 christos parse_dialup_type(cfg_parser_t *pctx, const cfg_type_t *type,
2861 1.1 christos cfg_obj_t **ret)
2862 1.1 christos {
2863 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
2864 1.1 christos }
2865 1.1 christos static void
2866 1.1 christos doc_dialup_type(cfg_printer_t *pctx, const cfg_type_t *type) {
2867 1.1 christos doc_enum_or_other(pctx, type, &cfg_type_boolean);
2868 1.1 christos }
2869 1.1 christos static cfg_type_t cfg_type_dialuptype = {
2870 1.1 christos "dialuptype", parse_dialup_type, cfg_print_ustring, doc_dialup_type,
2871 1.1 christos &cfg_rep_string, dialup_enums
2872 1.1 christos };
2873 1.1 christos
2874 1.1 christos static const char *notify_enums[] = { "explicit", "master-only", NULL };
2875 1.1 christos static isc_result_t
2876 1.1 christos parse_notify_type(cfg_parser_t *pctx, const cfg_type_t *type,
2877 1.1 christos cfg_obj_t **ret)
2878 1.1 christos {
2879 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
2880 1.1 christos }
2881 1.1 christos static void
2882 1.1 christos doc_notify_type(cfg_printer_t *pctx, const cfg_type_t *type) {
2883 1.1 christos doc_enum_or_other(pctx, type, &cfg_type_boolean);
2884 1.1 christos }
2885 1.1 christos static cfg_type_t cfg_type_notifytype = {
2886 1.1 christos "notifytype", parse_notify_type, cfg_print_ustring, doc_notify_type,
2887 1.1 christos &cfg_rep_string, notify_enums,
2888 1.1 christos };
2889 1.1 christos
2890 1.1 christos static const char *minimal_enums[] = { "no-auth", "no-auth-recursive", NULL };
2891 1.1 christos static isc_result_t
2892 1.1 christos parse_minimal(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
2893 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
2894 1.1 christos }
2895 1.1 christos static void
2896 1.1 christos doc_minimal(cfg_printer_t *pctx, const cfg_type_t *type) {
2897 1.1 christos doc_enum_or_other(pctx, type, &cfg_type_boolean);
2898 1.1 christos }
2899 1.1 christos static cfg_type_t cfg_type_minimal = {
2900 1.1 christos "mimimal", parse_minimal, cfg_print_ustring, doc_minimal,
2901 1.1 christos &cfg_rep_string, minimal_enums,
2902 1.1 christos };
2903 1.1 christos
2904 1.1 christos static const char *ixfrdiff_enums[] = { "master", "slave", NULL };
2905 1.1 christos static isc_result_t
2906 1.1 christos parse_ixfrdiff_type(cfg_parser_t *pctx, const cfg_type_t *type,
2907 1.1 christos cfg_obj_t **ret)
2908 1.1 christos {
2909 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
2910 1.1 christos }
2911 1.1 christos static void
2912 1.1 christos doc_ixfrdiff_type(cfg_printer_t *pctx, const cfg_type_t *type) {
2913 1.1 christos doc_enum_or_other(pctx, type, &cfg_type_boolean);
2914 1.1 christos }
2915 1.1 christos static cfg_type_t cfg_type_ixfrdifftype = {
2916 1.1 christos "ixfrdiff", parse_ixfrdiff_type, cfg_print_ustring, doc_ixfrdiff_type,
2917 1.1 christos &cfg_rep_string, ixfrdiff_enums,
2918 1.1 christos };
2919 1.1 christos
2920 1.1 christos static const char *filter_aaaa_enums[] = { "break-dnssec", NULL };
2921 1.1 christos static isc_result_t
2922 1.1 christos parse_filter_aaaa(cfg_parser_t *pctx, const cfg_type_t *type,
2923 1.1 christos cfg_obj_t **ret) {
2924 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
2925 1.1 christos }
2926 1.1 christos static void
2927 1.1 christos doc_filter_aaaa(cfg_printer_t *pctx, const cfg_type_t *type) {
2928 1.1 christos doc_enum_or_other(pctx, type, &cfg_type_boolean);
2929 1.1 christos }
2930 1.1 christos static cfg_type_t cfg_type_filter_aaaa = {
2931 1.1 christos "filter_aaaa", parse_filter_aaaa, cfg_print_ustring,
2932 1.1 christos doc_filter_aaaa, &cfg_rep_string, filter_aaaa_enums,
2933 1.1 christos };
2934 1.1 christos
2935 1.1 christos static keyword_type_t key_kw = { "key", &cfg_type_astring };
2936 1.1 christos
2937 1.1 christos LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_keyref = {
2938 1.1 christos "keyref", parse_keyvalue, print_keyvalue, doc_keyvalue,
2939 1.1 christos &cfg_rep_string, &key_kw
2940 1.1 christos };
2941 1.1 christos
2942 1.1 christos static cfg_type_t cfg_type_optional_keyref = {
2943 1.1 christos "optional_keyref", parse_optional_keyvalue, print_keyvalue,
2944 1.1 christos doc_optional_keyvalue, &cfg_rep_string, &key_kw
2945 1.1 christos };
2946 1.1 christos
2947 1.1 christos #ifdef HAVE_GEOIP
2948 1.1 christos /*
2949 1.1 christos * "geoip" ACL element:
2950 1.1 christos * geoip [ db <database> ] search-type <string>
2951 1.1 christos */
2952 1.1 christos static const char *geoiptype_enums[] = {
2953 1.1 christos "area", "areacode", "asnum", "city", "continent", "country",
2954 1.1 christos "country3", "countryname", "domain", "isp", "metro", "metrocode",
2955 1.1 christos "netspeed", "org", "postal", "postalcode", "region", "regionname",
2956 1.1 christos "timezone", "tz", NULL
2957 1.1 christos };
2958 1.1 christos static cfg_type_t cfg_type_geoiptype = {
2959 1.1 christos "geoiptype", cfg_parse_enum, cfg_print_ustring,
2960 1.1 christos cfg_doc_enum, &cfg_rep_string, &geoiptype_enums
2961 1.1 christos };
2962 1.1 christos
2963 1.1 christos static const char *geoipdb_enums[] = {
2964 1.1 christos "asnum", "city", "country", "domain", "isp", "netspeed",
2965 1.1 christos "org", "region", NULL
2966 1.1 christos };
2967 1.1 christos static cfg_type_t cfg_type_geoipdb = {
2968 1.1 christos "geoipdb", cfg_parse_enum, cfg_print_ustring,
2969 1.1 christos cfg_doc_enum, &cfg_rep_string, &geoipdb_enums
2970 1.1 christos };
2971 1.1 christos
2972 1.1 christos static cfg_tuplefielddef_t geoip_fields[] = {
2973 1.1 christos { "negated", &cfg_type_void, 0 },
2974 1.1 christos { "db", &cfg_type_geoipdb, 0 },
2975 1.1 christos { "subtype", &cfg_type_geoiptype, 0 },
2976 1.1 christos { "search", &cfg_type_astring, 0 },
2977 1.1 christos { NULL, NULL, 0 }
2978 1.1 christos };
2979 1.1 christos
2980 1.1 christos static cfg_type_t cfg_type_geoip = {
2981 1.1 christos "geoip", parse_geoip, print_geoip, doc_geoip,
2982 1.1 christos &cfg_rep_tuple, geoip_fields
2983 1.1 christos };
2984 1.1 christos
2985 1.1 christos static isc_result_t
2986 1.1 christos parse_geoip(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
2987 1.1 christos isc_result_t result;
2988 1.1 christos cfg_obj_t *obj = NULL;
2989 1.1 christos const cfg_tuplefielddef_t *fields = type->of;
2990 1.1 christos
2991 1.1 christos CHECK(cfg_create_tuple(pctx, type, &obj));
2992 1.1 christos CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[0]));
2993 1.1 christos
2994 1.1 christos /* Parse the optional "db" field. */
2995 1.1 christos CHECK(cfg_peektoken(pctx, 0));
2996 1.1 christos if (pctx->token.type == isc_tokentype_string) {
2997 1.1 christos CHECK(cfg_gettoken(pctx, 0));
2998 1.1 christos if (strcasecmp(TOKEN_STRING(pctx), "db") == 0 &&
2999 1.1 christos obj->value.tuple[1] == NULL) {
3000 1.1 christos CHECK(cfg_parse_obj(pctx, fields[1].type,
3001 1.1 christos &obj->value.tuple[1]));
3002 1.1 christos } else {
3003 1.1 christos CHECK(cfg_parse_void(pctx, NULL,
3004 1.1 christos &obj->value.tuple[1]));
3005 1.1 christos cfg_ungettoken(pctx);
3006 1.1 christos }
3007 1.1 christos }
3008 1.1 christos
3009 1.1 christos CHECK(cfg_parse_obj(pctx, fields[2].type, &obj->value.tuple[2]));
3010 1.1 christos CHECK(cfg_parse_obj(pctx, fields[3].type, &obj->value.tuple[3]));
3011 1.1 christos
3012 1.1 christos *ret = obj;
3013 1.1 christos return (ISC_R_SUCCESS);
3014 1.1 christos
3015 1.1 christos cleanup:
3016 1.1 christos CLEANUP_OBJ(obj);
3017 1.1 christos return (result);
3018 1.1 christos }
3019 1.1 christos
3020 1.1 christos static void
3021 1.1 christos print_geoip(cfg_printer_t *pctx, const cfg_obj_t *obj) {
3022 1.1 christos if (obj->value.tuple[1]->type->print != cfg_print_void) {
3023 1.1 christos cfg_print_cstr(pctx, " db ");
3024 1.1 christos cfg_print_obj(pctx, obj->value.tuple[1]);
3025 1.1 christos }
3026 1.1 christos cfg_print_obj(pctx, obj->value.tuple[2]);
3027 1.1 christos cfg_print_obj(pctx, obj->value.tuple[3]);
3028 1.1 christos }
3029 1.1 christos
3030 1.1 christos static void
3031 1.1 christos doc_geoip(cfg_printer_t *pctx, const cfg_type_t *type) {
3032 1.1 christos UNUSED(type);
3033 1.1 christos cfg_print_cstr(pctx, "[ db ");
3034 1.1 christos cfg_doc_enum(pctx, &cfg_type_geoipdb);
3035 1.1 christos cfg_print_cstr(pctx, " ]");
3036 1.1 christos cfg_print_cstr(pctx, " ");
3037 1.1 christos cfg_doc_enum(pctx, &cfg_type_geoiptype);
3038 1.1 christos cfg_print_cstr(pctx, " ");
3039 1.1 christos cfg_print_cstr(pctx, "<quoted_string>");
3040 1.1 christos }
3041 1.1 christos #endif /* HAVE_GEOIP */
3042 1.1 christos
3043 1.1 christos /*%
3044 1.1 christos * An EDNS client subnet address
3045 1.1 christos */
3046 1.1 christos
3047 1.1 christos static keyword_type_t ecs_kw = { "ecs", &cfg_type_netprefix };
3048 1.1 christos LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_ecsprefix = {
3049 1.1 christos "edns_client_subnet", parse_keyvalue, print_keyvalue, doc_keyvalue,
3050 1.1 christos &cfg_rep_netprefix, &ecs_kw
3051 1.1 christos };
3052 1.1 christos
3053 1.1 christos /*%
3054 1.1 christos * A "controls" statement is represented as a map with the multivalued
3055 1.1 christos * "inet" and "unix" clauses.
3056 1.1 christos */
3057 1.1 christos
3058 1.1 christos static keyword_type_t controls_allow_kw = {
3059 1.1 christos "allow", &cfg_type_bracketed_aml };
3060 1.1 christos
3061 1.1 christos static cfg_type_t cfg_type_controls_allow = {
3062 1.1 christos "controls_allow", parse_keyvalue,
3063 1.1 christos print_keyvalue, doc_keyvalue,
3064 1.1 christos &cfg_rep_list, &controls_allow_kw
3065 1.1 christos };
3066 1.1 christos
3067 1.1 christos static keyword_type_t controls_keys_kw = {
3068 1.1 christos "keys", &cfg_type_keylist
3069 1.1 christos };
3070 1.1 christos
3071 1.1 christos static cfg_type_t cfg_type_controls_keys = {
3072 1.1 christos "controls_keys", parse_optional_keyvalue,
3073 1.1 christos print_keyvalue, doc_optional_keyvalue,
3074 1.1 christos &cfg_rep_list, &controls_keys_kw
3075 1.1 christos };
3076 1.1 christos
3077 1.1 christos static keyword_type_t controls_readonly_kw = {
3078 1.1 christos "read-only", &cfg_type_boolean
3079 1.1 christos };
3080 1.1 christos
3081 1.1 christos static cfg_type_t cfg_type_controls_readonly = {
3082 1.1 christos "controls_readonly", parse_optional_keyvalue,
3083 1.1 christos print_keyvalue, doc_optional_keyvalue,
3084 1.1 christos &cfg_rep_boolean, &controls_readonly_kw
3085 1.1 christos };
3086 1.1 christos
3087 1.1 christos static cfg_tuplefielddef_t inetcontrol_fields[] = {
3088 1.1 christos { "address", &cfg_type_controls_sockaddr, 0 },
3089 1.1 christos { "allow", &cfg_type_controls_allow, 0 },
3090 1.1 christos { "keys", &cfg_type_controls_keys, 0 },
3091 1.1 christos { "read-only", &cfg_type_controls_readonly, 0 },
3092 1.1 christos { NULL, NULL, 0 }
3093 1.1 christos };
3094 1.1 christos
3095 1.1 christos static cfg_type_t cfg_type_inetcontrol = {
3096 1.1 christos "inetcontrol", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
3097 1.1 christos &cfg_rep_tuple, inetcontrol_fields
3098 1.1 christos };
3099 1.1 christos
3100 1.1 christos static keyword_type_t controls_perm_kw = {
3101 1.1 christos "perm", &cfg_type_uint32
3102 1.1 christos };
3103 1.1 christos
3104 1.1 christos static cfg_type_t cfg_type_controls_perm = {
3105 1.1 christos "controls_perm", parse_keyvalue,
3106 1.1 christos print_keyvalue, doc_keyvalue,
3107 1.1 christos &cfg_rep_uint32, &controls_perm_kw
3108 1.1 christos };
3109 1.1 christos
3110 1.1 christos static keyword_type_t controls_owner_kw = {
3111 1.1 christos "owner", &cfg_type_uint32
3112 1.1 christos };
3113 1.1 christos
3114 1.1 christos static cfg_type_t cfg_type_controls_owner = {
3115 1.1 christos "controls_owner", parse_keyvalue,
3116 1.1 christos print_keyvalue, doc_keyvalue,
3117 1.1 christos &cfg_rep_uint32, &controls_owner_kw
3118 1.1 christos };
3119 1.1 christos
3120 1.1 christos static keyword_type_t controls_group_kw = {
3121 1.1 christos "group", &cfg_type_uint32
3122 1.1 christos };
3123 1.1 christos
3124 1.1 christos static cfg_type_t cfg_type_controls_group = {
3125 1.1 christos "controls_allow", parse_keyvalue,
3126 1.1 christos print_keyvalue, doc_keyvalue,
3127 1.1 christos &cfg_rep_uint32, &controls_group_kw
3128 1.1 christos };
3129 1.1 christos
3130 1.1 christos static cfg_tuplefielddef_t unixcontrol_fields[] = {
3131 1.1 christos { "path", &cfg_type_qstring, 0 },
3132 1.1 christos { "perm", &cfg_type_controls_perm, 0 },
3133 1.1 christos { "owner", &cfg_type_controls_owner, 0 },
3134 1.1 christos { "group", &cfg_type_controls_group, 0 },
3135 1.1 christos { "keys", &cfg_type_controls_keys, 0 },
3136 1.1 christos { "read-only", &cfg_type_controls_readonly, 0 },
3137 1.1 christos { NULL, NULL, 0 }
3138 1.1 christos };
3139 1.1 christos
3140 1.1 christos static cfg_type_t cfg_type_unixcontrol = {
3141 1.1 christos "unixcontrol", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
3142 1.1 christos &cfg_rep_tuple, unixcontrol_fields
3143 1.1 christos };
3144 1.1 christos
3145 1.1 christos static cfg_clausedef_t
3146 1.1 christos controls_clauses[] = {
3147 1.1 christos { "inet", &cfg_type_inetcontrol, CFG_CLAUSEFLAG_MULTI },
3148 1.1 christos { "unix", &cfg_type_unixcontrol, CFG_CLAUSEFLAG_MULTI },
3149 1.1 christos { NULL, NULL, 0 }
3150 1.1 christos };
3151 1.1 christos
3152 1.1 christos static cfg_clausedef_t *
3153 1.1 christos controls_clausesets[] = {
3154 1.1 christos controls_clauses,
3155 1.1 christos NULL
3156 1.1 christos };
3157 1.1 christos static cfg_type_t cfg_type_controls = {
3158 1.1 christos "controls", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map,
3159 1.1 christos &controls_clausesets
3160 1.1 christos };
3161 1.1 christos
3162 1.1 christos /*%
3163 1.1 christos * A "statistics-channels" statement is represented as a map with the
3164 1.1 christos * multivalued "inet" clauses.
3165 1.1 christos */
3166 1.1 christos static void
3167 1.1 christos doc_optional_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) {
3168 1.1 christos const keyword_type_t *kw = type->of;
3169 1.1 christos cfg_print_cstr(pctx, "[ ");
3170 1.1 christos cfg_print_cstr(pctx, kw->name);
3171 1.1 christos cfg_print_cstr(pctx, " ");
3172 1.1 christos cfg_doc_obj(pctx, kw->type);
3173 1.1 christos cfg_print_cstr(pctx, " ]");
3174 1.1 christos }
3175 1.1 christos
3176 1.1 christos static cfg_type_t cfg_type_optional_allow = {
3177 1.1 christos "optional_allow", parse_optional_keyvalue, print_keyvalue,
3178 1.1 christos doc_optional_bracketed_list, &cfg_rep_list, &controls_allow_kw
3179 1.1 christos };
3180 1.1 christos
3181 1.1 christos static cfg_tuplefielddef_t statserver_fields[] = {
3182 1.1 christos { "address", &cfg_type_controls_sockaddr, 0 }, /* reuse controls def */
3183 1.1 christos { "allow", &cfg_type_optional_allow, 0 },
3184 1.1 christos { NULL, NULL, 0 }
3185 1.1 christos };
3186 1.1 christos
3187 1.1 christos static cfg_type_t cfg_type_statschannel = {
3188 1.1 christos "statschannel", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
3189 1.1 christos &cfg_rep_tuple, statserver_fields
3190 1.1 christos };
3191 1.1 christos
3192 1.1 christos static cfg_clausedef_t
3193 1.1 christos statservers_clauses[] = {
3194 1.1 christos { "inet", &cfg_type_statschannel, CFG_CLAUSEFLAG_MULTI },
3195 1.1 christos { NULL, NULL, 0 }
3196 1.1 christos };
3197 1.1 christos
3198 1.1 christos static cfg_clausedef_t *
3199 1.1 christos statservers_clausesets[] = {
3200 1.1 christos statservers_clauses,
3201 1.1 christos NULL
3202 1.1 christos };
3203 1.1 christos
3204 1.1 christos static cfg_type_t cfg_type_statschannels = {
3205 1.1 christos "statistics-channels", cfg_parse_map, cfg_print_map, cfg_doc_map,
3206 1.1 christos &cfg_rep_map, &statservers_clausesets
3207 1.1 christos };
3208 1.1 christos
3209 1.1 christos /*%
3210 1.1 christos * An optional class, as used in view and zone statements.
3211 1.1 christos */
3212 1.1 christos static isc_result_t
3213 1.1 christos parse_optional_class(cfg_parser_t *pctx, const cfg_type_t *type,
3214 1.1 christos cfg_obj_t **ret)
3215 1.1 christos {
3216 1.1 christos isc_result_t result;
3217 1.1 christos UNUSED(type);
3218 1.1 christos CHECK(cfg_peektoken(pctx, 0));
3219 1.1 christos if (pctx->token.type == isc_tokentype_string)
3220 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_ustring, ret));
3221 1.1 christos else
3222 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
3223 1.1 christos cleanup:
3224 1.1 christos return (result);
3225 1.1 christos }
3226 1.1 christos
3227 1.1 christos static void
3228 1.1 christos doc_optional_class(cfg_printer_t *pctx, const cfg_type_t *type) {
3229 1.1 christos UNUSED(type);
3230 1.1 christos cfg_print_cstr(pctx, "[ <class> ]");
3231 1.1 christos }
3232 1.1 christos
3233 1.1 christos static cfg_type_t cfg_type_optional_class = {
3234 1.1 christos "optional_class", parse_optional_class, NULL, doc_optional_class,
3235 1.1 christos NULL, NULL
3236 1.1 christos };
3237 1.1 christos
3238 1.1 christos static isc_result_t
3239 1.1 christos parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type,
3240 1.1 christos cfg_obj_t **ret)
3241 1.1 christos {
3242 1.1 christos isc_result_t result;
3243 1.1 christos cfg_obj_t *obj = NULL;
3244 1.1 christos isc_netaddr_t netaddr;
3245 1.1 christos in_port_t port = 0;
3246 1.1 christos isc_dscp_t dscp = -1;
3247 1.1 christos unsigned int have_address = 0;
3248 1.1 christos unsigned int have_port = 0;
3249 1.1 christos unsigned int have_dscp = 0;
3250 1.1 christos const unsigned int *flagp = type->of;
3251 1.1 christos
3252 1.1 christos if ((*flagp & CFG_ADDR_V4OK) != 0)
3253 1.1 christos isc_netaddr_any(&netaddr);
3254 1.1 christos else if ((*flagp & CFG_ADDR_V6OK) != 0)
3255 1.1 christos isc_netaddr_any6(&netaddr);
3256 1.1 christos else
3257 1.1 christos INSIST(0);
3258 1.1 christos
3259 1.1 christos for (;;) {
3260 1.1 christos CHECK(cfg_peektoken(pctx, 0));
3261 1.1 christos if (pctx->token.type == isc_tokentype_string) {
3262 1.1 christos if (strcasecmp(TOKEN_STRING(pctx),
3263 1.1 christos "address") == 0)
3264 1.1 christos {
3265 1.1 christos /* read "address" */
3266 1.1 christos CHECK(cfg_gettoken(pctx, 0));
3267 1.1 christos CHECK(cfg_parse_rawaddr(pctx, *flagp,
3268 1.1 christos &netaddr));
3269 1.1 christos have_address++;
3270 1.1 christos } else if (strcasecmp(TOKEN_STRING(pctx), "port") == 0)
3271 1.1 christos {
3272 1.1 christos /* read "port" */
3273 1.1 christos CHECK(cfg_gettoken(pctx, 0));
3274 1.1 christos CHECK(cfg_parse_rawport(pctx,
3275 1.1 christos CFG_ADDR_WILDOK,
3276 1.1 christos &port));
3277 1.1 christos have_port++;
3278 1.1 christos } else if (strcasecmp(TOKEN_STRING(pctx), "dscp") == 0)
3279 1.1 christos {
3280 1.1 christos /* read "dscp" */
3281 1.1 christos CHECK(cfg_gettoken(pctx, 0));
3282 1.1 christos CHECK(cfg_parse_dscp(pctx, &dscp));
3283 1.1 christos have_dscp++;
3284 1.1 christos } else if (have_port == 0 && have_dscp == 0 &&
3285 1.1 christos have_address == 0)
3286 1.1 christos {
3287 1.1 christos return (cfg_parse_sockaddr(pctx, type, ret));
3288 1.1 christos } else {
3289 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR,
3290 1.1 christos "expected 'address', 'port', "
3291 1.1 christos "or 'dscp'");
3292 1.1 christos return (ISC_R_UNEXPECTEDTOKEN);
3293 1.1 christos }
3294 1.1 christos } else
3295 1.1 christos break;
3296 1.1 christos }
3297 1.1 christos if (have_address > 1 || have_port > 1 ||
3298 1.1 christos have_address + have_port == 0) {
3299 1.1 christos cfg_parser_error(pctx, 0, "expected one address and/or port");
3300 1.1 christos return (ISC_R_UNEXPECTEDTOKEN);
3301 1.1 christos }
3302 1.1 christos
3303 1.1 christos if (have_dscp > 1) {
3304 1.1 christos cfg_parser_error(pctx, 0, "expected at most one dscp");
3305 1.1 christos return (ISC_R_UNEXPECTEDTOKEN);
3306 1.1 christos }
3307 1.1 christos
3308 1.1 christos CHECK(cfg_create_obj(pctx, &cfg_type_querysource, &obj));
3309 1.1 christos isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, port);
3310 1.1 christos obj->value.sockaddrdscp.dscp = dscp;
3311 1.1 christos *ret = obj;
3312 1.1 christos return (ISC_R_SUCCESS);
3313 1.1 christos
3314 1.1 christos cleanup:
3315 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR, "invalid query source");
3316 1.1 christos CLEANUP_OBJ(obj);
3317 1.1 christos return (result);
3318 1.1 christos }
3319 1.1 christos
3320 1.1 christos static void
3321 1.1 christos print_querysource(cfg_printer_t *pctx, const cfg_obj_t *obj) {
3322 1.1 christos isc_netaddr_t na;
3323 1.1 christos isc_netaddr_fromsockaddr(&na, &obj->value.sockaddr);
3324 1.1 christos cfg_print_cstr(pctx, "address ");
3325 1.1 christos cfg_print_rawaddr(pctx, &na);
3326 1.1 christos cfg_print_cstr(pctx, " port ");
3327 1.1 christos cfg_print_rawuint(pctx, isc_sockaddr_getport(&obj->value.sockaddr));
3328 1.1 christos if (obj->value.sockaddrdscp.dscp != -1) {
3329 1.1 christos cfg_print_cstr(pctx, " dscp ");
3330 1.1 christos cfg_print_rawuint(pctx, obj->value.sockaddrdscp.dscp);
3331 1.1 christos }
3332 1.1 christos }
3333 1.1 christos
3334 1.1 christos static void
3335 1.1 christos doc_querysource(cfg_printer_t *pctx, const cfg_type_t *type) {
3336 1.1 christos const unsigned int *flagp = type->of;
3337 1.1 christos
3338 1.1 christos cfg_print_cstr(pctx, "( ( [ address ] ( ");
3339 1.1 christos if (*flagp & CFG_ADDR_V4OK)
3340 1.1 christos cfg_print_cstr(pctx, "<ipv4_address>");
3341 1.1 christos else if (*flagp & CFG_ADDR_V6OK)
3342 1.1 christos cfg_print_cstr(pctx, "<ipv6_address>");
3343 1.1 christos else
3344 1.1 christos INSIST(0);
3345 1.1 christos cfg_print_cstr(pctx, " | * ) [ port ( <integer> | * ) ] ) | "
3346 1.1 christos "( [ [ address ] ( ");
3347 1.1 christos if (*flagp & CFG_ADDR_V4OK)
3348 1.1 christos cfg_print_cstr(pctx, "<ipv4_address>");
3349 1.1 christos else if (*flagp & CFG_ADDR_V6OK)
3350 1.1 christos cfg_print_cstr(pctx, "<ipv6_address>");
3351 1.1 christos else
3352 1.1 christos INSIST(0);
3353 1.1 christos cfg_print_cstr(pctx, " | * ) ] port ( <integer> | * ) ) )"
3354 1.1 christos " [ dscp <integer> ]");
3355 1.1 christos }
3356 1.1 christos
3357 1.1 christos static unsigned int sockaddr4wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V4OK |
3358 1.1 christos CFG_ADDR_DSCPOK;
3359 1.1 christos static unsigned int sockaddr6wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V6OK |
3360 1.1 christos CFG_ADDR_DSCPOK;
3361 1.1 christos
3362 1.1 christos static cfg_type_t cfg_type_querysource4 = {
3363 1.1 christos "querysource4", parse_querysource, NULL, doc_querysource,
3364 1.1 christos NULL, &sockaddr4wild_flags
3365 1.1 christos };
3366 1.1 christos
3367 1.1 christos static cfg_type_t cfg_type_querysource6 = {
3368 1.1 christos "querysource6", parse_querysource, NULL, doc_querysource,
3369 1.1 christos NULL, &sockaddr6wild_flags
3370 1.1 christos };
3371 1.1 christos
3372 1.1 christos static cfg_type_t cfg_type_querysource = {
3373 1.1 christos "querysource", NULL, print_querysource, NULL, &cfg_rep_sockaddr, NULL
3374 1.1 christos };
3375 1.1 christos
3376 1.1 christos /*% addrmatchelt */
3377 1.1 christos
3378 1.1 christos static isc_result_t
3379 1.1 christos parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type,
3380 1.1 christos cfg_obj_t **ret)
3381 1.1 christos {
3382 1.1 christos isc_result_t result;
3383 1.1 christos UNUSED(type);
3384 1.1 christos
3385 1.1 christos CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
3386 1.1 christos
3387 1.1 christos if (pctx->token.type == isc_tokentype_string ||
3388 1.1 christos pctx->token.type == isc_tokentype_qstring) {
3389 1.1 christos if (pctx->token.type == isc_tokentype_string &&
3390 1.1 christos (strcasecmp(TOKEN_STRING(pctx), "key") == 0)) {
3391 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_keyref, ret));
3392 1.1 christos } else if (pctx->token.type == isc_tokentype_string &&
3393 1.1 christos (strcasecmp(TOKEN_STRING(pctx), "ecs") == 0)) {
3394 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_ecsprefix, ret));
3395 1.1 christos } else if (pctx->token.type == isc_tokentype_string &&
3396 1.1 christos (strcasecmp(TOKEN_STRING(pctx), "geoip") == 0)) {
3397 1.1 christos #ifdef HAVE_GEOIP
3398 1.1 christos CHECK(cfg_gettoken(pctx, 0));
3399 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_geoip, ret));
3400 1.1 christos #else
3401 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR, "'geoip' "
3402 1.1 christos "not supported in this build");
3403 1.1 christos return (ISC_R_UNEXPECTEDTOKEN);
3404 1.1 christos #endif
3405 1.1 christos } else {
3406 1.1 christos if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK |
3407 1.1 christos CFG_ADDR_V4PREFIXOK |
3408 1.1 christos CFG_ADDR_V6OK))
3409 1.1 christos {
3410 1.1 christos CHECK(cfg_parse_netprefix(pctx, NULL, ret));
3411 1.1 christos } else {
3412 1.1 christos CHECK(cfg_parse_astring(pctx, NULL, ret));
3413 1.1 christos }
3414 1.1 christos }
3415 1.1 christos } else if (pctx->token.type == isc_tokentype_special) {
3416 1.1 christos if (pctx->token.value.as_char == '{') {
3417 1.1 christos /* Nested match list. */
3418 1.1 christos CHECK(cfg_parse_obj(pctx,
3419 1.1 christos &cfg_type_bracketed_aml, ret));
3420 1.1 christos } else if (pctx->token.value.as_char == '!') {
3421 1.1 christos CHECK(cfg_gettoken(pctx, 0)); /* read "!" */
3422 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_negated, ret));
3423 1.1 christos } else {
3424 1.1 christos goto bad;
3425 1.1 christos }
3426 1.1 christos } else {
3427 1.1 christos bad:
3428 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR,
3429 1.1 christos "expected IP match list element");
3430 1.1 christos return (ISC_R_UNEXPECTEDTOKEN);
3431 1.1 christos }
3432 1.1 christos cleanup:
3433 1.1 christos return (result);
3434 1.1 christos }
3435 1.1 christos
3436 1.1 christos /*%
3437 1.1 christos * A negated address match list element (like "! 10.0.0.1").
3438 1.1 christos * Somewhat sneakily, the caller is expected to parse the
3439 1.1 christos * "!", but not to print it.
3440 1.1 christos */
3441 1.1 christos
3442 1.1 christos static cfg_tuplefielddef_t negated_fields[] = {
3443 1.1 christos { "negated", &cfg_type_addrmatchelt, 0 },
3444 1.1 christos { NULL, NULL, 0 }
3445 1.1 christos };
3446 1.1 christos
3447 1.1 christos static void
3448 1.1 christos print_negated(cfg_printer_t *pctx, const cfg_obj_t *obj) {
3449 1.1 christos cfg_print_cstr(pctx, "!");
3450 1.1 christos cfg_print_tuple(pctx, obj);
3451 1.1 christos }
3452 1.1 christos
3453 1.1 christos static cfg_type_t cfg_type_negated = {
3454 1.1 christos "negated", cfg_parse_tuple, print_negated, NULL, &cfg_rep_tuple,
3455 1.1 christos &negated_fields
3456 1.1 christos };
3457 1.1 christos
3458 1.1 christos /*% An address match list element */
3459 1.1 christos
3460 1.1 christos static cfg_type_t cfg_type_addrmatchelt = {
3461 1.1 christos "address_match_element", parse_addrmatchelt, NULL, cfg_doc_terminal,
3462 1.1 christos NULL, NULL
3463 1.1 christos };
3464 1.1 christos
3465 1.1 christos /*% A bracketed address match list */
3466 1.1 christos
3467 1.1 christos static cfg_type_t cfg_type_bracketed_aml = {
3468 1.1 christos "bracketed_aml", cfg_parse_bracketed_list, cfg_print_bracketed_list,
3469 1.1 christos cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_addrmatchelt
3470 1.1 christos };
3471 1.1 christos
3472 1.1 christos /*%
3473 1.1 christos * The socket address syntax in the "controls" statement is silly.
3474 1.1 christos * It allows both socket address families, but also allows "*",
3475 1.1 christos * whis is gratuitously interpreted as the IPv4 wildcard address.
3476 1.1 christos */
3477 1.1 christos static unsigned int controls_sockaddr_flags =
3478 1.1 christos CFG_ADDR_V4OK | CFG_ADDR_V6OK | CFG_ADDR_WILDOK;
3479 1.1 christos static cfg_type_t cfg_type_controls_sockaddr = {
3480 1.1 christos "controls_sockaddr", cfg_parse_sockaddr, cfg_print_sockaddr,
3481 1.1 christos cfg_doc_sockaddr, &cfg_rep_sockaddr, &controls_sockaddr_flags
3482 1.1 christos };
3483 1.1 christos
3484 1.1 christos /*%
3485 1.1 christos * Handle the special kludge syntax of the "keys" clause in the "server"
3486 1.1 christos * statement, which takes a single key with or without braces and semicolon.
3487 1.1 christos */
3488 1.1 christos static isc_result_t
3489 1.1 christos parse_server_key_kludge(cfg_parser_t *pctx, const cfg_type_t *type,
3490 1.1 christos cfg_obj_t **ret)
3491 1.1 christos {
3492 1.1 christos isc_result_t result;
3493 1.1 christos isc_boolean_t braces = ISC_FALSE;
3494 1.1 christos UNUSED(type);
3495 1.1 christos
3496 1.1 christos /* Allow opening brace. */
3497 1.1 christos CHECK(cfg_peektoken(pctx, 0));
3498 1.1 christos if (pctx->token.type == isc_tokentype_special &&
3499 1.1 christos pctx->token.value.as_char == '{') {
3500 1.1 christos CHECK(cfg_gettoken(pctx, 0));
3501 1.1 christos braces = ISC_TRUE;
3502 1.1 christos }
3503 1.1 christos
3504 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_astring, ret));
3505 1.1 christos
3506 1.1 christos if (braces) {
3507 1.1 christos /* Skip semicolon if present. */
3508 1.1 christos CHECK(cfg_peektoken(pctx, 0));
3509 1.1 christos if (pctx->token.type == isc_tokentype_special &&
3510 1.1 christos pctx->token.value.as_char == ';')
3511 1.1 christos CHECK(cfg_gettoken(pctx, 0));
3512 1.1 christos
3513 1.1 christos CHECK(cfg_parse_special(pctx, '}'));
3514 1.1 christos }
3515 1.1 christos cleanup:
3516 1.1 christos return (result);
3517 1.1 christos }
3518 1.1 christos static cfg_type_t cfg_type_server_key_kludge = {
3519 1.1 christos "server_key", parse_server_key_kludge, NULL, cfg_doc_terminal,
3520 1.1 christos NULL, NULL
3521 1.1 christos };
3522 1.1 christos
3523 1.1 christos
3524 1.1 christos /*%
3525 1.1 christos * An optional logging facility.
3526 1.1 christos */
3527 1.1 christos
3528 1.1 christos static isc_result_t
3529 1.1 christos parse_optional_facility(cfg_parser_t *pctx, const cfg_type_t *type,
3530 1.1 christos cfg_obj_t **ret)
3531 1.1 christos {
3532 1.1 christos isc_result_t result;
3533 1.1 christos UNUSED(type);
3534 1.1 christos
3535 1.1 christos CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
3536 1.1 christos if (pctx->token.type == isc_tokentype_string ||
3537 1.1 christos pctx->token.type == isc_tokentype_qstring) {
3538 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_astring, ret));
3539 1.1 christos } else {
3540 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
3541 1.1 christos }
3542 1.1 christos cleanup:
3543 1.1 christos return (result);
3544 1.1 christos }
3545 1.1 christos
3546 1.1 christos static void
3547 1.1 christos doc_optional_facility(cfg_printer_t *pctx, const cfg_type_t *type) {
3548 1.1 christos UNUSED(type);
3549 1.1 christos cfg_print_cstr(pctx, "[ <syslog_facility> ]");
3550 1.1 christos }
3551 1.1 christos
3552 1.1 christos static cfg_type_t cfg_type_optional_facility = {
3553 1.1 christos "optional_facility", parse_optional_facility, NULL,
3554 1.1 christos doc_optional_facility, NULL, NULL
3555 1.1 christos };
3556 1.1 christos
3557 1.1 christos
3558 1.1 christos /*%
3559 1.1 christos * A log severity. Return as a string, except "debug N",
3560 1.1 christos * which is returned as a keyword object.
3561 1.1 christos */
3562 1.1 christos
3563 1.1 christos static keyword_type_t debug_kw = { "debug", &cfg_type_uint32 };
3564 1.1 christos static cfg_type_t cfg_type_debuglevel = {
3565 1.1 christos "debuglevel", parse_keyvalue,
3566 1.1 christos print_keyvalue, doc_keyvalue,
3567 1.1 christos &cfg_rep_uint32, &debug_kw
3568 1.1 christos };
3569 1.1 christos
3570 1.1 christos static isc_result_t
3571 1.1 christos parse_logseverity(cfg_parser_t *pctx, const cfg_type_t *type,
3572 1.1 christos cfg_obj_t **ret)
3573 1.1 christos {
3574 1.1 christos isc_result_t result;
3575 1.1 christos UNUSED(type);
3576 1.1 christos
3577 1.1 christos CHECK(cfg_peektoken(pctx, 0));
3578 1.1 christos if (pctx->token.type == isc_tokentype_string &&
3579 1.1 christos strcasecmp(TOKEN_STRING(pctx), "debug") == 0) {
3580 1.1 christos CHECK(cfg_gettoken(pctx, 0)); /* read "debug" */
3581 1.1 christos CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER));
3582 1.1 christos if (pctx->token.type == isc_tokentype_number) {
3583 1.1 christos CHECK(cfg_parse_uint32(pctx, NULL, ret));
3584 1.1 christos } else {
3585 1.1 christos /*
3586 1.1 christos * The debug level is optional and defaults to 1.
3587 1.1 christos * This makes little sense, but we support it for
3588 1.1 christos * compatibility with BIND 8.
3589 1.1 christos */
3590 1.1 christos CHECK(cfg_create_obj(pctx, &cfg_type_uint32, ret));
3591 1.1 christos (*ret)->value.uint32 = 1;
3592 1.1 christos }
3593 1.1 christos (*ret)->type = &cfg_type_debuglevel; /* XXX kludge */
3594 1.1 christos } else {
3595 1.1 christos CHECK(cfg_parse_obj(pctx, &cfg_type_loglevel, ret));
3596 1.1 christos }
3597 1.1 christos cleanup:
3598 1.1 christos return (result);
3599 1.1 christos }
3600 1.1 christos
3601 1.1 christos static cfg_type_t cfg_type_logseverity = {
3602 1.1 christos "log_severity", parse_logseverity, NULL, cfg_doc_terminal,
3603 1.1 christos NULL, NULL
3604 1.1 christos };
3605 1.1 christos
3606 1.1 christos /*%
3607 1.1 christos * The "file" clause of the "channel" statement.
3608 1.1 christos * This is yet another special case.
3609 1.1 christos */
3610 1.1 christos
3611 1.1 christos static const char *logversions_enums[] = { "unlimited", NULL };
3612 1.1 christos static isc_result_t
3613 1.1 christos parse_logversions(cfg_parser_t *pctx, const cfg_type_t *type,
3614 1.1 christos cfg_obj_t **ret)
3615 1.1 christos {
3616 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_uint32, ret));
3617 1.1 christos }
3618 1.1 christos
3619 1.1 christos static void
3620 1.1 christos doc_logversions(cfg_printer_t *pctx, const cfg_type_t *type) {
3621 1.1 christos doc_enum_or_other(pctx, type, &cfg_type_uint32);
3622 1.1 christos }
3623 1.1 christos
3624 1.1 christos static cfg_type_t cfg_type_logversions = {
3625 1.1 christos "logversions", parse_logversions, cfg_print_ustring, doc_logversions,
3626 1.1 christos &cfg_rep_string, logversions_enums
3627 1.1 christos };
3628 1.1 christos
3629 1.1 christos static const char *logsuffix_enums[] = { "increment", "timestamp", NULL };
3630 1.1 christos static cfg_type_t cfg_type_logsuffix = {
3631 1.1 christos "logsuffix", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
3632 1.1 christos &cfg_rep_string, &logsuffix_enums
3633 1.1 christos };
3634 1.1 christos
3635 1.1 christos static cfg_tuplefielddef_t logfile_fields[] = {
3636 1.1 christos { "file", &cfg_type_qstring, 0 },
3637 1.1 christos { "versions", &cfg_type_logversions, 0 },
3638 1.1 christos { "size", &cfg_type_size, 0 },
3639 1.1 christos { "suffix", &cfg_type_logsuffix, 0 },
3640 1.1 christos { NULL, NULL, 0 }
3641 1.1 christos };
3642 1.1 christos
3643 1.1 christos static isc_result_t
3644 1.1 christos parse_logfile(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
3645 1.1 christos isc_result_t result;
3646 1.1 christos cfg_obj_t *obj = NULL;
3647 1.1 christos const cfg_tuplefielddef_t *fields = type->of;
3648 1.1 christos
3649 1.1 christos CHECK(cfg_create_tuple(pctx, type, &obj));
3650 1.1 christos
3651 1.1 christos /* Parse the mandatory "file" field */
3652 1.1 christos CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
3653 1.1 christos
3654 1.1 christos /* Parse "versions" and "size" fields in any order. */
3655 1.1 christos for (;;) {
3656 1.1 christos CHECK(cfg_peektoken(pctx, 0));
3657 1.1 christos if (pctx->token.type == isc_tokentype_string) {
3658 1.1 christos CHECK(cfg_gettoken(pctx, 0));
3659 1.1 christos if (strcasecmp(TOKEN_STRING(pctx),
3660 1.1 christos "versions") == 0 &&
3661 1.1 christos obj->value.tuple[1] == NULL) {
3662 1.1 christos CHECK(cfg_parse_obj(pctx, fields[1].type,
3663 1.1 christos &obj->value.tuple[1]));
3664 1.1 christos } else if (strcasecmp(TOKEN_STRING(pctx),
3665 1.1 christos "size") == 0 &&
3666 1.1 christos obj->value.tuple[2] == NULL) {
3667 1.1 christos CHECK(cfg_parse_obj(pctx, fields[2].type,
3668 1.1 christos &obj->value.tuple[2]));
3669 1.1 christos } else if (strcasecmp(TOKEN_STRING(pctx),
3670 1.1 christos "suffix") == 0 &&
3671 1.1 christos obj->value.tuple[3] == NULL) {
3672 1.1 christos CHECK(cfg_parse_obj(pctx, fields[3].type,
3673 1.1 christos &obj->value.tuple[3]));
3674 1.1 christos } else {
3675 1.1 christos break;
3676 1.1 christos }
3677 1.1 christos } else {
3678 1.1 christos break;
3679 1.1 christos }
3680 1.1 christos }
3681 1.1 christos
3682 1.1 christos /* Create void objects for missing optional values. */
3683 1.1 christos if (obj->value.tuple[1] == NULL)
3684 1.1 christos CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[1]));
3685 1.1 christos if (obj->value.tuple[2] == NULL)
3686 1.1 christos CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[2]));
3687 1.1 christos if (obj->value.tuple[3] == NULL)
3688 1.1 christos CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[3]));
3689 1.1 christos
3690 1.1 christos *ret = obj;
3691 1.1 christos return (ISC_R_SUCCESS);
3692 1.1 christos
3693 1.1 christos cleanup:
3694 1.1 christos CLEANUP_OBJ(obj);
3695 1.1 christos return (result);
3696 1.1 christos }
3697 1.1 christos
3698 1.1 christos static void
3699 1.1 christos print_logfile(cfg_printer_t *pctx, const cfg_obj_t *obj) {
3700 1.1 christos cfg_print_obj(pctx, obj->value.tuple[0]); /* file */
3701 1.1 christos if (obj->value.tuple[1]->type->print != cfg_print_void) {
3702 1.1 christos cfg_print_cstr(pctx, " versions ");
3703 1.1 christos cfg_print_obj(pctx, obj->value.tuple[1]);
3704 1.1 christos }
3705 1.1 christos if (obj->value.tuple[2]->type->print != cfg_print_void) {
3706 1.1 christos cfg_print_cstr(pctx, " size ");
3707 1.1 christos cfg_print_obj(pctx, obj->value.tuple[2]);
3708 1.1 christos }
3709 1.1 christos if (obj->value.tuple[3]->type->print != cfg_print_void) {
3710 1.1 christos cfg_print_cstr(pctx, " suffix ");
3711 1.1 christos cfg_print_obj(pctx, obj->value.tuple[3]);
3712 1.1 christos }
3713 1.1 christos }
3714 1.1 christos
3715 1.1 christos
3716 1.1 christos static void
3717 1.1 christos doc_logfile(cfg_printer_t *pctx, const cfg_type_t *type) {
3718 1.1 christos UNUSED(type);
3719 1.1 christos cfg_print_cstr(pctx, "<quoted_string>");
3720 1.1 christos cfg_print_cstr(pctx, " ");
3721 1.1 christos cfg_print_cstr(pctx, "[ versions ( unlimited | <integer> ) ]");
3722 1.1 christos cfg_print_cstr(pctx, " ");
3723 1.1 christos cfg_print_cstr(pctx, "[ size <size> ]");
3724 1.1 christos cfg_print_cstr(pctx, " ");
3725 1.1 christos cfg_print_cstr(pctx, "[ suffix ( increment | timestamp ) ]");
3726 1.1 christos }
3727 1.1 christos
3728 1.1 christos static cfg_type_t cfg_type_logfile = {
3729 1.1 christos "log_file", parse_logfile, print_logfile, doc_logfile,
3730 1.1 christos &cfg_rep_tuple, logfile_fields
3731 1.1 christos };
3732 1.1 christos
3733 1.1 christos /*% An IPv4 address with optional dscp and port, "*" accepted as wildcard. */
3734 1.1 christos static cfg_type_t cfg_type_sockaddr4wild = {
3735 1.1 christos "sockaddr4wild", cfg_parse_sockaddr, cfg_print_sockaddr,
3736 1.1 christos cfg_doc_sockaddr, &cfg_rep_sockaddr, &sockaddr4wild_flags
3737 1.1 christos };
3738 1.1 christos
3739 1.1 christos /*% An IPv6 address with optional port, "*" accepted as wildcard. */
3740 1.1 christos static cfg_type_t cfg_type_sockaddr6wild = {
3741 1.1 christos "v6addrportwild", cfg_parse_sockaddr, cfg_print_sockaddr,
3742 1.1 christos cfg_doc_sockaddr, &cfg_rep_sockaddr, &sockaddr6wild_flags
3743 1.1 christos };
3744 1.1 christos
3745 1.1 christos /*%
3746 1.1 christos * rndc
3747 1.1 christos */
3748 1.1 christos
3749 1.1 christos static cfg_clausedef_t
3750 1.1 christos rndcconf_options_clauses[] = {
3751 1.1 christos { "default-key", &cfg_type_astring, 0 },
3752 1.1 christos { "default-port", &cfg_type_uint32, 0 },
3753 1.1 christos { "default-server", &cfg_type_astring, 0 },
3754 1.1 christos { "default-source-address", &cfg_type_netaddr4wild, 0 },
3755 1.1 christos { "default-source-address-v6", &cfg_type_netaddr6wild, 0 },
3756 1.1 christos { NULL, NULL, 0 }
3757 1.1 christos };
3758 1.1 christos
3759 1.1 christos static cfg_clausedef_t *
3760 1.1 christos rndcconf_options_clausesets[] = {
3761 1.1 christos rndcconf_options_clauses,
3762 1.1 christos NULL
3763 1.1 christos };
3764 1.1 christos
3765 1.1 christos static cfg_type_t cfg_type_rndcconf_options = {
3766 1.1 christos "rndcconf_options", cfg_parse_map, cfg_print_map, cfg_doc_map,
3767 1.1 christos &cfg_rep_map, rndcconf_options_clausesets
3768 1.1 christos };
3769 1.1 christos
3770 1.1 christos static cfg_clausedef_t
3771 1.1 christos rndcconf_server_clauses[] = {
3772 1.1 christos { "key", &cfg_type_astring, 0 },
3773 1.1 christos { "port", &cfg_type_uint32, 0 },
3774 1.1 christos { "source-address", &cfg_type_netaddr4wild, 0 },
3775 1.1 christos { "source-address-v6", &cfg_type_netaddr6wild, 0 },
3776 1.1 christos { "addresses", &cfg_type_bracketed_sockaddrnameportlist, 0 },
3777 1.1 christos { NULL, NULL, 0 }
3778 1.1 christos };
3779 1.1 christos
3780 1.1 christos static cfg_clausedef_t *
3781 1.1 christos rndcconf_server_clausesets[] = {
3782 1.1 christos rndcconf_server_clauses,
3783 1.1 christos NULL
3784 1.1 christos };
3785 1.1 christos
3786 1.1 christos static cfg_type_t cfg_type_rndcconf_server = {
3787 1.1 christos "rndcconf_server", cfg_parse_named_map, cfg_print_map, cfg_doc_map,
3788 1.1 christos &cfg_rep_map, rndcconf_server_clausesets
3789 1.1 christos };
3790 1.1 christos
3791 1.1 christos static cfg_clausedef_t
3792 1.1 christos rndcconf_clauses[] = {
3793 1.1 christos { "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
3794 1.1 christos { "server", &cfg_type_rndcconf_server, CFG_CLAUSEFLAG_MULTI },
3795 1.1 christos { "options", &cfg_type_rndcconf_options, 0 },
3796 1.1 christos { NULL, NULL, 0 }
3797 1.1 christos };
3798 1.1 christos
3799 1.1 christos static cfg_clausedef_t *
3800 1.1 christos rndcconf_clausesets[] = {
3801 1.1 christos rndcconf_clauses,
3802 1.1 christos NULL
3803 1.1 christos };
3804 1.1 christos
3805 1.1 christos LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndcconf = {
3806 1.1 christos "rndcconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
3807 1.1 christos &cfg_rep_map, rndcconf_clausesets
3808 1.1 christos };
3809 1.1 christos
3810 1.1 christos static cfg_clausedef_t
3811 1.1 christos rndckey_clauses[] = {
3812 1.1 christos { "key", &cfg_type_key, 0 },
3813 1.1 christos { NULL, NULL, 0 }
3814 1.1 christos };
3815 1.1 christos
3816 1.1 christos static cfg_clausedef_t *
3817 1.1 christos rndckey_clausesets[] = {
3818 1.1 christos rndckey_clauses,
3819 1.1 christos NULL
3820 1.1 christos };
3821 1.1 christos
3822 1.1 christos LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndckey = {
3823 1.1 christos "rndckey", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
3824 1.1 christos &cfg_rep_map, rndckey_clausesets
3825 1.1 christos };
3826 1.1 christos
3827 1.1 christos /*
3828 1.1 christos * session.key has exactly the same syntax as rndc.key, but it's defined
3829 1.1 christos * separately for clarity (and so we can extend it someday, if needed).
3830 1.1 christos */
3831 1.1 christos LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_sessionkey = {
3832 1.1 christos "sessionkey", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
3833 1.1 christos &cfg_rep_map, rndckey_clausesets
3834 1.1 christos };
3835 1.1 christos
3836 1.1 christos static cfg_tuplefielddef_t nameport_fields[] = {
3837 1.1 christos { "name", &cfg_type_astring, 0 },
3838 1.1 christos { "port", &cfg_type_optional_port, 0 },
3839 1.1 christos { "dscp", &cfg_type_optional_dscp, 0 },
3840 1.1 christos { NULL, NULL, 0 }
3841 1.1 christos };
3842 1.1 christos
3843 1.1 christos static cfg_type_t cfg_type_nameport = {
3844 1.1 christos "nameport", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
3845 1.1 christos &cfg_rep_tuple, nameport_fields
3846 1.1 christos };
3847 1.1 christos
3848 1.1 christos static void
3849 1.1 christos doc_sockaddrnameport(cfg_printer_t *pctx, const cfg_type_t *type) {
3850 1.1 christos UNUSED(type);
3851 1.1 christos cfg_print_cstr(pctx, "( ");
3852 1.1 christos cfg_print_cstr(pctx, "<quoted_string>");
3853 1.1 christos cfg_print_cstr(pctx, " ");
3854 1.1 christos cfg_print_cstr(pctx, "[ port <integer> ]");
3855 1.1 christos cfg_print_cstr(pctx, " ");
3856 1.1 christos cfg_print_cstr(pctx, "[ dscp <integer> ]");
3857 1.1 christos cfg_print_cstr(pctx, " | ");
3858 1.1 christos cfg_print_cstr(pctx, "<ipv4_address>");
3859 1.1 christos cfg_print_cstr(pctx, " ");
3860 1.1 christos cfg_print_cstr(pctx, "[ port <integer> ]");
3861 1.1 christos cfg_print_cstr(pctx, " ");
3862 1.1 christos cfg_print_cstr(pctx, "[ dscp <integer> ]");
3863 1.1 christos cfg_print_cstr(pctx, " | ");
3864 1.1 christos cfg_print_cstr(pctx, "<ipv6_address>");
3865 1.1 christos cfg_print_cstr(pctx, " ");
3866 1.1 christos cfg_print_cstr(pctx, "[ port <integer> ]");
3867 1.1 christos cfg_print_cstr(pctx, " ");
3868 1.1 christos cfg_print_cstr(pctx, "[ dscp <integer> ]");
3869 1.1 christos cfg_print_cstr(pctx, " )");
3870 1.1 christos }
3871 1.1 christos
3872 1.1 christos static isc_result_t
3873 1.1 christos parse_sockaddrnameport(cfg_parser_t *pctx, const cfg_type_t *type,
3874 1.1 christos cfg_obj_t **ret)
3875 1.1 christos {
3876 1.1 christos isc_result_t result;
3877 1.1 christos cfg_obj_t *obj = NULL;
3878 1.1 christos UNUSED(type);
3879 1.1 christos
3880 1.1 christos CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
3881 1.1 christos if (pctx->token.type == isc_tokentype_string ||
3882 1.1 christos pctx->token.type == isc_tokentype_qstring) {
3883 1.1 christos if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V6OK))
3884 1.1 christos CHECK(cfg_parse_sockaddr(pctx, &cfg_type_sockaddr,
3885 1.1 christos ret));
3886 1.1 christos else {
3887 1.1 christos const cfg_tuplefielddef_t *fields =
3888 1.1 christos cfg_type_nameport.of;
3889 1.1 christos CHECK(cfg_create_tuple(pctx, &cfg_type_nameport,
3890 1.1 christos &obj));
3891 1.1 christos CHECK(cfg_parse_obj(pctx, fields[0].type,
3892 1.1 christos &obj->value.tuple[0]));
3893 1.1 christos CHECK(cfg_parse_obj(pctx, fields[1].type,
3894 1.1 christos &obj->value.tuple[1]));
3895 1.1 christos CHECK(cfg_parse_obj(pctx, fields[2].type,
3896 1.1 christos &obj->value.tuple[2]));
3897 1.1 christos *ret = obj;
3898 1.1 christos obj = NULL;
3899 1.1 christos }
3900 1.1 christos } else {
3901 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR,
3902 1.1 christos "expected IP address or hostname");
3903 1.1 christos return (ISC_R_UNEXPECTEDTOKEN);
3904 1.1 christos }
3905 1.1 christos cleanup:
3906 1.1 christos CLEANUP_OBJ(obj);
3907 1.1 christos return (result);
3908 1.1 christos }
3909 1.1 christos
3910 1.1 christos static cfg_type_t cfg_type_sockaddrnameport = {
3911 1.1 christos "sockaddrnameport_element", parse_sockaddrnameport, NULL,
3912 1.1 christos doc_sockaddrnameport, NULL, NULL
3913 1.1 christos };
3914 1.1 christos
3915 1.1 christos static cfg_type_t cfg_type_bracketed_sockaddrnameportlist = {
3916 1.1 christos "bracketed_sockaddrnameportlist", cfg_parse_bracketed_list,
3917 1.1 christos cfg_print_bracketed_list, cfg_doc_bracketed_list,
3918 1.1 christos &cfg_rep_list, &cfg_type_sockaddrnameport
3919 1.1 christos };
3920 1.1 christos
3921 1.1 christos /*%
3922 1.1 christos * A list of socket addresses or name with an optional default port,
3923 1.1 christos * as used in the dual-stack-servers option. E.g.,
3924 1.1 christos * "port 1234 { dual-stack-servers.net; 10.0.0.1; 1::2 port 69; }"
3925 1.1 christos */
3926 1.1 christos static cfg_tuplefielddef_t nameportiplist_fields[] = {
3927 1.1 christos { "port", &cfg_type_optional_port, 0 },
3928 1.1 christos { "addresses", &cfg_type_bracketed_sockaddrnameportlist, 0 },
3929 1.1 christos { NULL, NULL, 0 }
3930 1.1 christos };
3931 1.1 christos
3932 1.1 christos static cfg_type_t cfg_type_nameportiplist = {
3933 1.1 christos "nameportiplist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
3934 1.1 christos &cfg_rep_tuple, nameportiplist_fields
3935 1.1 christos };
3936 1.1 christos
3937 1.1 christos /*%
3938 1.1 christos * masters element.
3939 1.1 christos */
3940 1.1 christos
3941 1.1 christos static void
3942 1.1 christos doc_masterselement(cfg_printer_t *pctx, const cfg_type_t *type) {
3943 1.1 christos UNUSED(type);
3944 1.1 christos cfg_print_cstr(pctx, "( ");
3945 1.1 christos cfg_print_cstr(pctx, "<masters>");
3946 1.1 christos cfg_print_cstr(pctx, " | ");
3947 1.1 christos cfg_print_cstr(pctx, "<ipv4_address>");
3948 1.1 christos cfg_print_cstr(pctx, " ");
3949 1.1 christos cfg_print_cstr(pctx, "[ port <integer> ]");
3950 1.1 christos cfg_print_cstr(pctx, " | ");
3951 1.1 christos cfg_print_cstr(pctx, "<ipv6_address>");
3952 1.1 christos cfg_print_cstr(pctx, " ");
3953 1.1 christos cfg_print_cstr(pctx, "[ port <integer> ]");
3954 1.1 christos cfg_print_cstr(pctx, " )");
3955 1.1 christos }
3956 1.1 christos
3957 1.1 christos static isc_result_t
3958 1.1 christos parse_masterselement(cfg_parser_t *pctx, const cfg_type_t *type,
3959 1.1 christos cfg_obj_t **ret)
3960 1.1 christos {
3961 1.1 christos isc_result_t result;
3962 1.1 christos cfg_obj_t *obj = NULL;
3963 1.1 christos UNUSED(type);
3964 1.1 christos
3965 1.1 christos CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
3966 1.1 christos if (pctx->token.type == isc_tokentype_string ||
3967 1.1 christos pctx->token.type == isc_tokentype_qstring) {
3968 1.1 christos if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V6OK))
3969 1.1 christos CHECK(cfg_parse_sockaddr(pctx, &cfg_type_sockaddr,
3970 1.1 christos ret));
3971 1.1 christos else
3972 1.1 christos CHECK(cfg_parse_astring(pctx, &cfg_type_astring, ret));
3973 1.1 christos } else {
3974 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR,
3975 1.1 christos "expected IP address or masters name");
3976 1.1 christos return (ISC_R_UNEXPECTEDTOKEN);
3977 1.1 christos }
3978 1.1 christos cleanup:
3979 1.1 christos CLEANUP_OBJ(obj);
3980 1.1 christos return (result);
3981 1.1 christos }
3982 1.1 christos
3983 1.1 christos static cfg_type_t cfg_type_masterselement = {
3984 1.1 christos "masters_element", parse_masterselement, NULL,
3985 1.1 christos doc_masterselement, NULL, NULL
3986 1.1 christos };
3987 1.1 christos
3988 1.1 christos static isc_result_t
3989 1.1 christos parse_ttlval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
3990 1.1 christos isc_result_t result;
3991 1.1 christos cfg_obj_t *obj = NULL;
3992 1.1 christos isc_uint32_t ttl;
3993 1.1 christos
3994 1.1 christos UNUSED(type);
3995 1.1 christos
3996 1.1 christos CHECK(cfg_gettoken(pctx, 0));
3997 1.1 christos if (pctx->token.type != isc_tokentype_string) {
3998 1.1 christos result = ISC_R_UNEXPECTEDTOKEN;
3999 1.1 christos goto cleanup;
4000 1.1 christos }
4001 1.1 christos
4002 1.1 christos result = dns_ttl_fromtext(&pctx->token.value.as_textregion, &ttl);
4003 1.1 christos if (result == ISC_R_RANGE ) {
4004 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR, "TTL out of range ");
4005 1.1 christos return (result);
4006 1.1 christos } else if (result != ISC_R_SUCCESS)
4007 1.1 christos goto cleanup;
4008 1.1 christos
4009 1.1 christos CHECK(cfg_create_obj(pctx, &cfg_type_uint32, &obj));
4010 1.1 christos obj->value.uint32 = ttl;
4011 1.1 christos *ret = obj;
4012 1.1 christos return (ISC_R_SUCCESS);
4013 1.1 christos
4014 1.1 christos cleanup:
4015 1.1 christos cfg_parser_error(pctx, CFG_LOG_NEAR,
4016 1.1 christos "expected integer and optional unit");
4017 1.1 christos return (result);
4018 1.1 christos }
4019 1.1 christos
4020 1.1 christos /*%
4021 1.1 christos * A TTL value (number + optional unit).
4022 1.1 christos */
4023 1.1 christos static cfg_type_t cfg_type_ttlval = {
4024 1.1 christos "ttlval", parse_ttlval, cfg_print_uint64, cfg_doc_terminal,
4025 1.1 christos &cfg_rep_uint64, NULL
4026 1.1 christos };
4027 1.1 christos
4028 1.1 christos static isc_result_t
4029 1.1 christos parse_maxttl(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
4030 1.1 christos return (parse_enum_or_other(pctx, type, &cfg_type_ttlval, ret));
4031 1.1 christos }
4032 1.1 christos
4033 1.1 christos static void
4034 1.1 christos doc_maxttl(cfg_printer_t *pctx, const cfg_type_t *type) {
4035 1.1 christos doc_enum_or_other(pctx, type, &cfg_type_ttlval);
4036 1.1 christos }
4037 1.1 christos
4038 1.1 christos /*%
4039 1.1 christos * A size or "unlimited", but not "default".
4040 1.1 christos */
4041 1.1 christos static const char *maxttl_enums[] = { "unlimited", NULL };
4042 1.1 christos static cfg_type_t cfg_type_maxttl = {
4043 1.1 christos "maxttl_no_default", parse_maxttl, cfg_print_ustring, doc_maxttl,
4044 1.1 christos &cfg_rep_string, maxttl_enums
4045 1.1 christos };
4046 1.1 christos
4047 1.1 christos static int cmp_clause(const void *ap, const void *bp) {
4048 1.1 christos const cfg_clausedef_t *a = (const cfg_clausedef_t *)ap;
4049 1.1 christos const cfg_clausedef_t *b = (const cfg_clausedef_t *)bp;
4050 1.1 christos return (strcmp(a->name, b->name));
4051 1.1 christos }
4052 1.1 christos
4053 1.1 christos isc_boolean_t
4054 1.1 christos cfg_clause_validforzone(const char *name, unsigned int ztype) {
4055 1.1 christos const cfg_clausedef_t *clause;
4056 1.1 christos isc_boolean_t valid = ISC_FALSE;
4057 1.1 christos
4058 1.1 christos for (clause = zone_clauses; clause->name != NULL; clause++) {
4059 1.1 christos if ((clause->flags & ztype) == 0 ||
4060 1.1 christos strcmp(clause->name, name) != 0)
4061 1.1 christos {
4062 1.1 christos continue;
4063 1.1 christos }
4064 1.1 christos valid = ISC_TRUE;
4065 1.1 christos }
4066 1.1 christos for (clause = zone_only_clauses; clause->name != NULL; clause++) {
4067 1.1 christos if ((clause->flags & ztype) == 0 ||
4068 1.1 christos strcmp(clause->name, name) != 0)
4069 1.1 christos {
4070 1.1 christos continue;
4071 1.1 christos }
4072 1.1 christos valid = ISC_TRUE;
4073 1.1 christos }
4074 1.1 christos
4075 1.1 christos return (valid);
4076 1.1 christos }
4077 1.1 christos
4078 1.1 christos void
4079 1.1 christos cfg_print_zonegrammar(const unsigned int zonetype,
4080 1.1 christos void (*f)(void *closure, const char *text, int textlen),
4081 1.1 christos void *closure)
4082 1.1 christos {
4083 1.1 christos #define NCLAUSES \
4084 1.1 christos (((sizeof(zone_clauses) + sizeof(zone_only_clauses)) / \
4085 1.1 christos sizeof(clause[0])) - 1)
4086 1.1 christos
4087 1.1 christos cfg_printer_t pctx;
4088 1.1 christos cfg_clausedef_t *clause = NULL;
4089 1.1 christos cfg_clausedef_t clauses[NCLAUSES];
4090 1.1 christos
4091 1.1 christos pctx.f = f;
4092 1.1 christos pctx.closure = closure;
4093 1.1 christos pctx.indent = 0;
4094 1.1 christos pctx.flags = 0;
4095 1.1 christos
4096 1.1 christos memmove(clauses, zone_clauses, sizeof(zone_clauses));
4097 1.1 christos memmove(clauses + sizeof(zone_clauses)/sizeof(zone_clauses[0]) - 1,
4098 1.1 christos zone_only_clauses, sizeof(zone_only_clauses));
4099 1.1 christos qsort(clauses, NCLAUSES - 1, sizeof(clause[0]), cmp_clause);
4100 1.1 christos
4101 1.1 christos cfg_print_cstr(&pctx, "zone <string> [ <class> ] {\n");
4102 1.1 christos pctx.indent++;
4103 1.1 christos
4104 1.1 christos switch (zonetype) {
4105 1.1 christos case CFG_ZONE_MASTER:
4106 1.1 christos cfg_print_indent(&pctx);
4107 1.1 christos cfg_print_cstr(&pctx, "type ( master | primary );\n");
4108 1.1 christos break;
4109 1.1 christos case CFG_ZONE_SLAVE:
4110 1.1 christos cfg_print_indent(&pctx);
4111 1.1 christos cfg_print_cstr(&pctx, "type ( slave | secondary );\n");
4112 1.1 christos break;
4113 1.1 christos case CFG_ZONE_STUB:
4114 1.1 christos cfg_print_indent(&pctx);
4115 1.1 christos cfg_print_cstr(&pctx, "type stub;\n");
4116 1.1 christos break;
4117 1.1 christos case CFG_ZONE_HINT:
4118 1.1 christos cfg_print_indent(&pctx);
4119 1.1 christos cfg_print_cstr(&pctx, "type hint;\n");
4120 1.1 christos break;
4121 1.1 christos case CFG_ZONE_FORWARD:
4122 1.1 christos cfg_print_indent(&pctx);
4123 1.1 christos cfg_print_cstr(&pctx, "type forward;\n");
4124 1.1 christos break;
4125 1.1 christos case CFG_ZONE_STATICSTUB:
4126 1.1 christos cfg_print_indent(&pctx);
4127 1.1 christos cfg_print_cstr(&pctx, "type static-stub;\n");
4128 1.1 christos break;
4129 1.1 christos case CFG_ZONE_REDIRECT:
4130 1.1 christos cfg_print_indent(&pctx);
4131 1.1 christos cfg_print_cstr(&pctx, "type redirect;\n");
4132 1.1 christos break;
4133 1.1 christos case CFG_ZONE_DELEGATION:
4134 1.1 christos cfg_print_indent(&pctx);
4135 1.1 christos cfg_print_cstr(&pctx, "type delegation-only;\n");
4136 1.1 christos break;
4137 1.1 christos case CFG_ZONE_INVIEW:
4138 1.1 christos /* no zone type is specified for these */
4139 1.1 christos break;
4140 1.1 christos default:
4141 1.1 christos INSIST(0);
4142 1.1 christos }
4143 1.1 christos
4144 1.1 christos for (clause = clauses; clause->name != NULL; clause++) {
4145 1.1 christos if ((clause->flags & zonetype) == 0 ||
4146 1.1 christos strcasecmp(clause->name, "type") == 0) {
4147 1.1 christos continue;
4148 1.1 christos }
4149 1.1 christos cfg_print_indent(&pctx);
4150 1.1 christos cfg_print_cstr(&pctx, clause->name);
4151 1.1 christos cfg_print_cstr(&pctx, " ");
4152 1.1 christos cfg_doc_obj(&pctx, clause->type);
4153 1.1 christos cfg_print_cstr(&pctx, ";");
4154 1.1 christos cfg_print_clauseflags(&pctx, clause->flags);
4155 1.1 christos cfg_print_cstr(&pctx, "\n");
4156 1.1 christos }
4157 1.1 christos
4158 1.1 christos pctx.indent--;
4159 1.1 christos cfg_print_cstr(&pctx, "};\n");
4160 1.1 christos }
4161