Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / bin / named / config.c
blobfc650ec67c64f4a90d56371307a2f34449169a8e
1 /*
2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2001, 2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: config.c,v 1.11.2.6 2004/04/19 23:15:38 marka Exp $ */
20 #include <config.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include <isc/buffer.h>
26 #include <isc/log.h>
27 #include <isc/mem.h>
28 #include <isc/region.h>
29 #include <isc/result.h>
30 #include <isc/sockaddr.h>
31 #include <isc/util.h>
33 #include <isccfg/cfg.h>
35 #include <dns/fixedname.h>
36 #include <dns/name.h>
37 #include <dns/rdataclass.h>
38 #include <dns/tsig.h>
39 #include <dns/zone.h>
41 #include <named/config.h>
42 #include <named/globals.h>
44 static char defaultconf[] = "\
45 options {\n\
46 # blackhole {none;};\n"
47 #ifndef WIN32
48 " coresize default;\n\
49 datasize default;\n\
50 files default;\n\
51 stacksize default;\n"
52 #endif
53 " deallocate-on-exit true;\n\
54 # directory <none>\n\
55 dump-file \"named_dump.db\";\n\
56 fake-iquery no;\n\
57 has-old-clients false;\n\
58 heartbeat-interval 60;\n\
59 host-statistics no;\n\
60 interface-interval 60;\n\
61 listen-on {any;};\n\
62 listen-on-v6 {none;};\n\
63 match-mapped-addresses no;\n\
64 memstatistics-file \"named.memstats\";\n\
65 multiple-cnames no;\n\
66 # named-xfer <obsolete>;\n\
67 # pid-file \"" NS_LOCALSTATEDIR "/named.pid\"; /* or /lwresd.pid */\n\
68 port 53;\n\
70 #ifdef PATH_RANDOMDEV
72 random-device \"" PATH_RANDOMDEV "\";\n\
74 #endif
76 recursive-clients 1000;\n\
77 rrset-order {order cyclic;};\n\
78 serial-queries 20;\n\
79 serial-query-rate 20;\n\
80 statistics-file \"named.stats\";\n\
81 statistics-interval 60;\n\
82 tcp-clients 100;\n\
83 # tkey-dhkey <none>\n\
84 # tkey-gssapi-credential <none>\n\
85 # tkey-domain <none>\n\
86 transfers-per-ns 2;\n\
87 transfers-in 10;\n\
88 transfers-out 10;\n\
89 treat-cr-as-space true;\n\
90 use-id-pool true;\n\
91 use-ixfr true;\n\
92 version \""VERSION"\";\n\
93 \n\
94 /* view */\n\
95 allow-notify {none;};\n\
96 allow-update-forwarding {none;};\n\
97 allow-recursion {any;};\n\
98 allow-v6-synthesis {none;};\n\
99 # sortlist <none>\n\
100 # topology <none>\n\
101 auth-nxdomain false;\n\
102 minimal-responses false;\n\
103 recursion true;\n\
104 provide-ixfr true;\n\
105 request-ixfr true;\n\
106 fetch-glue no;\n\
107 rfc2308-type1 no;\n\
108 additional-from-auth true;\n\
109 additional-from-cache true;\n\
110 query-source address *;\n\
111 query-source-v6 address *;\n\
112 notify-source *;\n\
113 notify-source-v6 *;\n\
114 cleaning-interval 60;\n\
115 min-roots 2;\n\
116 lame-ttl 600;\n\
117 max-ncache-ttl 10800; /* 3 hours */\n\
118 max-cache-ttl 604800; /* 1 week */\n\
119 transfer-format many-answers;\n\
120 max-cache-size 0;\n\
121 check-names master ignore;\n\
122 check-names slave ignore;\n\
123 check-names response ignore;\n\
125 /* zone */\n\
126 allow-query {any;};\n\
127 allow-transfer {any;};\n\
128 notify yes;\n\
129 # also-notify <none>\n\
130 dialup no;\n\
131 # forward <none>\n\
132 # forwarders <none>\n\
133 maintain-ixfr-base no;\n\
134 # max-ixfr-log-size <obsolete>\n\
135 transfer-source *;\n\
136 transfer-source-v6 *;\n\
137 max-transfer-time-in 120;\n\
138 max-transfer-time-out 120;\n\
139 max-transfer-idle-in 60;\n\
140 max-transfer-idle-out 60;\n\
141 max-retry-time 1209600; /* 2 weeks */\n\
142 min-retry-time 500;\n\
143 max-refresh-time 2419200; /* 4 weeks */\n\
144 min-refresh-time 300;\n\
145 sig-validity-interval 30; /* days */\n\
146 zone-statistics false;\n\
147 };";
149 isc_result_t
150 ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) {
151 isc_buffer_t b;
153 isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1);
154 isc_buffer_add(&b, sizeof(defaultconf) - 1);
155 return (cfg_parse_buffer(parser, &b, &cfg_type_namedconf, conf));
158 isc_result_t
159 ns_config_get(cfg_obj_t **maps, const char* name, cfg_obj_t **obj) {
160 int i;
162 for (i = 0; ; i++) {
163 if (maps[i] == NULL)
164 return (ISC_R_NOTFOUND);
165 if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS)
166 return (ISC_R_SUCCESS);
171 ns_config_listcount(cfg_obj_t *list) {
172 cfg_listelt_t *e;
173 int i = 0;
175 for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e))
176 i++;
178 return (i);
181 isc_result_t
182 ns_config_getclass(cfg_obj_t *classobj, dns_rdataclass_t defclass,
183 dns_rdataclass_t *classp) {
184 char *str;
185 isc_textregion_t r;
186 isc_result_t result;
188 if (!cfg_obj_isstring(classobj)) {
189 *classp = defclass;
190 return (ISC_R_SUCCESS);
192 str = cfg_obj_asstring(classobj);
193 r.base = str;
194 r.length = strlen(str);
195 result = dns_rdataclass_fromtext(classp, &r);
196 if (result != ISC_R_SUCCESS)
197 cfg_obj_log(classobj, ns_g_lctx, ISC_LOG_ERROR,
198 "unknown class '%s'", str);
199 return (result);
202 dns_zonetype_t
203 ns_config_getzonetype(cfg_obj_t *zonetypeobj) {
204 dns_zonetype_t ztype = dns_zone_none;
205 char *str;
207 str = cfg_obj_asstring(zonetypeobj);
208 if (strcasecmp(str, "master") == 0)
209 ztype = dns_zone_master;
210 else if (strcasecmp(str, "slave") == 0)
211 ztype = dns_zone_slave;
212 else if (strcasecmp(str, "stub") == 0)
213 ztype = dns_zone_stub;
214 else
215 INSIST(0);
216 return (ztype);
219 isc_result_t
220 ns_config_getiplist(cfg_obj_t *config, cfg_obj_t *list,
221 in_port_t defport, isc_mem_t *mctx,
222 isc_sockaddr_t **addrsp, isc_uint32_t *countp)
224 int count, i = 0;
225 cfg_obj_t *addrlist;
226 cfg_obj_t *portobj;
227 cfg_listelt_t *element;
228 isc_sockaddr_t *addrs;
229 in_port_t port;
230 isc_result_t result;
232 INSIST(addrsp != NULL && *addrsp == NULL);
234 addrlist = cfg_tuple_get(list, "addresses");
235 count = ns_config_listcount(addrlist);
237 portobj = cfg_tuple_get(list, "port");
238 if (cfg_obj_isuint32(portobj)) {
239 isc_uint32_t val = cfg_obj_asuint32(portobj);
240 if (val > ISC_UINT16_MAX) {
241 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
242 "port '%u' out of range", val);
243 return (ISC_R_RANGE);
245 port = (in_port_t) val;
246 } else if (defport != 0)
247 port = defport;
248 else {
249 result = ns_config_getport(config, &port);
250 if (result != ISC_R_SUCCESS)
251 return (result);
254 addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
255 if (addrs == NULL)
256 return (ISC_R_NOMEMORY);
258 for (element = cfg_list_first(addrlist);
259 element != NULL;
260 element = cfg_list_next(element), i++)
262 INSIST(i < count);
263 addrs[i] = *cfg_obj_assockaddr(cfg_listelt_value(element));
264 if (isc_sockaddr_getport(&addrs[i]) == 0)
265 isc_sockaddr_setport(&addrs[i], port);
267 INSIST(i == count);
269 *addrsp = addrs;
270 *countp = count;
272 return (ISC_R_SUCCESS);
275 void
276 ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
277 isc_uint32_t count)
279 INSIST(addrsp != NULL && *addrsp != NULL);
281 isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
282 *addrsp = NULL;
285 isc_result_t
286 ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx,
287 isc_sockaddr_t **addrsp, dns_name_t ***keysp,
288 isc_uint32_t *countp)
290 isc_uint32_t count, i = 0;
291 isc_result_t result;
292 cfg_listelt_t *element;
293 cfg_obj_t *addrlist;
294 cfg_obj_t *portobj;
295 in_port_t port;
296 dns_fixedname_t fname;
297 isc_sockaddr_t *addrs = NULL;
298 dns_name_t **keys = NULL;
300 INSIST(addrsp != NULL && *addrsp == NULL);
302 addrlist = cfg_tuple_get(list, "addresses");
303 count = ns_config_listcount(addrlist);
305 portobj = cfg_tuple_get(list, "port");
306 if (cfg_obj_isuint32(portobj)) {
307 isc_uint32_t val = cfg_obj_asuint32(portobj);
308 if (val > ISC_UINT16_MAX) {
309 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
310 "port '%u' out of range", val);
311 return (ISC_R_RANGE);
313 port = (in_port_t) val;
314 } else {
315 result = ns_config_getport(config, &port);
316 if (result != ISC_R_SUCCESS)
317 return (result);
320 result = ISC_R_NOMEMORY;
322 addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
323 if (addrs == NULL)
324 goto cleanup;
326 keys = isc_mem_get(mctx, count * sizeof(dns_name_t *));
327 if (keys == NULL)
328 goto cleanup;
330 for (element = cfg_list_first(addrlist);
331 element != NULL;
332 element = cfg_list_next(element), i++)
334 cfg_obj_t *addr;
335 cfg_obj_t *key;
336 char *keystr;
337 isc_buffer_t b;
339 INSIST(i < count);
341 addr = cfg_tuple_get(cfg_listelt_value(element), "sockaddr");
342 key = cfg_tuple_get(cfg_listelt_value(element), "key");
344 addrs[i] = *cfg_obj_assockaddr(addr);
345 if (isc_sockaddr_getport(&addrs[i]) == 0)
346 isc_sockaddr_setport(&addrs[i], port);
348 keys[i] = NULL;
349 if (!cfg_obj_isstring(key))
350 continue;
351 keys[i] = isc_mem_get(mctx, sizeof(dns_name_t));
352 if (keys[i] == NULL)
353 goto cleanup;
354 dns_name_init(keys[i], NULL);
356 keystr = cfg_obj_asstring(key);
357 isc_buffer_init(&b, keystr, strlen(keystr));
358 isc_buffer_add(&b, strlen(keystr));
359 dns_fixedname_init(&fname);
360 result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
361 dns_rootname, ISC_FALSE, NULL);
362 if (result != ISC_R_SUCCESS)
363 goto cleanup;
364 result = dns_name_dup(dns_fixedname_name(&fname), mctx,
365 keys[i]);
366 if (result != ISC_R_SUCCESS)
367 goto cleanup;
369 INSIST(i == count);
371 *addrsp = addrs;
372 *keysp = keys;
373 *countp = count;
375 return (ISC_R_SUCCESS);
377 cleanup:
378 if (addrs != NULL)
379 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
380 if (keys != NULL) {
381 unsigned int j;
382 for (j = 0 ; j <= i; j++) {
383 if (keys[j] == NULL)
384 continue;
385 if (dns_name_dynamic(keys[j]))
386 dns_name_free(keys[j], mctx);
387 isc_mem_put(mctx, keys[j], sizeof(dns_name_t));
389 isc_mem_put(mctx, keys, count * sizeof(dns_name_t *));
391 return (result);
394 void
395 ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
396 dns_name_t ***keysp, isc_uint32_t count)
398 unsigned int i;
399 dns_name_t **keys = *keysp;
401 INSIST(addrsp != NULL && *addrsp != NULL);
403 isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
404 for (i = 0; i < count; i++) {
405 if (keys[i] == NULL)
406 continue;
407 if (dns_name_dynamic(keys[i]))
408 dns_name_free(keys[i], mctx);
409 isc_mem_put(mctx, keys[i], sizeof(dns_name_t));
411 isc_mem_put(mctx, *keysp, count * sizeof(dns_name_t *));
412 *addrsp = NULL;
413 *keysp = NULL;
416 isc_result_t
417 ns_config_getport(cfg_obj_t *config, in_port_t *portp) {
418 cfg_obj_t *maps[3];
419 cfg_obj_t *options = NULL;
420 cfg_obj_t *portobj = NULL;
421 isc_result_t result;
422 int i;
424 cfg_map_get(config, "options", &options);
425 i = 0;
426 if (options != NULL)
427 maps[i++] = options;
428 maps[i++] = ns_g_defaults;
429 maps[i] = NULL;
431 result = ns_config_get(maps, "port", &portobj);
432 INSIST(result == ISC_R_SUCCESS);
433 if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
434 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
435 "port '%u' out of range",
436 cfg_obj_asuint32(portobj));
437 return (ISC_R_RANGE);
439 *portp = (in_port_t)cfg_obj_asuint32(portobj);
440 return (ISC_R_SUCCESS);
443 isc_result_t
444 ns_config_getkeyalgorithm(const char *str, dns_name_t **name)
446 if (strcasecmp(str, "hmac-md5") == 0 ||
447 strcasecmp(str, "hmac-md5.sig-alg.reg.int") == 0 ||
448 strcasecmp(str, "hmac-md5.sig-alg.reg.int.") == 0)
450 if (name != NULL)
451 *name = dns_tsig_hmacmd5_name;
452 return (ISC_R_SUCCESS);
454 return (ISC_R_NOTFOUND);