diff --git a/CHANGES b/CHANGES index c4b6d5c9fa..61d2553989 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,6 @@ + 762. [feature] named now uses the new configuration parser. + 761. [bug] _REENTRANT was still defined when building with --disable-threads. diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in index 4b141d29c3..2fc3b8ffab 100644 --- a/bin/named/Makefile.in +++ b/bin/named/Makefile.in @@ -13,7 +13,7 @@ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.67 2001/02/04 15:52:39 bwelling Exp $ +# $Id: Makefile.in,v 1.68 2001/03/04 21:21:19 bwelling Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -32,34 +32,37 @@ DBDRIVER_INCLUDES = DBDRIVER_LIBS = CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include \ - ${LWRES_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} \ - ${OMAPI_INCLUDES} ${DBDRIVER_INCLUDES} + ${LWRES_INCLUDES} ${OMAPI_INCLUDES} ${DNS_INCLUDES} \ + ${ISCCFG_INCLUDES} ${ISC_INCLUDES} ${DBDRIVER_INCLUDES} CDEFINES = CWARNINGS = OMAPILIBS = ../../lib/omapi/libomapi.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_OPENSSL_LIBS@ @DNS_GSSAPI_LIBS@ +ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ LWRESLIBS = ../../lib/lwres/liblwres.@A@ OMAPIDEPLIBS = ../../lib/omapi/libomapi.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ +ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ -DEPLIBS = ${LWRESDEPLIBS} ${OMAPIDEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS} +DEPLIBS = ${LWRESDEPLIBS} ${OMAPIDEPLIBS} ${DNSDEPLIBS} \ + ${ISCCFGDEPLIBS} ${ISCDEPLIBS} -LIBS = ${LWRESLIBS} ${OMAPILIBS} ${DNSLIBS} ${ISCLIBS} \ - ${DBDRIVER_LIBS} @LIBS@ +LIBS = ${LWRESLIBS} ${OMAPILIBS} ${DNSLIBS} \ + ${ISCCFGLIBS} ${ISCLIBS} ${DBDRIVER_LIBS} @LIBS@ SUBDIRS = unix TARGETS = named lwresd -OBJS = aclconf.@O@ client.@O@ interfacemgr.@O@ listenlist.@O@ \ - log.@O@ logconf.@O@ main.@O@ notify.@O@ omapi.@O@ \ - omapiconf.@O@ query.@O@ server.@O@ sortlist.@O@ \ +OBJS = aclconf.@O@ client.@O@ config.@O@ interfacemgr.@O@ \ + listenlist.@O@ log.@O@ logconf.@O@ main.@O@ notify.@O@ \ + omapi.@O@ omapiconf.@O@ query.@O@ server.@O@ sortlist.@O@ \ tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \ zoneconf.@O@ \ lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \ @@ -68,9 +71,9 @@ OBJS = aclconf.@O@ client.@O@ interfacemgr.@O@ listenlist.@O@ \ UOBJS = unix/os.@O@ -SRCS = aclconf.c client.c interfacemgr.c listenlist.c \ - log.c logconf.c main.c notify.c omapi.c \ - omapiconf.c query.c server.c sortlist.c \ +SRCS = aclconf.c client.c config.c interfacemgr.c \ + listenlist.c log.c logconf.c main.c notify.c \ + omapi.c omapiconf.c query.c server.c sortlist.c \ tkeyconf.c tsigconf.c update.c xfrout.c \ zoneconf.c \ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \ @@ -86,6 +89,11 @@ main.@O@: main.c -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ -DNS_SYSCONFDIR=\"${sysconfdir}\" -c ${srcdir}/main.c +config.@O@: config.c + ${LIBTOOL} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \ + -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ + -c ${srcdir}/config.c + named: ${OBJS} ${UOBJS} ${DEPLIBS} ${LIBTOOL} ${PURIFY} ${CC} ${CFLAGS} -o $@ ${OBJS} ${UOBJS} ${LIBS} diff --git a/bin/named/aclconf.c b/bin/named/aclconf.c index 6b032f829f..17a36a8f8f 100644 --- a/bin/named/aclconf.c +++ b/bin/named/aclconf.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: aclconf.c,v 1.25 2001/01/09 21:39:39 bwelling Exp $ */ +/* $Id: aclconf.c,v 1.26 2001/03/04 21:21:20 bwelling Exp $ */ #include @@ -46,34 +46,59 @@ ns_aclconfctx_destroy(ns_aclconfctx_t *ctx) { } } +/* + * Find the definition of the named acl whose name is "name". + */ static isc_result_t -convert_named_acl(char *aclname, dns_c_ctx_t *cctx, +get_acl_def(cfg_obj_t *cctx, char *name, cfg_obj_t **ret) { + isc_result_t result; + cfg_obj_t *acls = NULL; + cfg_listelt_t *elt; + + result = cfg_map_get(cctx, "acl", &acls); + if (result != ISC_R_SUCCESS) + return (result); + for (elt = cfg_list_first(acls); + elt != NULL; + elt = cfg_list_next(elt)) { + cfg_obj_t *acl = cfg_listelt_value(elt); + const char *aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name")); + if (strcasecmp(aclname, name) == 0) { + *ret = cfg_tuple_get(acl, "value"); + return (ISC_R_SUCCESS); + } + } + return (ISC_R_NOTFOUND); +} + +static isc_result_t +convert_named_acl(cfg_obj_t *nameobj, cfg_obj_t *cctx, ns_aclconfctx_t *ctx, isc_mem_t *mctx, dns_acl_t **target) { isc_result_t result; - dns_c_acl_t *cacl; + cfg_obj_t *cacl = NULL; dns_acl_t *dacl; + char *aclname = cfg_obj_asstring(nameobj); /* Look for an already-converted version. */ for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache); dacl != NULL; dacl = ISC_LIST_NEXT(dacl, nextincache)) { - if (strcmp(aclname, dacl->name) == 0) { + if (strcasecmp(aclname, dacl->name) == 0) { dns_acl_attach(dacl, target); return (ISC_R_SUCCESS); } } /* Not yet converted. Convert now. */ - result = dns_c_acltable_getacl(cctx->acls, aclname, &cacl); + result = get_acl_def(cctx, aclname, &cacl); if (result != ISC_R_SUCCESS) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, - DNS_LOGMODULE_ACL, ISC_LOG_WARNING, - "undefined ACL '%s'", aclname); + cfg_obj_log(nameobj, dns_lctx, ISC_LOG_WARNING, + "undefined ACL '%s'", aclname); return (result); } - result = ns_acl_fromconfig(cacl->ipml, cctx, ctx, mctx, &dacl); + result = ns_acl_fromconfig(cacl, cctx, ctx, mctx, &dacl); if (result != ISC_R_SUCCESS) return (result); dacl->name = isc_mem_strdup(dacl->mctx, aclname); @@ -85,11 +110,12 @@ convert_named_acl(char *aclname, dns_c_ctx_t *cctx, } static isc_result_t -convert_keyname(char *txtname, isc_mem_t *mctx, dns_name_t *dnsname) { +convert_keyname(cfg_obj_t *keyobj, isc_mem_t *mctx, dns_name_t *dnsname) { isc_result_t result; isc_buffer_t buf; dns_fixedname_t fixname; unsigned int keylen; + const char *txtname = cfg_obj_asstring(keyobj); keylen = strlen(txtname); isc_buffer_init(&buf, txtname, keylen); @@ -98,34 +124,33 @@ convert_keyname(char *txtname, isc_mem_t *mctx, dns_name_t *dnsname) { result = dns_name_fromtext(dns_fixedname_name(&fixname), &buf, dns_rootname, ISC_FALSE, NULL); if (result != ISC_R_SUCCESS) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, - DNS_LOGMODULE_ACL, ISC_LOG_WARNING, - "key name \"%s\" is not a valid domain name", - txtname); + cfg_obj_log(keyobj, dns_lctx, ISC_LOG_WARNING, + "key name '%s' is not a valid domain name", + txtname); return (result); } return (dns_name_dup(dns_fixedname_name(&fixname), mctx, dnsname)); } isc_result_t -ns_acl_fromconfig(dns_c_ipmatchlist_t *caml, - dns_c_ctx_t *cctx, - ns_aclconfctx_t *ctx, - isc_mem_t *mctx, - dns_acl_t **target) +ns_acl_fromconfig(cfg_obj_t *caml, + cfg_obj_t *cctx, + ns_aclconfctx_t *ctx, + isc_mem_t *mctx, + dns_acl_t **target) { isc_result_t result; unsigned int count; dns_acl_t *dacl = NULL; dns_aclelement_t *de; - dns_c_ipmatchelement_t *ce; + cfg_listelt_t *elt; REQUIRE(target != NULL && *target == NULL); count = 0; - for (ce = ISC_LIST_HEAD(caml->elements); - ce != NULL; - ce = ISC_LIST_NEXT(ce, next)) + for (elt = cfg_list_first(caml); + elt != NULL; + elt = cfg_list_next(elt)) count++; result = dns_acl_create(mctx, count, &dacl); @@ -133,59 +158,63 @@ ns_acl_fromconfig(dns_c_ipmatchlist_t *caml, return (result); de = dacl->elements; - for (ce = ISC_LIST_HEAD(caml->elements); - ce != NULL; - ce = ISC_LIST_NEXT(ce, next)) + for (elt = cfg_list_first(caml); + elt != NULL; + elt = cfg_list_next(elt)) { - de->negative = dns_c_ipmatchelement_isneg(ce); - switch (ce->type) { - case dns_c_ipmatch_pattern: + cfg_obj_t *ce = cfg_listelt_value(elt); + if (cfg_obj_istuple(ce)) { + /* This must be a negated element. */ + ce = cfg_tuple_get(ce, "value"); + de->negative = ISC_TRUE; + } else { + de->negative = ISC_FALSE; + } + + if (cfg_obj_isnetprefix(ce)) { + /* Network prefix */ de->type = dns_aclelementtype_ipprefix; - isc_netaddr_fromsockaddr(&de->u.ip_prefix.address, - &ce->u.direct.address); - /* XXX "mask" is a misnomer */ - de->u.ip_prefix.prefixlen = ce->u.direct.mask; - break; - case dns_c_ipmatch_key: + + cfg_obj_asnetprefix(ce, + &de->u.ip_prefix.address, + &de->u.ip_prefix.prefixlen); + } else if (cfg_obj_istype(ce, &cfg_type_keyref)) { + /* Key name */ de->type = dns_aclelementtype_keyname; dns_name_init(&de->u.keyname, NULL); - result = convert_keyname(ce->u.key, mctx, - &de->u.keyname); + result = convert_keyname(ce, mctx, &de->u.keyname); if (result != ISC_R_SUCCESS) goto cleanup; - break; - case dns_c_ipmatch_indirect: + } else if (cfg_obj_islist(ce)) { + /* Nested ACL */ de->type = dns_aclelementtype_nestedacl; - result = ns_acl_fromconfig(ce->u.indirect.list, - cctx, ctx, mctx, - &de->u.nestedacl); - if (result != ISC_R_SUCCESS) - goto cleanup; - break; - case dns_c_ipmatch_localhost: - de->type = dns_aclelementtype_localhost; - break; - - case dns_c_ipmatch_any: - de->type = dns_aclelementtype_any; - break; - - case dns_c_ipmatch_localnets: - de->type = dns_aclelementtype_localnets; - break; - case dns_c_ipmatch_acl: - de->type = dns_aclelementtype_nestedacl; - result = convert_named_acl(ce->u.aclname, - cctx, ctx, mctx, + result = ns_acl_fromconfig(ce, cctx, ctx, mctx, &de->u.nestedacl); if (result != ISC_R_SUCCESS) goto cleanup; - break; - default: - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, - DNS_LOGMODULE_ACL, ISC_LOG_WARNING, - "address match list contains " - "unsupported element type"); + } else if (cfg_obj_isstring(ce)) { + /* ACL name */ + char *name = cfg_obj_asstring(ce); + if (strcasecmp(name, "localhost") == 0) { + de->type = dns_aclelementtype_localhost; + } else if (strcasecmp(name, "localnets") == 0) { + de->type = dns_aclelementtype_localnets; + } else if (strcasecmp(name, "any") == 0) { + de->type = dns_aclelementtype_any; + } else if (strcasecmp(name, "none") == 0) { + de->type = dns_aclelementtype_any; + de->negative = ! de->negative; + } else { + de->type = dns_aclelementtype_nestedacl; + result = convert_named_acl(ce, cctx, ctx, mctx, + &de->u.nestedacl); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + } else { + cfg_obj_log(ce, dns_lctx, ISC_LOG_WARNING, + "address match list contains " + "unsupported element type"); result = ISC_R_FAILURE; goto cleanup; } diff --git a/bin/named/config.c b/bin/named/config.c new file mode 100644 index 0000000000..d1181850a9 --- /dev/null +++ b/bin/named/config.c @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: config.c,v 1.1 2001/03/04 21:21:21 bwelling Exp $ */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +static char defaultconf[] = " +options { +# blackhole {none;}; + coresize default; + datasize default; + deallocate-on-exit true; +# directory + dump-file \"named_dump.db\"; + fake-iquery no; + files default; + has-old-clients false; + heartbeat-interval 3600; + host-statistics no; + interface-interval 3600; + listen-on {any;}; + listen-on-v6 {none;}; + memstatistics-file \"named.memstats\"; + multiple-cnames no; +# named-xfer +# pid-file \"" NS_LOCALSTATEDIR "/named.pid\"; /* or /lwresd.pid */ + port 53; +" +#ifdef PATH_RANDOMDEV +" + random-device \"" PATH_RANDOMDEV "\"; +" +#endif +" + recursive-clients 1000; + rrset-order {order cyclic;}; + serial-queries 20; + stacksize default; + statistics-file \"named.stats\"; + statistics-interval 3600; + tcp-clients 100; +# tkey-dhkey +# tkey-gssapi-credential +# tkey-domain + transfers-per-ns 2; + transfers-in 10; + transfers-out 10; + treat-cr-as-space true; + use-id-pool true; + use-ixfr true; + version \""VERSION"\"; + + /* view */ + allow-notify {none;}; + allow-update-forwarding {none;}; + allow-recursion {any;}; + allow-v6-synthesis {none;}; +# sortlist +# topology + auth-nxdomain false; + recursion true; + provide-ixfr true; + request-ixfr true; + fetch-glue no; + rfc2308-type1 no; + additional-from-auth true; + additional-from-cache true; + query-source address *; + query-source-v6 address *; + notify-source *; + notify-source-v6 *; + cleaning-interval 3600; + min-roots 2; + lame-ttl 600; + max-ncache-ttl 10800; /* 3 hours */ + max-cache-ttl 604800; /* 1 week */ + transfer-format many-answers; + max-cache-size 0; + check-names master ignore; + check-names slave ignore; + check-names response ignore; + + /* zone */ + allow-query {any;}; + allow-transfer {any;}; + notify yes; +# also-notify + dialup no; +# forward +# forwarders + maintain-ixfr-base no; +# max-ixfr-log-size + transfer-source *; + transfer-source-v6 *; + max-transfer-time-in 7200; + max-transfer-time-out 7200; + max-transfer-idle-in 3600; + max-transfer-idle-out 3600; + max-retry-time 1209600; /* 2 weeks */ + min-retry-time 500; + max-refresh-time 2419200; /* 4 weeks */ + min-refresh-time 300; + sig-validity-interval 30; /* days */ + zone-statistics false; +};"; + +isc_result_t +ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) { + isc_buffer_t b; + + isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1); + isc_buffer_add(&b, sizeof(defaultconf) - 1); + return (cfg_parse_buffer(parser, &b, &cfg_type_namedconf, conf)); +} + +isc_result_t +ns_config_get(cfg_obj_t **maps, const char* name, cfg_obj_t **obj) { + int i; + + for (i = 0; ; i++) { + if (maps[i] == NULL) + return (ISC_R_NOTFOUND); + if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) + return (ISC_R_SUCCESS); + } +} + +int +ns_config_listcount(cfg_obj_t *list) { + cfg_listelt_t *e; + int i = 0; + + for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e)) + i++; + + return (i); +} + +isc_result_t +ns_config_getclass(cfg_obj_t *classobj, dns_rdataclass_t *classp) { + char *str; + isc_textregion_t r; + + if (!cfg_obj_isstring(classobj)) { + *classp = dns_rdataclass_in; + return (ISC_R_SUCCESS); + } + str = cfg_obj_asstring(classobj); + r.base = str; + r.length = strlen(str); + return (dns_rdataclass_fromtext(classp, &r)); +} + +isc_result_t +ns_config_getzonetype(cfg_obj_t *zonetypeobj) { + dns_zonetype_t ztype; + char *str; + + str = cfg_obj_asstring(zonetypeobj); + if (strcmp(str, "master") == 0) + ztype = dns_zone_master; + else if (strcmp(str, "slave") == 0) + ztype = dns_zone_slave; + else if (strcmp(str, "stub") == 0) + ztype = dns_zone_stub; + else + INSIST(0); + return (ztype); +} + +isc_result_t +ns_config_getiplist(cfg_obj_t *config, cfg_obj_t *list, + in_port_t defport, isc_mem_t *mctx, + isc_sockaddr_t **addrsp, isc_uint32_t *countp) +{ + int count, i = 0; + cfg_obj_t *addrlist; + cfg_obj_t *portobj; + cfg_listelt_t *element; + isc_sockaddr_t *addrs; + in_port_t port; + isc_result_t result; + + INSIST(addrsp != NULL && *addrsp == NULL); + + addrlist = cfg_tuple_get(list, "addresses"); + count = ns_config_listcount(addrlist); + + portobj = cfg_tuple_get(list, "port"); + if (cfg_obj_isuint32(portobj)) { + isc_uint32_t val = cfg_obj_asuint32(portobj); + if (val > ISC_UINT16_MAX) { + cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, + "port '%u' out of range", val); + return (ISC_R_RANGE); + } + port = (in_port_t) val; + } else if (defport != 0) + port = defport; + else { + result = ns_config_getport(config, &port); + if (result != ISC_R_SUCCESS) + return (result); + } + + addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t)); + if (addrs == NULL) + return (ISC_R_NOMEMORY); + + for (element = cfg_list_first(addrlist); + element != NULL; + element = cfg_list_next(element), i++) + { + INSIST(i < count); + addrs[i] = *cfg_obj_assockaddr(cfg_listelt_value(element)); + if (isc_sockaddr_getport(&addrs[i]) == 0) + isc_sockaddr_setport(&addrs[i], port); + } + INSIST(i == count); + + *addrsp = addrs; + *countp = count; + + return (ISC_R_SUCCESS); +} + +void +ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp, + isc_uint32_t count) +{ + INSIST(addrsp != NULL && *addrsp != NULL); + + isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t)); + *addrsp = NULL; +} + +isc_result_t +ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx, + isc_sockaddr_t **addrsp, dns_name_t ***keysp, + isc_uint32_t *countp) +{ + isc_uint32_t count, i = 0; + isc_result_t result; + cfg_listelt_t *element; + cfg_obj_t *addrlist; + cfg_obj_t *portobj; + in_port_t port; + dns_fixedname_t fname; + isc_sockaddr_t *addrs = NULL; + dns_name_t **keys = NULL; + + INSIST(addrsp != NULL && *addrsp == NULL); + + addrlist = cfg_tuple_get(list, "addresses"); + count = ns_config_listcount(addrlist); + + portobj = cfg_tuple_get(list, "port"); + if (cfg_obj_isuint32(portobj)) { + isc_uint32_t val = cfg_obj_asuint32(portobj); + if (val > ISC_UINT16_MAX) { + cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, + "port '%u' out of range", val); + return (ISC_R_RANGE); + } + port = (in_port_t) val; + } else { + result = ns_config_getport(config, &port); + if (result != ISC_R_SUCCESS) + return (result); + } + + result = ISC_R_NOMEMORY; + + addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t)); + if (addrs == NULL) + goto cleanup; + + keys = isc_mem_get(mctx, count * sizeof(dns_name_t *)); + if (keys == NULL) + goto cleanup; + + for (element = cfg_list_first(addrlist); + element != NULL; + element = cfg_list_next(element), i++) + { + cfg_obj_t *addr; + cfg_obj_t *key; + char *keystr; + isc_buffer_t b; + + INSIST(i < count); + + addr = cfg_tuple_get(cfg_listelt_value(element), "sockaddr"); + key = cfg_tuple_get(cfg_listelt_value(element), "key"); + + addrs[i] = *cfg_obj_assockaddr(addr); + if (isc_sockaddr_getport(&addrs[i]) == 0) + isc_sockaddr_setport(&addrs[i], port); + + keys[i] = NULL; + if (!cfg_obj_isstring(key)) + continue; + keys[i] = isc_mem_get(mctx, sizeof(dns_name_t)); + if (keys[i] == NULL) + goto cleanup; + dns_name_init(keys[i], NULL); + + keystr = cfg_obj_asstring(key); + isc_buffer_init(&b, keystr, strlen(keystr)); + isc_buffer_add(&b, strlen(keystr)); + dns_fixedname_init(&fname); + result = dns_name_fromtext(dns_fixedname_name(&fname), &b, + dns_rootname, ISC_FALSE, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_name_dup(dns_fixedname_name(&fname), mctx, + keys[i]); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + INSIST(i == count); + + *addrsp = addrs; + *keysp = keys; + *countp = count; + + return (ISC_R_SUCCESS); + + cleanup: + if (addrs != NULL) + isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t)); + if (keys != NULL) { + unsigned int j; + for (j = 0 ; j <= i; j++) { + if (keys[j] == NULL) + continue; + if (dns_name_dynamic(keys[j])) + dns_name_free(keys[j], mctx); + isc_mem_put(mctx, keys[j], sizeof(dns_name_t)); + } + isc_mem_put(mctx, keys, count * sizeof(dns_name_t *)); + } + return (result); +} + +void +ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp, + dns_name_t ***keysp, isc_uint32_t count) +{ + unsigned int i; + dns_name_t **keys = *keysp; + + INSIST(addrsp != NULL && *addrsp != NULL); + + isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t)); + for (i = 0; i < count; i++) { + if (keys[i] == NULL) + continue; + if (dns_name_dynamic(keys[i])) + dns_name_free(keys[i], mctx); + isc_mem_put(mctx, keys[i], sizeof(dns_name_t)); + } + isc_mem_put(mctx, *keysp, count * sizeof(dns_name_t *)); + *addrsp = NULL; + *keysp = NULL; +} + +isc_result_t +ns_config_getport(cfg_obj_t *config, in_port_t *portp) { + cfg_obj_t *maps[3]; + cfg_obj_t *options = NULL; + cfg_obj_t *portobj = NULL; + isc_result_t result; + int i; + + if (ns_g_port != 0) { + *portp = ns_g_port; + return (ISC_R_SUCCESS); + } + + cfg_map_get(config, "options", &options); + i = 0; + if (options != NULL) + maps[i++] = options; + maps[i++] = ns_g_defaults; + maps[i] = NULL; + + result = ns_config_get(maps, "port", &portobj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) { + cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, + "port '%u' out of range", + cfg_obj_asuint32(portobj)); + return (ISC_R_RANGE); + } + *portp = (in_port_t)cfg_obj_asuint32(portobj); + return (ISC_R_SUCCESS); +} diff --git a/bin/named/include/named/aclconf.h b/bin/named/include/named/aclconf.h index ccdffb8374..cb2cff3cb3 100644 --- a/bin/named/include/named/aclconf.h +++ b/bin/named/include/named/aclconf.h @@ -15,14 +15,15 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: aclconf.h,v 1.11 2001/01/09 21:40:11 bwelling Exp $ */ +/* $Id: aclconf.h,v 1.12 2001/03/04 21:21:31 bwelling Exp $ */ #ifndef NS_ACLCONF_H #define NS_ACLCONF_H 1 #include -#include +#include + #include typedef struct ns_aclconfctx { @@ -48,8 +49,8 @@ ns_aclconfctx_destroy(ns_aclconfctx_t *ctx); */ isc_result_t -ns_acl_fromconfig(dns_c_ipmatchlist_t *caml, - dns_c_ctx_t *cctx, +ns_acl_fromconfig(cfg_obj_t *caml, + cfg_obj_t *cctx, ns_aclconfctx_t *ctx, isc_mem_t *mctx, dns_acl_t **target); diff --git a/bin/named/include/named/config.h b/bin/named/include/named/config.h new file mode 100644 index 0000000000..78c21084cb --- /dev/null +++ b/bin/named/include/named/config.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: config.h,v 1.1 2001/03/04 21:21:32 bwelling Exp $ */ + +/* $Id: config.h,v 1.1 2001/03/04 21:21:32 bwelling Exp $ */ + +#ifndef NAMED_CONFIG_H +#define NAMED_CONFIG_H 1 + +#include + +#include +#include + +isc_result_t +ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf); + +isc_result_t +ns_config_get(cfg_obj_t **maps, const char* name, cfg_obj_t **obj); + +int +ns_config_listcount(cfg_obj_t *list); + +isc_result_t +ns_config_getclass(cfg_obj_t *classobj, dns_rdataclass_t *classp); + +dns_zonetype_t +ns_config_getzonetype(cfg_obj_t *zonetypeobj); + +isc_result_t +ns_config_getiplist(cfg_obj_t *config, cfg_obj_t *list, + in_port_t defport, isc_mem_t *mctx, + isc_sockaddr_t **addrsp, isc_uint32_t *countp); + +void +ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp, + isc_uint32_t count); + +isc_result_t +ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx, + isc_sockaddr_t **addrsp, dns_name_t ***keys, + isc_uint32_t *countp); + +void +ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp, + dns_name_t ***keys, isc_uint32_t count); + +isc_result_t +ns_config_getport(cfg_obj_t *config, in_port_t *portp); + +#endif /* NAMED_CONFIG_H */ diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index 4e9e477a7a..efc01e29e0 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: globals.h,v 1.52 2001/01/09 21:40:13 bwelling Exp $ */ +/* $Id: globals.h,v 1.53 2001/03/04 21:21:32 bwelling Exp $ */ #ifndef NAMED_GLOBALS_H #define NAMED_GLOBALS_H 1 @@ -24,6 +24,8 @@ #include #include +#include + #include #include @@ -53,6 +55,7 @@ EXTERN isc_entropy_t * ns_g_entropy INIT(NULL); EXTERN isc_timermgr_t * ns_g_timermgr INIT(NULL); EXTERN isc_socketmgr_t * ns_g_socketmgr INIT(NULL); EXTERN omapi_object_t * ns_g_omapimgr INIT(NULL); +EXTERN cfg_parser_t * ns_g_parser INIT(NULL); EXTERN const char * ns_g_version INIT(VERSION); EXTERN in_port_t ns_g_port INIT(0); EXTERN in_port_t lwresd_g_listenport INIT(0); @@ -72,6 +75,8 @@ EXTERN unsigned int ns_g_debuglevel INIT(0); /* * Current configuration information. */ +EXTERN cfg_obj_t * ns_g_config INIT(NULL); +EXTERN cfg_obj_t * ns_g_defaults INIT(NULL); EXTERN const char * ns_g_conffile INIT(NS_SYSCONFDIR "/named.conf"); EXTERN const char * lwresd_g_conffile INIT(NS_SYSCONFDIR diff --git a/bin/named/include/named/logconf.h b/bin/named/include/named/logconf.h index f8ddfa1f77..30dd3b1d47 100644 --- a/bin/named/include/named/logconf.h +++ b/bin/named/include/named/logconf.h @@ -15,20 +15,18 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: logconf.h,v 1.9 2001/01/09 21:40:18 bwelling Exp $ */ +/* $Id: logconf.h,v 1.10 2001/03/04 21:21:33 bwelling Exp $ */ #ifndef NAMED_LOGCONF_H #define NAMED_LOGCONF_H 1 #include -#include - isc_result_t -ns_log_configure(isc_logconfig_t *logconf, dns_c_logginglist_t *clog); +ns_log_configure(isc_logconfig_t *logconf, cfg_obj_t *logstmt); /* * Set up the logging configuration in '*logconf' according to - * the named.conf data in 'clog'. + * the named.conf data in 'logstmt'. */ #endif /* NAMED_LOGCONF_H */ diff --git a/bin/named/include/named/lwresd.h b/bin/named/include/named/lwresd.h index f930cad754..a2a2826211 100644 --- a/bin/named/include/named/lwresd.h +++ b/bin/named/include/named/lwresd.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwresd.h,v 1.10 2001/01/09 21:40:21 bwelling Exp $ */ +/* $Id: lwresd.h,v 1.11 2001/03/04 21:21:34 bwelling Exp $ */ #ifndef NAMED_LWRESD_H #define NAMED_LWRESD_H 1 @@ -23,7 +23,8 @@ #include #include -#include +#include + #include struct ns_lwresd { @@ -55,13 +56,11 @@ struct ns_lwreslistener { * Configure lwresd. */ isc_result_t -ns_lwresd_configure(isc_mem_t *mctx, dns_c_ctx_t *cctx); +ns_lwresd_configure(isc_mem_t *mctx, cfg_obj_t *config); -/* - * Create a configuration context based on resolv.conf and default parameters. - */ isc_result_t -ns_lwresd_parseresolvconf(isc_mem_t *mctx, dns_c_ctx_t **ctxp); +ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx, + cfg_obj_t **configp); /* * Trigger shutdown. @@ -73,8 +72,7 @@ ns_lwresd_shutdown(void); * Manager functions */ isc_result_t -ns_lwdmanager_create(isc_mem_t *mctx, dns_c_lwres_t *lwres, - ns_lwresd_t **lwresdp); +ns_lwdmanager_create(isc_mem_t *mctx, cfg_obj_t *lwres, ns_lwresd_t **lwresdp); void ns_lwdmanager_attach(ns_lwresd_t *source, ns_lwresd_t **targetp); diff --git a/bin/named/include/named/omapi.h b/bin/named/include/named/omapi.h index 196235e3ba..ac6a42bdd8 100644 --- a/bin/named/include/named/omapi.h +++ b/bin/named/include/named/omapi.h @@ -15,13 +15,11 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: omapi.h,v 1.19 2001/02/06 23:57:15 bwelling Exp $ */ +/* $Id: omapi.h,v 1.20 2001/03/04 21:21:35 bwelling Exp $ */ #ifndef NAMED_OMAPI_H #define NAMED_OMAPI_H 1 -#include - #include #include @@ -50,7 +48,7 @@ isc_result_t ns_omapi_init(void); isc_result_t -ns_omapi_configure(isc_mem_t *mctx, dns_c_ctx_t *cctx, +ns_omapi_configure(isc_mem_t *mctx, cfg_obj_t *config, ns_aclconfctx_t *aclconfctx); void diff --git a/bin/named/include/named/tkeyconf.h b/bin/named/include/named/tkeyconf.h index 07a5b45b62..28516f975b 100644 --- a/bin/named/include/named/tkeyconf.h +++ b/bin/named/include/named/tkeyconf.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tkeyconf.h,v 1.8 2001/01/09 21:40:30 bwelling Exp $ */ +/* $Id: tkeyconf.h,v 1.9 2001/03/04 21:21:36 bwelling Exp $ */ #ifndef NS_TKEYCONF_H #define NS_TKEYCONF_H 1 @@ -23,19 +23,19 @@ #include #include -#include +#include ISC_LANG_BEGINDECLS isc_result_t -ns_tkeyctx_fromconfig(dns_c_ctx_t *cfg, isc_mem_t *mctx, isc_entropy_t *ectx, - dns_tkeyctx_t **tctxp); +ns_tkeyctx_fromconfig(cfg_obj_t *options, isc_mem_t *mctx, isc_entropy_t *ectx, + dns_tkeyctx_t **tctxp); /* * Create a TKEY context and configure it, including the default DH key - * and default domain, according to 'cfg'. + * and default domain, according to 'options'. * * Requires: - * 'cfg' is a valid configuration context. + * 'cfg' is a valid configuration options object. * 'mctx' is not NULL * 'ectx' is not NULL * 'tctx' is not NULL diff --git a/bin/named/include/named/tsigconf.h b/bin/named/include/named/tsigconf.h index e4cea63fef..5a2300de42 100644 --- a/bin/named/include/named/tsigconf.h +++ b/bin/named/include/named/tsigconf.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tsigconf.h,v 1.8 2001/01/09 21:40:31 bwelling Exp $ */ +/* $Id: tsigconf.h,v 1.9 2001/03/04 21:21:37 bwelling Exp $ */ #ifndef NS_TSIGCONF_H #define NS_TSIGCONF_H 1 @@ -23,19 +23,17 @@ #include #include -#include - ISC_LANG_BEGINDECLS isc_result_t -ns_tsigkeyring_fromconfig(dns_c_view_t *confview, dns_c_ctx_t *confctx, - isc_mem_t *mctx, dns_tsig_keyring_t **ringp); +ns_tsigkeyring_fromconfig(cfg_obj_t *config, cfg_obj_t *vconfig, + isc_mem_t *mctx, dns_tsig_keyring_t **ringp); /* * Create a TSIG key ring and configure it according to the 'key' - * statements in 'confview' and 'confctx'. + * statements in the global and view configuration objects. * * Requires: - * 'confctx' is a valid configuration context. + * 'config' is not NULL. * 'mctx' is not NULL * 'ring' is not NULL, and '*ring' is NULL * diff --git a/bin/named/include/named/zoneconf.h b/bin/named/include/named/zoneconf.h index 4cbf3e1cb0..83ca9f24d5 100644 --- a/bin/named/include/named/zoneconf.h +++ b/bin/named/include/named/zoneconf.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.h,v 1.15 2001/01/09 21:40:36 bwelling Exp $ */ +/* $Id: zoneconf.h,v 1.16 2001/03/04 21:21:39 bwelling Exp $ */ #ifndef NS_ZONECONF_H #define NS_ZONECONF_H 1 @@ -23,13 +23,15 @@ #include #include +#include + #include ISC_LANG_BEGINDECLS isc_result_t -ns_zone_configure(dns_c_ctx_t *cctx, dns_c_view_t *cview, dns_c_zone_t *czone, - ns_aclconfctx_t *ac, dns_zone_t *zone); +ns_zone_configure(cfg_obj_t *config, cfg_obj_t *vconfig, cfg_obj_t *zconfig, + ns_aclconfctx_t *ac, dns_zone_t *zone); /* * Configure or reconfigure a zone according to the named.conf * data in 'cctx' and 'czone'. @@ -46,20 +48,14 @@ ns_zone_configure(dns_c_ctx_t *cctx, dns_c_view_t *cview, dns_c_zone_t *czone, */ isc_boolean_t -ns_zone_reusable(dns_zone_t *zone, dns_c_zone_t *czone); +ns_zone_reusable(dns_zone_t *zone, cfg_obj_t *zconfig); /* * If 'zone' can be safely reconfigured according to the configuration - * data in 'czone', return ISC_TRUE. If the configuration data is so + * data in 'zconfig', return ISC_TRUE. If the configuration data is so * different from the current zone state that the zone needs to be destroyed * and recreated, return ISC_FALSE. */ -isc_result_t -ns_zonemgr_configure(dns_c_ctx_t *cctx, dns_zonemgr_t *zonemgr); -/* - * Configure the zone manager according to the named.conf data - * in 'cctx'. - */ ISC_LANG_ENDDECLS #endif /* NS_ZONECONF_H */ diff --git a/bin/named/log.c b/bin/named/log.c index 9192650535..0332b6e224 100644 --- a/bin/named/log.c +++ b/bin/named/log.c @@ -15,12 +15,14 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.c,v 1.28 2001/01/09 21:39:44 bwelling Exp $ */ +/* $Id: log.c,v 1.29 2001/03/04 21:21:21 bwelling Exp $ */ #include #include +#include + #include /* @@ -75,6 +77,7 @@ ns_log_init(isc_boolean_t safe) { isc_log_setcontext(ns_g_lctx); dns_log_init(ns_g_lctx); dns_log_setcontext(ns_g_lctx); + isccfg_log_init(ns_g_lctx); if (safe) result = ns_log_setsafechannels(lcfg); diff --git a/bin/named/logconf.c b/bin/named/logconf.c index 57a075f261..1c789594cc 100644 --- a/bin/named/logconf.c +++ b/bin/named/logconf.c @@ -15,12 +15,17 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: logconf.c,v 1.27 2001/01/09 21:39:45 bwelling Exp $ */ +/* $Id: logconf.c,v 1.28 2001/03/04 21:21:22 bwelling Exp $ */ #include +#include #include #include +#include + +#include +#include #include #include @@ -35,42 +40,35 @@ * in 'ccat' and add it to 'lctx'. */ static isc_result_t -category_fromconf(dns_c_logcat_t *ccat, isc_logconfig_t *lctx) { +category_fromconf(cfg_obj_t *ccat, isc_logconfig_t *lctx) { isc_result_t result; - unsigned int i; + const char *catname; isc_logcategory_t *category; isc_logmodule_t *module; + cfg_obj_t *destinations = NULL; + cfg_listelt_t *element = NULL; - category = isc_log_categorybyname(ns_g_lctx, ccat->catname); + catname = cfg_obj_asstring(cfg_tuple_get(ccat, "name")); + category = isc_log_categorybyname(ns_g_lctx, catname); if (category == NULL) { - isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_CONFIG, - NS_LOGMODULE_SERVER, ISC_LOG_ERROR, - "unknown logging category '%s' ignored", - ccat->catname); + cfg_obj_log(ccat, ns_g_lctx, ISC_LOG_ERROR, + "unknown logging category '%s' ignored", + catname); /* * Allow further processing by returning success. */ return (ISC_R_SUCCESS); } -#ifdef notyet - module = isc_log_modulebyname(ns_g_lctx, ccat->modname); - if (module == NULL) { - isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_CONFIG, - NS_LOGMODULE_SERVER, ISC_LOG_ERROR, - "unknown logging module '%s' ignored", - ccat->modname); - /* - * Allow further processing by returning success. - */ - return (ISC_R_SUCCESS); - } -#else module = NULL; -#endif - for (i = 0; i < ccat->nextcname; i++) { - char *channelname = ccat->channel_names[i]; + destinations = cfg_tuple_get(ccat, "destinations"); + for (element = cfg_list_first(destinations); + element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *channel = cfg_listelt_value(element); + char *channelname = cfg_obj_asstring(channel); result = isc_log_usechannel(lctx, channelname, category, module); @@ -90,156 +88,170 @@ category_fromconf(dns_c_logcat_t *ccat, isc_logconfig_t *lctx) { * in 'cchan' and add it to 'lctx'. */ static isc_result_t -channel_fromconf(dns_c_logchan_t *cchan, isc_logconfig_t *lctx) { +channel_fromconf(cfg_obj_t *channel, isc_logconfig_t *lctx) { isc_result_t result; isc_logdestination_t dest; unsigned int type; unsigned int flags = 0; int level; - dns_c_logseverity_t severity; + const char *channelname; + cfg_obj_t *fileobj = NULL; + cfg_obj_t *syslogobj = NULL; + cfg_obj_t *nullobj = NULL; + cfg_obj_t *stderrobj = NULL; + cfg_obj_t *severity = NULL; + int i; + + channelname = cfg_obj_asstring(cfg_map_getname(channel)); + + (void)cfg_map_get(channel, "file", &fileobj); + (void)cfg_map_get(channel, "syslog", &syslogobj); + (void)cfg_map_get(channel, "null", &nullobj); + (void)cfg_map_get(channel, "stderr", &stderrobj); + + i = 0; + if (fileobj != NULL) + i++; + if (syslogobj != NULL) + i++; + if (nullobj != NULL) + i++; + if (stderrobj != NULL) + i++; + + if (i != 1) { + cfg_obj_log(channel, ns_g_lctx, ISC_LOG_ERROR, + "channel '%s': exactly one of file, syslog, " + "null, and stderr must be present", channelname); + return (ISC_R_FAILURE); + } type = ISC_LOG_TONULL; - switch (cchan->ctype) { - case dns_c_logchan_file: + + if (fileobj != NULL) { + cfg_obj_t *pathobj = cfg_tuple_get(fileobj, "file"); + cfg_obj_t *sizeobj = cfg_tuple_get(fileobj, "size"); + cfg_obj_t *versionsobj = cfg_tuple_get(fileobj, "versions"); + isc_int32_t versions = ISC_LOG_ROLLNEVER; + isc_offset_t size = ISC_OFFSET_MAXIMUM; + type = ISC_LOG_TOFILE; - { - const char *path = NULL; - isc_int32_t versions = ISC_LOG_ROLLNEVER; - /* - * XXXDCL should be isc_offset_t, but that - * is incompatible with dns_c_logchan_getsize. - */ - isc_uint32_t size = 0; - (void)dns_c_logchan_getpath(cchan, &path); - if (path == NULL) { - isc_log_write(ns_g_lctx, - DNS_LOGCATEGORY_CONFIG, - NS_LOGMODULE_SERVER, - ISC_LOG_ERROR, - "file log channel has " - "no file name"); - return (ISC_R_UNEXPECTED); - } - (void)dns_c_logchan_getversions(cchan, - (isc_uint32_t *) - &versions); - (void)dns_c_logchan_getsize(cchan, &size); - dest.file.stream = NULL; - dest.file.name = cchan->u.filec.path; - dest.file.versions = versions; - dest.file.maximum_size = size; - } - break; + + if (versionsobj != NULL && cfg_obj_isuint32(versionsobj)) + versions = cfg_obj_asuint32(versionsobj); + if (sizeobj != NULL && + cfg_obj_isuint64(sizeobj) && + cfg_obj_asuint64(sizeobj) < ISC_OFFSET_MAXIMUM) + size = (isc_offset_t)cfg_obj_asuint64(sizeobj); + dest.file.stream = NULL; + dest.file.name = cfg_obj_asstring(pathobj); + dest.file.versions = versions; + dest.file.maximum_size = size; + } else if (syslogobj != NULL) { + int facility = LOG_DAEMON; - case dns_c_logchan_syslog: type = ISC_LOG_TOSYSLOG; - { - int facility = LOG_DAEMON; - (void)dns_c_logchan_getfacility(cchan, &facility); - dest.facility = facility; - } - break; - case dns_c_logchan_stderr: + if (cfg_obj_isstring(syslogobj)) { + char *facilitystr = cfg_obj_asstring(syslogobj); + (void)isc_syslog_facilityfromstring(facilitystr, + &facility); + } + dest.facility = facility; + } else if (stderrobj != NULL) { type = ISC_LOG_TOFILEDESC; - { - dest.file.stream = stderr; - dest.file.name = NULL; - dest.file.versions = ISC_LOG_ROLLNEVER; - dest.file.maximum_size = 0; - } - - case dns_c_logchan_null: - break; + dest.file.stream = stderr; + dest.file.name = NULL; + dest.file.versions = ISC_LOG_ROLLNEVER; + dest.file.maximum_size = 0; } /* * Munge flags. */ { - isc_boolean_t printcat = ISC_FALSE; - isc_boolean_t printsev = ISC_FALSE; - isc_boolean_t printtime = ISC_FALSE; + cfg_obj_t *printcat = NULL; + cfg_obj_t *printsev = NULL; + cfg_obj_t *printtime = NULL; - (void)dns_c_logchan_getprintcat(cchan, &printcat); - (void)dns_c_logchan_getprintsev(cchan, &printsev); - (void)dns_c_logchan_getprinttime(cchan, &printtime); + (void)cfg_map_get(channel, "print-category", &printcat); + (void)cfg_map_get(channel, "print-severity", &printsev); + (void)cfg_map_get(channel, "print-time", &printtime); - if (printcat) + if (printcat != NULL && cfg_obj_asboolean(printcat)) flags |= ISC_LOG_PRINTCATEGORY; - if (printtime) + if (printtime != NULL && cfg_obj_asboolean(printtime)) flags |= ISC_LOG_PRINTTIME; - if (printsev) + if (printsev != NULL && cfg_obj_asboolean(printsev)) flags |= ISC_LOG_PRINTLEVEL; - /* XXX ISC_LOG_PRINTMODULE */ } level = ISC_LOG_INFO; - if (dns_c_logchan_getseverity(cchan, &severity) == ISC_R_SUCCESS) { - switch (severity) { - case dns_c_log_critical: - level = ISC_LOG_CRITICAL; - break; - case dns_c_log_error: - level = ISC_LOG_ERROR; - break; - case dns_c_log_warn: - level = ISC_LOG_WARNING; - break; - case dns_c_log_notice: - level = ISC_LOG_NOTICE; - break; - case dns_c_log_info: - level = ISC_LOG_INFO; - break; - case dns_c_log_debug: - (void)dns_c_logchan_getdebuglevel(cchan, &level); - break; - case dns_c_log_dynamic: - level = ISC_LOG_DYNAMIC; - break; - default: - level = ISC_LOG_INFO; - break; - } + if (cfg_map_get(channel, "severity", &severity) == ISC_R_SUCCESS) { + if (cfg_obj_isstring(severity)) { + char *str = cfg_obj_asstring(severity); + if (strcasecmp(str, "critical") == 0) + level = ISC_LOG_CRITICAL; + else if (strcasecmp(str, "error") == 0) + level = ISC_LOG_ERROR; + else if (strcasecmp(str, "warning") == 0) + level = ISC_LOG_WARNING; + else if (strcasecmp(str, "notice") == 0) + level = ISC_LOG_NOTICE; + else if (strcasecmp(str, "info") == 0) + level = ISC_LOG_INFO; + else if (strcasecmp(str, "dynamic") == 0) + level = ISC_LOG_DYNAMIC; + } else + /* debug */ + level = cfg_obj_asuint32(severity); } - result = isc_log_createchannel(lctx, cchan->name, + result = isc_log_createchannel(lctx, channelname, type, level, &dest, flags); return (result); } isc_result_t -ns_log_configure(isc_logconfig_t *lcctx, dns_c_logginglist_t *clog) { +ns_log_configure(isc_logconfig_t *logconf, cfg_obj_t *logstmt) { isc_result_t result; - dns_c_logchan_t *cchan; - dns_c_logcat_t *ccat; + cfg_obj_t *channels = NULL; + cfg_obj_t *categories = NULL; + cfg_listelt_t *element; isc_boolean_t default_set = ISC_FALSE; - CHECK(ns_log_setdefaultchannels(lcctx)); + CHECK(ns_log_setdefaultchannels(logconf)); - for (cchan = ISC_LIST_HEAD(clog->channels); - cchan != NULL; - cchan = ISC_LIST_NEXT(cchan, next)) { - CHECK(channel_fromconf(cchan, lcctx)); + (void)cfg_map_get(logstmt, "channel", &channels); + for (element = cfg_list_first(channels); + element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *channel = cfg_listelt_value(element); + CHECK(channel_fromconf(channel, logconf)); } - for (ccat = ISC_LIST_HEAD(clog->categories); - ccat != NULL; - ccat = ISC_LIST_NEXT(ccat, next)) { - CHECK(category_fromconf(ccat, lcctx)); - if (! default_set) - default_set = - ISC_TF(strcmp(ccat->catname, "default") == 0); + (void)cfg_map_get(logstmt, "category", &categories); + for (element = cfg_list_first(categories); + element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *category = cfg_listelt_value(element); + CHECK(category_fromconf(category, logconf)); + if (!default_set) { + cfg_obj_t *catname = cfg_tuple_get(category, "name"); + if (strcmp(cfg_obj_asstring(catname), "default")) + default_set = ISC_TRUE; + } } - if (! default_set) - CHECK(ns_log_setdefaultcategory(lcctx)); + if (!default_set) + CHECK(ns_log_setdefaultcategory(logconf)); return (ISC_R_SUCCESS); cleanup: - if (lcctx != NULL) - isc_logconfig_destroy(&lcctx); + if (logconf != NULL) + isc_logconfig_destroy(&logconf); return (result); } diff --git a/bin/named/lwresd.c b/bin/named/lwresd.c index a912e05c5e..6e0f2e995d 100644 --- a/bin/named/lwresd.c +++ b/bin/named/lwresd.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwresd.c,v 1.30 2001/01/25 02:33:39 bwelling Exp $ */ +/* $Id: lwresd.c,v 1.31 2001/03/04 21:21:23 bwelling Exp $ */ /* * Main program for the Lightweight Resolver Daemon. @@ -37,12 +37,15 @@ #include #include +#include + #include #include #include #include #include +#include #include #include #include @@ -96,88 +99,32 @@ ns__lwresd_memfree(void *arg, void *mem, size_t size) { } while (0) static isc_result_t -parse_sortlist(lwres_conf_t *lwc, isc_mem_t *mctx, - dns_c_ipmatchlist_t **sortlist) -{ - dns_c_ipmatchlist_t *inner = NULL, *middle = NULL, *outer = NULL; - dns_c_ipmatchelement_t *element = NULL; - int i; - isc_result_t result; - - REQUIRE(sortlist != NULL && *sortlist == NULL); - - REQUIRE (lwc->sortlistnxt > 0); - - CHECK(dns_c_ipmatchlist_new(mctx, &middle)); - - CHECK(dns_c_ipmatchany_new(mctx, &element)); - ISC_LIST_APPEND(middle->elements, element, next); - element = NULL; - - CHECK(dns_c_ipmatchlist_new(mctx, &inner)); - for (i = 0; i < lwc->sortlistnxt; i++) { - isc_sockaddr_t sa; - isc_netaddr_t ma; - unsigned int mask; - - CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, - &lwc->sortlist[i].addr, - 0)); - CHECK(lwaddr_netaddr_fromlwresaddr(&ma, - &lwc->sortlist[i].mask)); - CHECK(isc_netaddr_masktoprefixlen(&ma, &mask)); - CHECK(dns_c_ipmatchpattern_new(mctx, &element, sa, mask)); - ISC_LIST_APPEND(inner->elements, element, next); - element = NULL; - } - - CHECK(dns_c_ipmatchindirect_new(mctx, &element, inner, NULL)); - dns_c_ipmatchlist_detach(&inner); - ISC_LIST_APPEND(middle->elements, element, next); - element = NULL; - - CHECK(dns_c_ipmatchlist_new(mctx, &outer)); - CHECK(dns_c_ipmatchindirect_new(mctx, &element, middle, NULL)); - dns_c_ipmatchlist_detach(&middle); - ISC_LIST_APPEND(outer->elements, element, next); - - *sortlist = outer; - +buffer_putstr(isc_buffer_t *b, const char *s) { + unsigned int len = strlen(s); + if (isc_buffer_availablelength(b) <= len) + return (ISC_R_NOSPACE); + isc_buffer_putmem(b, s, len); return (ISC_R_SUCCESS); - cleanup: - if (inner != NULL) - dns_c_ipmatchlist_detach(&inner); - if (outer != NULL) - dns_c_ipmatchlist_detach(&outer); - if (element != NULL) - dns_c_ipmatchelement_delete(mctx, &element); - return (result); } /* * Convert a resolv.conf file into a config structure. */ isc_result_t -ns_lwresd_parseresolvconf(isc_mem_t *mctx, dns_c_ctx_t **ctxp) { - dns_c_ctx_t *ctx = NULL; +ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx, + cfg_obj_t **configp) +{ + char text[4096]; + char str[16]; + isc_buffer_t b; lwres_context_t *lwctx = NULL; lwres_conf_t *lwc = NULL; isc_sockaddr_t sa; + isc_netaddr_t na; int i; - in_port_t port; - dns_c_iplist_t *forwarders = NULL; - dns_c_iplist_t *locallist = NULL; - dns_c_lwreslist_t *lwreslist = NULL; - dns_c_lwres_t *lwres = NULL; - dns_c_search_t *search = NULL; - dns_c_searchlist_t *searchlist = NULL; - dns_c_ipmatchlist_t *sortlist = NULL; isc_result_t result; lwres_result_t lwresult; - struct in_addr localhost; - CHECK(dns_c_ctx_new(mctx, &ctx)); - lwctx = NULL; lwresult = lwres_context_create(&lwctx, mctx, ns__lwresd_memalloc, ns__lwresd_memfree, @@ -196,107 +143,133 @@ ns_lwresd_parseresolvconf(isc_mem_t *mctx, dns_c_ctx_t **ctxp) { lwc = lwres_conf_get(lwctx); INSIST(lwc != NULL); + isc_buffer_init(&b, text, sizeof(text)); + /* * Build the list of forwarders. */ if (lwc->nsnext > 0) { - CHECK(dns_c_iplist_new(mctx, lwc->nsnext, &forwarders)); - - if (ns_g_port != 0) - port = ns_g_port; - else - port = 53; + CHECK(buffer_putstr(&b, "options {\n")); + CHECK(buffer_putstr(&b, "\tforwarders {\n")); for (i = 0 ; i < lwc->nsnext ; i++) { CHECK(lwaddr_sockaddr_fromlwresaddr( &sa, &lwc->nameservers[i], - port)); - if (result != ISC_R_SUCCESS) - continue; - CHECK(dns_c_iplist_append(forwarders, sa, NULL)); - } - - if (forwarders->nextidx != 0) { - CHECK(dns_c_ctx_setforwarders(ctx, forwarders)); - dns_c_iplist_detach(&forwarders); - CHECK(dns_c_ctx_setforward(ctx, dns_c_forw_first)); + ns_g_port)); + isc_netaddr_fromsockaddr(&na, &sa); + CHECK(buffer_putstr(&b, "\t\t")); + CHECK(isc_netaddr_totext(&na, &b)); + CHECK(buffer_putstr(&b, ";\n")); } + CHECK(buffer_putstr(&b, "\t};\n")); + CHECK(buffer_putstr(&b, "};\n\n")); } + CHECK(buffer_putstr(&b, "lwres {\n")); + /* * Build the search path */ if (lwc->searchnxt > 0) { - CHECK(dns_c_searchlist_new(mctx, &searchlist)); - for (i = 0; i < lwc->searchnxt; i++) { - search = NULL; - CHECK(dns_c_search_new(mctx, lwc->search[i], &search)); - dns_c_searchlist_append(searchlist, search); + if (lwc->searchnxt > 0) { + CHECK(buffer_putstr(&b, "\tsearch {\n")); + for (i = 0; i < lwc->searchnxt; i++) { + CHECK(buffer_putstr(&b, "\t\t")); + CHECK(buffer_putstr(&b, lwc->search[i])); + CHECK(buffer_putstr(&b, ";\n")); + } + CHECK(buffer_putstr(&b, "\t};\n")); } } + /* + * Build the ndots line + */ + if (lwc->ndots != 1) { + CHECK(buffer_putstr(&b, "\tndots ")); + snprintf(str, sizeof(str), "%u", lwc->ndots); + CHECK(buffer_putstr(&b, str)); + CHECK(buffer_putstr(&b, ";\n")); + } + + /* + * Build the listen-on line + */ + if (lwc->lwnext > 0) { + CHECK(buffer_putstr(&b, "\tlisten-on {\n")); + + for (i = 0 ; i < lwc->lwnext ; i++) { + CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, + &lwc->lwservers[i], + 0)); + isc_netaddr_fromsockaddr(&na, &sa); + CHECK(buffer_putstr(&b, "\t\t")); + CHECK(isc_netaddr_totext(&na, &b)); + CHECK(buffer_putstr(&b, ";\n")); + } + CHECK(buffer_putstr(&b, "\t};\n")); + } + /* * Build the sortlist */ if (lwc->sortlistnxt > 0) { - CHECK(parse_sortlist(lwc, mctx, &sortlist)); - CHECK(dns_c_ctx_setsortlist(ctx, sortlist)); - dns_c_ipmatchlist_detach(&sortlist); + CHECK(buffer_putstr(&b, "\tsortlist {\n")); + CHECK(buffer_putstr(&b, "\t{\n")); + CHECK(buffer_putstr(&b, "\t\tany;\n")); + CHECK(buffer_putstr(&b, "\t\t{;\n")); + for (i = 0 ; i < lwc->sortlistnxt; i++) { + lwres_addr_t *lwaddr = &lwc->sortlist[i].addr; + lwres_addr_t *lwmask = &lwc->sortlist[i].mask; + unsigned int mask; + + CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwmask, 0)); + isc_netaddr_fromsockaddr(&na, &sa); + result = isc_netaddr_masktoprefixlen(&na, &mask); + if (result != ISC_R_SUCCESS) { + char addrtext[ISC_NETADDR_FORMATSIZE]; + isc_netaddr_format(&na, addrtext, + sizeof(addrtext)); + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_LWRESD, + ISC_LOG_ERROR, + "processing sortlist: '%s' is " + "not a valid netmask", + addrtext); + goto cleanup; + } + + CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwaddr, 0)); + isc_netaddr_fromsockaddr(&na, &sa); + + CHECK(buffer_putstr(&b, "\t\t\t")); + CHECK(isc_netaddr_totext(&na, &b)); + snprintf(str, sizeof(str), "%u", mask); + CHECK(buffer_putstr(&b, "/")); + CHECK(buffer_putstr(&b, str)); + CHECK(buffer_putstr(&b, ";\n")); + } + CHECK(buffer_putstr(&b, "\t\t}\n")); + CHECK(buffer_putstr(&b, "\t}\n")); + CHECK(buffer_putstr(&b, "};\n")); } - CHECK(dns_c_lwreslist_new(mctx, &lwreslist)); - CHECK(dns_c_lwres_new(mctx, &lwres)); + CHECK(buffer_putstr(&b, "};\n")); - port = lwresd_g_listenport; - if (port == 0) - port = LWRES_UDP_PORT; +#if 0 + printf("%.*s\n", + (int)isc_buffer_usedlength(&b), + (char *)isc_buffer_base(&b)); +#endif - if (lwc->lwnext == 0) { - localhost.s_addr = htonl(INADDR_LOOPBACK); - isc_sockaddr_fromin(&sa, &localhost, port); - } else { - CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, &lwc->lwservers[0], - port)); - } + lwres_conf_clear(lwctx); + lwres_context_destroy(&lwctx); - CHECK(dns_c_iplist_new(mctx, 1, &locallist)); - CHECK(dns_c_iplist_append(locallist, sa, NULL)); - - CHECK(dns_c_lwres_setlistenon(lwres, locallist)); - dns_c_iplist_detach(&locallist); - - CHECK(dns_c_lwres_setsearchlist(lwres, searchlist)); - searchlist = NULL; - - CHECK(dns_c_lwres_setndots(lwres, lwc->ndots)); - - CHECK(dns_c_lwreslist_append(lwreslist, lwres)); - lwres = NULL; - - CHECK(dns_c_ctx_setlwres(ctx, lwreslist)); - lwreslist = NULL; - - *ctxp = ctx; - - result = ISC_R_SUCCESS; + return (cfg_parse_buffer(pctx, &b, &cfg_type_namedconf, configp)); cleanup: - if (result != ISC_R_SUCCESS) { - if (forwarders != NULL) - dns_c_iplist_detach(&forwarders); - if (locallist != NULL) - dns_c_iplist_detach(&locallist); - if (searchlist != NULL) - dns_c_searchlist_delete(&searchlist); - if (sortlist != NULL) - dns_c_ipmatchlist_detach(&sortlist); - if (lwres != NULL) - dns_c_lwres_delete(&lwres); - if (lwreslist != NULL) - dns_c_lwreslist_delete(&lwreslist); - dns_c_ctx_delete(&ctx); - } if (lwctx != NULL) { lwres_conf_clear(lwctx); @@ -311,12 +284,14 @@ ns_lwresd_parseresolvconf(isc_mem_t *mctx, dns_c_ctx_t **ctxp) { * Handle lwresd manager objects */ isc_result_t -ns_lwdmanager_create(isc_mem_t *mctx, dns_c_lwres_t *lwres, +ns_lwdmanager_create(isc_mem_t *mctx, cfg_obj_t *lwres, ns_lwresd_t **lwresdp) { ns_lwresd_t *lwresd; const char *vname; - dns_c_search_t *search; + dns_rdataclass_t vclass; + cfg_obj_t *obj, *viewobj, *searchobj; + cfg_listelt_t *element; isc_result_t result; INSIST(lwresdp != NULL && *lwresdp == NULL); @@ -328,29 +303,45 @@ ns_lwdmanager_create(isc_mem_t *mctx, dns_c_lwres_t *lwres, lwresd->mctx = NULL; isc_mem_attach(mctx, &lwresd->mctx); lwresd->view = NULL; - lwresd->ndots = lwres->ndots; lwresd->search = NULL; lwresd->refs = 1; + obj = NULL; + (void)cfg_map_get(lwres, "ndots", &obj); + if (obj != NULL) + lwresd->ndots = cfg_obj_asuint32(obj); + else + lwresd->ndots = 1; + RUNTIME_CHECK(isc_mutex_init(&lwresd->lock) == ISC_R_SUCCESS); lwresd->shutting_down = ISC_FALSE; - if (lwres->view == NULL) + viewobj = NULL; + (void)cfg_map_get(lwres, "view", &viewobj); + if (viewobj != NULL) { + vname = cfg_obj_asstring(cfg_tuple_get(viewobj, "name")); + obj = cfg_tuple_get(viewobj, "class"); + result = ns_config_getclass(obj, &vclass); + if (result != ISC_R_SUCCESS) + goto fail; + } else { vname = "_default"; - else - vname = lwres->view; + vclass = dns_rdataclass_in; + } - result = dns_viewlist_find(&ns_g_server->viewlist, vname, - lwres->viewclass, &lwresd->view); + result = dns_viewlist_find(&ns_g_server->viewlist, vname, vclass, + &lwresd->view); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, - "couldn't find view %s", lwres->view); + "couldn't find view %s", vname); goto fail; } - if (lwres->searchlist != NULL) { + searchobj = NULL; + cfg_map_get(lwres, "search", &searchobj); + if (searchobj != NULL) { lwresd->search = NULL; result = ns_lwsearchlist_create(lwresd->mctx, &lwresd->search); @@ -360,19 +351,24 @@ ns_lwdmanager_create(isc_mem_t *mctx, dns_c_lwres_t *lwres, "couldn't create searchlist"); goto fail; } - for (search = ISC_LIST_HEAD(lwres->searchlist->searches); - search != NULL; - search = ISC_LIST_NEXT(search, next)) + for (element = cfg_list_first(searchobj); + element != NULL; + element = cfg_list_next(element)) { + cfg_obj_t *search; + char *searchstr; isc_buffer_t namebuf; dns_fixedname_t fname; dns_name_t *name; + search = cfg_listelt_value(element); + searchstr = cfg_obj_asstring(search); + dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - isc_buffer_init(&namebuf, search->search, - strlen(search->search)); - isc_buffer_add(&namebuf, strlen(search->search)); + isc_buffer_init(&namebuf, searchstr, + strlen(searchstr)); + isc_buffer_add(&namebuf, strlen(searchstr)); result = dns_name_fromtext(name, &namebuf, dns_rootname, ISC_FALSE, NULL); @@ -382,7 +378,7 @@ ns_lwdmanager_create(isc_mem_t *mctx, dns_c_lwres_t *lwres, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "invalid name %s in searchlist", - search->search); + searchstr); continue; } @@ -731,22 +727,24 @@ configure_listener(isc_sockaddr_t *address, ns_lwresd_t *lwresd, } isc_result_t -ns_lwresd_configure(isc_mem_t *mctx, dns_c_ctx_t *cctx) { - dns_c_lwres_t *lwres = NULL; - dns_c_lwreslist_t *list = NULL; +ns_lwresd_configure(isc_mem_t *mctx, cfg_obj_t *config) { + cfg_obj_t *lwreslist = NULL; + cfg_obj_t *lwres = NULL; + cfg_obj_t *listenerslist = NULL; + cfg_listelt_t *element = NULL; ns_lwreslistener_t *listener; ns_lwreslistenerlist_t newlisteners; isc_result_t result; char socktext[ISC_SOCKADDR_FORMATSIZE]; REQUIRE(mctx != NULL); - REQUIRE(cctx != NULL); + REQUIRE(config != NULL); RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS); ISC_LIST_INIT(newlisteners); - result = dns_c_ctx_getlwres(cctx, &list); + result = cfg_map_get(config, "lwres", &lwreslist); if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); @@ -759,42 +757,57 @@ ns_lwresd_configure(isc_mem_t *mctx, dns_c_ctx_t *cctx) { * the underlying config code, or to the bind attempt getting an * address-in-use error. */ - for (lwres = dns_c_lwreslist_head(list); - lwres != NULL; - lwres = dns_c_lwreslist_next(lwres)) + for (element = cfg_list_first(lwreslist); + element != NULL; + element = cfg_list_next(element)) { - unsigned int i; ns_lwresd_t *lwresd; + in_port_t port; + isc_sockaddr_t *addrs = NULL; + isc_uint32_t count; + lwres = cfg_listelt_value(element); lwresd = NULL; result = ns_lwdmanager_create(mctx, lwres, &lwresd); if (result != ISC_R_SUCCESS) return (result); - if (lwres->listeners == NULL) { + port = lwresd_g_listenport; + if (port == 0) + port = LWRES_UDP_PORT; + + listenerslist = NULL; + cfg_map_get(lwres, "listen-on", &listenerslist); + if (listenerslist == NULL) { struct in_addr localhost; - in_port_t port; isc_sockaddr_t address; - port = lwresd_g_listenport; - if (port == 0) - port = LWRES_UDP_PORT; localhost.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&address, &localhost, port); result = configure_listener(&address, lwresd, mctx, &newlisteners); } else { - isc_sockaddr_t *address; - for (i = 0; i < lwres->listeners->nextidx; i++) { - address = &lwres->listeners->ips[i]; - result = configure_listener(address, lwresd, + isc_uint32_t i; + + result = ns_config_getiplist(config, listenerslist, + port, mctx, + &addrs, &count); + if (result != ISC_R_SUCCESS) + goto failure; + + for (i = 0; i < count; i++) { + result = configure_listener(&addrs[i], lwresd, mctx, &newlisteners); if (result != ISC_R_SUCCESS) - break; + goto failure; } } + failure: + if (addrs != NULL) + ns_config_putiplist(mctx, &addrs, count); + ns_lwdmanager_detach(&lwresd); if (result != ISC_R_SUCCESS) return (result); diff --git a/bin/named/omapiconf.c b/bin/named/omapiconf.c index e8eb1487b3..bb54d39543 100644 --- a/bin/named/omapiconf.c +++ b/bin/named/omapiconf.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: omapiconf.c,v 1.15 2001/01/09 21:40:00 bwelling Exp $ */ +/* $Id: omapiconf.c,v 1.16 2001/03/04 21:21:24 bwelling Exp $ */ /* * Principal Author: DCL @@ -31,12 +31,23 @@ #include #include -#include +#include + +#include #include #include #include +typedef struct ns_omapikey ns_omapikey_t; + +typedef ISC_LIST(ns_omapikey_t) ns_omapikeylist_t; + +struct ns_omapikey { + char *keyname; + ISC_LINK(ns_omapikey_t) link; +}; + typedef struct ns_omapilistener ns_omapilistener_t; typedef ISC_LIST(ns_omapilistener_t) ns_omapilistenerlist_t; @@ -47,8 +58,8 @@ struct ns_omapilistener { omapi_object_t * manager; isc_sockaddr_t address; dns_acl_t * acl; - dns_c_kidlist_t * keyids; - LINK(ns_omapilistener_t) link; + ns_omapikeylist_t keyids; + ISC_LINK(ns_omapilistener_t) link; }; static ns_omapilistenerlist_t listeners; @@ -61,10 +72,19 @@ initialize_mutex(void) { RUNTIME_CHECK(isc_mutex_init(&listeners_lock) == ISC_R_SUCCESS); } +static void +free_omapikeylist(ns_omapikeylist_t *keylist, isc_mem_t *mctx) { + while (!ISC_LIST_EMPTY(*keylist)) { + ns_omapikey_t *key = ISC_LIST_HEAD(*keylist); + ISC_LIST_UNLINK(*keylist, key, link); + isc_mem_free(mctx, key->keyname); + isc_mem_put(mctx, key, sizeof(*key)); + } +} + static void free_listener(ns_omapilistener_t *listener) { - if (listener->keyids != NULL) - dns_c_kidlist_delete(&listener->keyids); + free_omapikeylist(&listener->keyids, listener->mctx); if (listener->acl != NULL) dns_acl_detach(&listener->acl); @@ -147,10 +167,84 @@ verify_connection(isc_sockaddr_t *sockaddr, void *arg) { return (ISC_TRUE); } +static isc_boolean_t +omapikeylist_find(ns_omapikeylist_t *keylist, const char *keyname) { + ns_omapikey_t *key; + + for (key = ISC_LIST_HEAD(*keylist); + key != NULL; + key = ISC_LIST_NEXT(key, link)) + { + if (strcasecmp(keyname, key->keyname) == 0) + return (ISC_TRUE); + } + return (ISC_FALSE); +} + +static isc_result_t +cfgkeylist_find(cfg_obj_t *keylist, const char *keyname, cfg_obj_t **objp) { + cfg_listelt_t *element; + const char *str; + cfg_obj_t *obj; + + for (element = cfg_list_first(keylist); + element != NULL; + element = cfg_list_next(element)) + { + obj = cfg_listelt_value(element); + str = cfg_obj_asstring(cfg_map_getname(obj)); + if (strcasecmp(str, keyname) == 0) + break; + } + if (element == NULL) + return (ISC_R_NOTFOUND); + obj = cfg_listelt_value(element); + *objp = obj; + return (ISC_R_SUCCESS); +} + +static isc_result_t +omapikeylist_fromcfg(cfg_obj_t *keylist, isc_mem_t *mctx, + ns_omapikeylist_t *keyids) +{ + cfg_listelt_t *element; + char *newstr = NULL; + const char *str; + cfg_obj_t *obj; + ns_omapikey_t *key = NULL; + + for (element = cfg_list_first(keylist); + element != NULL; + element = cfg_list_next(element)) + { + obj = cfg_listelt_value(element); + str = cfg_obj_asstring(obj); + newstr = isc_mem_strdup(mctx, str); + if (newstr == NULL) + goto cleanup; + key = isc_mem_get(mctx, sizeof(*key)); + if (key == NULL) + goto cleanup; + key->keyname = newstr; + ISC_LINK_INIT(key, link); + ISC_LIST_APPEND(*keyids, key, link); + key = NULL; + newstr = NULL; + } + return (ISC_R_SUCCESS); + + cleanup: + if (newstr != NULL) + isc_mem_free(mctx, newstr); + if (key != NULL) + isc_mem_put(mctx, key, sizeof(*key)); + free_omapikeylist(keyids, mctx); + return (ISC_R_NOMEMORY); +} + static isc_boolean_t verify_key(const char *name, unsigned int algorithm, void *arg) { ns_omapilistener_t *listener; - dns_c_kid_t *keyid = NULL; /* * XXXDCL Ideally algorithm would be checked, too, but the current @@ -161,11 +255,7 @@ verify_key(const char *name, unsigned int algorithm, void *arg) { listener = arg; - (void)dns_c_kidlist_find(listener->keyids, name, &keyid); - if (keyid != NULL) - return (ISC_TRUE); - else - return (ISC_FALSE); + return (omapikeylist_find(&listener->keyids, name)); } static isc_result_t @@ -196,11 +286,11 @@ ns_omapi_listen(ns_omapilistener_t *listener) { } static void -register_keys(dns_c_ctrl_t *control, dns_c_kdeflist_t *keydeflist, - char *socktext) -{ - dns_c_kid_t *keyid; - dns_c_kdef_t *keydef; +register_keys(cfg_obj_t *control, cfg_obj_t *keylist, char *socktext) { + char *keyid; + cfg_obj_t *key; + cfg_obj_t *keydef; + cfg_listelt_t *element; char secret[1024]; isc_buffer_t b; isc_result_t result; @@ -218,125 +308,131 @@ register_keys(dns_c_ctrl_t *control, dns_c_kdeflist_t *keydeflist, * from the controls statement in a reconfiguration are not deleted * until the server shuts down. */ - for (keyid = ISC_LIST_HEAD(control->keyidlist->keyids); - keyid != NULL; - keyid = ISC_LIST_NEXT(keyid, next)) { - omapi_auth_deregister(keyid->keyid); + for (element = cfg_list_first(keylist); + element != NULL; + element = cfg_list_next(element)) + { + key = cfg_listelt_value(element); + keyid = cfg_obj_asstring(cfg_map_getname(key)); - /* - * XXXDCL confparser.y apparently allows any keyid - * in the list even if it has not been defined with - * the keys statement. - */ - keydef = NULL; - result = dns_c_kdeflist_find(keydeflist, keyid->keyid, - &keydef); - if (result != ISC_R_SUCCESS) - isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, - NS_LOGMODULE_OMAPI, ISC_LOG_WARNING, - "couldn't find key %s for " - "use with command channel %s", - keyid->keyid, socktext); - else if (strcasecmp(keydef->algorithm, "hmac-md5") != 0) { - isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, - NS_LOGMODULE_OMAPI, ISC_LOG_WARNING, - "unsupported algorithm %s in " - "key %s for use with " - "command channel %s", - keydef->algorithm, keydef->keyid, - socktext); - result = DST_R_UNSUPPORTEDALG; - keydef = NULL; /* Prevent more error messages. */ - } + omapi_auth_deregister(keyid); - if (result == ISC_R_SUCCESS) { - isc_buffer_init(&b, secret, sizeof(secret)); - result = isc_base64_decodestring(ns_g_mctx, - keydef->secret, - &b); - } + /* + * XXXDCL confparser.y apparently allows any keyid + * in the list even if it has not been defined with + * the keys statement. + */ + keydef = NULL; + result = cfgkeylist_find(keylist, keyid, &keydef); + if (result != ISC_R_SUCCESS) + cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, + "couldn't find key %s for use with " + "command channel %s", keyid, socktext); + else { + cfg_obj_t *algobj = NULL; + cfg_obj_t *secretobj = NULL; + char *algstr = NULL; + char *secretstr = NULL; - if (keydef != NULL && result != ISC_R_SUCCESS) { - isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, - NS_LOGMODULE_OMAPI, ISC_LOG_WARNING, - "can't use secret for key %s on " - "command channel %s: %s", - keydef->keyid, socktext, - isc_result_totext(result)); - keydef = NULL; /* Prevent more error messages. */ + (void)cfg_map_get(keydef, "algorithm", &algobj); + (void)cfg_map_get(keydef, "secret", &secretobj); + INSIST(algobj != NULL && secretobj != NULL); - } else if (result == ISC_R_SUCCESS) - result = omapi_auth_register(keydef->keyid, + algstr = cfg_obj_asstring(algobj); + secretstr = cfg_obj_asstring(secretobj); + + if (strcasecmp(algstr, "hmac-md5") != 0) { + cfg_obj_log(control, ns_g_lctx, + ISC_LOG_WARNING, + "unsupported algorithm '%s' in " + "key '%s' for use with command " + "channel %s", + algstr, keyid, socktext); + continue; + } + + isc_buffer_init(&b, secret, sizeof(secret)); + result = isc_base64_decodestring(ns_g_mctx, + secretstr, &b); + + if (result != ISC_R_SUCCESS) { + cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING, + "secret for key '%s' on " + "command channel %s: %s", + keyid, socktext, + isc_result_totext(result)); + continue; + } + + result = omapi_auth_register(keyid, OMAPI_AUTH_HMACMD5, isc_buffer_base(&b), isc_buffer_usedlength(&b)); - if (keydef != NULL && result != ISC_R_SUCCESS) - isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, - NS_LOGMODULE_OMAPI, ISC_LOG_WARNING, - "couldn't register key %s for" + if (result != ISC_R_SUCCESS) + cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING, + "couldn't register key '%s' for" "use with command channel %s: %s", - keydef->keyid, socktext, + keyid, socktext, isc_result_totext(result)); + } } } static void -update_listener(ns_omapilistener_t **listenerp, dns_c_ctrl_t *control, - dns_c_ctx_t *cctx, ns_aclconfctx_t *aclconfctx, - char *socktext) +update_listener(ns_omapilistener_t **listenerp, cfg_obj_t *control, + cfg_obj_t *config, isc_sockaddr_t *addr, + ns_aclconfctx_t *aclconfctx, char *socktext) { ns_omapilistener_t *listener; + cfg_obj_t *allow; + cfg_obj_t *keys; dns_acl_t *new_acl = NULL; + ns_omapikeylist_t keyids; isc_result_t result; - for (listener = ISC_LIST_HEAD(listeners); listener != NULL; - listener = ISC_LIST_NEXT(listener, link)) { - - if (isc_sockaddr_equal(&control->u.inet_v.addr, - &listener->address)) { - /* - * There is already a listener for this sockaddr. - * Update the access list and key information. - * - * First, keep the old access list unless - * a new one can be made. - */ - result = ns_acl_fromconfig(control-> - u.inet_v.matchlist, - cctx, aclconfctx, - listener->mctx, &new_acl); - if (result == ISC_R_SUCCESS) { - dns_acl_detach(&listener->acl); - dns_acl_attach(new_acl, - &listener->acl); - dns_acl_detach(&new_acl); - } else - /* XXXDCL say the old acl is still used? */ - isc_log_write(ns_g_lctx, - ISC_LOGCATEGORY_GENERAL, - NS_LOGMODULE_OMAPI, - ISC_LOG_WARNING, - "couldn't install new acl for " - "command channel %s: %s", - socktext, - isc_result_totext(result)); - - /* - * Now update the key id list. - * XXXDCL the API for this seems incomplete. For now, - * I just reassign the pointer and set the control - * keyidlist to NULL so dns_c_ctrl_delete will not - * free it. - */ - if (listener->keyids != NULL) - dns_c_kidlist_delete(&listener->keyids); - listener->keyids = control->keyidlist; - control->keyidlist = NULL; - + for (listener = ISC_LIST_HEAD(listeners); + listener != NULL; + listener = ISC_LIST_NEXT(listener, link)) + if (isc_sockaddr_equal(addr, &listener->address)) break; - } + if (listener == NULL) { + *listenerp = NULL; + return; + } + + /* + * There is already a listener for this sockaddr. + * Update the access list and key information. + * + * First, keep the old access list unless a new one can be made. + */ + allow = cfg_tuple_get(control, "allow"); + result = ns_acl_fromconfig(allow, config, aclconfctx, + listener->mctx, &new_acl); + if (result == ISC_R_SUCCESS) { + dns_acl_detach(&listener->acl); + dns_acl_attach(new_acl, &listener->acl); + dns_acl_detach(&new_acl); + } else + /* XXXDCL say the old acl is still used? */ + cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, + "couldn't install new acl for " + "command channel %s: %s", + socktext, isc_result_totext(result)); + + keys = cfg_tuple_get(control, "keys"); + ISC_LIST_INIT(keyids); + result = omapikeylist_fromcfg(keys, listener->mctx, &keyids); + if (result != ISC_R_SUCCESS) + cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, + "couldn't install new keys for " + "command channel %s: %s", + socktext, isc_result_totext(result)); + else { + free_omapikeylist(&listener->keyids, listener->mctx); + listener->keyids = keyids; } *listenerp = listener; @@ -344,10 +440,12 @@ update_listener(ns_omapilistener_t **listenerp, dns_c_ctrl_t *control, static void add_listener(isc_mem_t *mctx, ns_omapilistener_t **listenerp, - dns_c_ctrl_t *control, dns_c_ctx_t *cctx, + cfg_obj_t *control, cfg_obj_t *config, isc_sockaddr_t *addr, ns_aclconfctx_t *aclconfctx, char *socktext) { ns_omapilistener_t *listener; + cfg_obj_t *allow; + cfg_obj_t *keys; dns_acl_t *new_acl = NULL; isc_result_t result = ISC_R_SUCCESS; @@ -358,32 +456,35 @@ add_listener(isc_mem_t *mctx, ns_omapilistener_t **listenerp, if (result == ISC_R_SUCCESS) { listener->mctx = mctx; listener->manager = NULL; - listener->address = control->u.inet_v.addr; + listener->address = *addr; ISC_LINK_INIT(listener, link); + ISC_LIST_INIT(listener->keyids); /* * Make the acl. */ - result = ns_acl_fromconfig(control->u.inet_v.matchlist, - cctx, aclconfctx, mctx, &new_acl); + allow = cfg_tuple_get(control, "allow"); + result = ns_acl_fromconfig(allow, config, aclconfctx, mctx, + &new_acl); } if (result == ISC_R_SUCCESS) { dns_acl_attach(new_acl, &listener->acl); dns_acl_detach(&new_acl); - /* - * Now update the key id list. - * XXXDCL the API for this seems incomplete. For now, - * I just reassign the pointer and set it to NULL so - * dns_c_ctrl_delete will not free it. - */ - listener->keyids = control->keyidlist; - control->keyidlist = NULL; - - result = ns_omapi_listen(listener); + keys = cfg_tuple_get(control, "keys"); + result = omapikeylist_fromcfg(keys, listener->mctx, + &listener->keyids); + if (result != ISC_R_SUCCESS) + cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, + "couldn't install new keys for " + "command channel %s: %s", + socktext, isc_result_totext(result)); } + if (result == ISC_R_SUCCESS) + result = ns_omapi_listen(listener); + if (result == ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, NS_LOGMODULE_OMAPI, ISC_LOG_NOTICE, @@ -394,10 +495,9 @@ add_listener(isc_mem_t *mctx, ns_omapilistener_t **listenerp, if (listener != NULL) free_listener(listener); - isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, - NS_LOGMODULE_OMAPI, ISC_LOG_WARNING, - "couldn't add command channel %s: %s", - socktext, isc_result_totext(result)); + cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, + "couldn't add command channel %s: %s", + socktext, isc_result_totext(result)); *listenerp = NULL; } @@ -406,25 +506,24 @@ add_listener(isc_mem_t *mctx, ns_omapilistener_t **listenerp, } isc_result_t -ns_omapi_configure(isc_mem_t *mctx, dns_c_ctx_t *cctx, +ns_omapi_configure(isc_mem_t *mctx, cfg_obj_t *config, ns_aclconfctx_t *aclconfctx) { ns_omapilistener_t *listener; ns_omapilistenerlist_t new_listeners; - dns_c_ctrllist_t *controls = NULL; - dns_c_ctrl_t *control; - dns_c_kdeflist_t *keydeflist = NULL; + cfg_obj_t *controlslist = NULL; + cfg_obj_t *keylist = NULL; + cfg_listelt_t *element, *element2; char socktext[ISC_SOCKADDR_FORMATSIZE]; - isc_result_t result; RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS); ISC_LIST_INIT(new_listeners); /* - * Get a pointer to the named.conf ``controls'' statement information. + * Get te list of named.conf 'controls' statements. */ - result = dns_c_ctx_getcontrols(cctx, &controls); + (void)cfg_map_get(config, "controls", &controlslist); LOCK(&listeners_lock); /* @@ -435,59 +534,109 @@ ns_omapi_configure(isc_mem_t *mctx, dns_c_ctx_t *cctx, * the underlying config code, or to the bind attempt getting an * address-in-use error. */ - if (result == ISC_R_SUCCESS) { - (void)dns_c_ctx_getkdeflist(cctx, &keydeflist); - if (keydeflist == NULL) - isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, - NS_LOGMODULE_OMAPI, ISC_LOG_WARNING, - "no key statements for use by " - "control channels"); + if (controlslist != NULL) { + (void)cfg_map_get(config, "key", &keylist); + if (keylist == NULL) + cfg_obj_log(controlslist, ns_g_lctx, ISC_LOG_WARNING, + "no key statements for use by " + "control channels"); - for (control = dns_c_ctrllist_head(controls); - control != NULL; - control = dns_c_ctrl_next(control)) { - /* - * The parser handles BIND 8 configuration file syntax, - * so it allows a control_type of dns_c_unix_control, - * as well as an inet phrase with no keys{} clause. - * However, it already warned that those were - * unsupported, so there is no need to do so again. - * The keydeflist == NULL case was already warned - * about a few lines above. - */ - if (control->control_type != dns_c_inet_control || - keydeflist == NULL || control->keyidlist == NULL) + for (element = cfg_list_first(controlslist); + element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *controls; + cfg_obj_t *inetcontrols = NULL; + + controls = cfg_listelt_value(element); + (void)cfg_map_get(controls, "inet", &inetcontrols); + if (inetcontrols == NULL) continue; - isc_sockaddr_format(&control->u.inet_v.addr, - socktext, sizeof(socktext)); + for (element2 = cfg_list_first(inetcontrols); + element2 != NULL; + element2 = cfg_list_next(element2)) + { + cfg_obj_t *control; + cfg_obj_t *obj; + isc_sockaddr_t *addr; - isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, - NS_LOGMODULE_OMAPI, ISC_LOG_DEBUG(9), - "processing control channel %s", - socktext); - - register_keys(control, keydeflist, socktext); - - update_listener(&listener, control, cctx, aclconfctx, - socktext); - - if (listener != NULL) /* - * Remove the listener from the old list, - * so it won't be shut down. + * The parser handles BIND 8 configuration file + * syntax, so it allows unix phrases as well + * inet phrases with no keys{} clause. + * + * "unix" phrases have been reported as + * unsupported by the parser. + * + * The keylist == NULL case was already warned + * about a few lines above. */ - ISC_LIST_UNLINK(listeners, listener, link); - else - /* - * This is a new listener. - */ - add_listener(mctx, &listener, control, cctx, - aclconfctx, socktext); + control = cfg_listelt_value(element2); - if (listener != NULL) - ISC_LIST_APPEND(new_listeners, listener, link); + obj = cfg_tuple_get(control, "address"); + addr = cfg_obj_assockaddr(obj); + if (isc_sockaddr_getport(addr) == 0) + isc_sockaddr_setport(addr, + NS_OMAPI_PORT); + isc_sockaddr_format(addr, socktext, + sizeof(socktext)); + + obj = cfg_tuple_get(control, "keys"); + + if (cfg_obj_isvoid(obj)) { + cfg_obj_log(obj, ns_g_lctx, + ISC_LOG_ERROR, + "no keys clause in " + "control channel %s", + socktext); + continue; + } + + if (cfg_list_first(obj) == NULL) { + cfg_obj_log(obj, ns_g_lctx, + ISC_LOG_ERROR, + "no keys specified in " + "control channel %s", + socktext); + continue; + } + + if (keylist == NULL) + continue; + + isc_log_write(ns_g_lctx, + ISC_LOGCATEGORY_GENERAL, + NS_LOGMODULE_OMAPI, + ISC_LOG_DEBUG(9), + "processing control channel %s", + socktext); + + register_keys(control, keylist, socktext); + + update_listener(&listener, control, config, + addr, aclconfctx, socktext); + + if (listener != NULL) + /* + * Remove the listener from the old + * list, so it won't be shut down. + */ + ISC_LIST_UNLINK(listeners, listener, + link); + else + /* + * This is a new listener. + */ + add_listener(mctx, &listener, control, + config, addr, aclconfctx, + socktext); + + if (listener != NULL) + ISC_LIST_APPEND(new_listeners, + listener, link); + } } } diff --git a/bin/named/server.c b/bin/named/server.c index 08654db51d..7a8177e5b3 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.292 2001/02/17 01:09:22 bwelling Exp $ */ +/* $Id: server.c,v 1.293 2001/03/04 21:21:26 bwelling Exp $ */ #include @@ -35,6 +35,9 @@ #include #include +#include +#include + #include #include #include @@ -57,6 +60,7 @@ #include #include +#include #include #include #include @@ -96,12 +100,6 @@ fatal(msg, result); \ } while (0) \ -typedef struct { - isc_mem_t * mctx; - dns_viewlist_t viewlist; - ns_aclconfctx_t *aclconf; -} ns_load_t; - static void fatal(const char *msg, isc_result_t result); @@ -109,18 +107,23 @@ static void ns_server_reload(isc_task_t *task, isc_event_t *event); static isc_result_t -ns_listenelt_fromconfig(dns_c_lstnon_t *celt, dns_c_ctx_t *cctx, +ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config, ns_aclconfctx_t *actx, isc_mem_t *mctx, ns_listenelt_t **target); static isc_result_t -ns_listenlist_fromconfig(dns_c_lstnlist_t *clist, dns_c_ctx_t *cctx, +ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config, ns_aclconfctx_t *actx, isc_mem_t *mctx, ns_listenlist_t **target); static isc_result_t -configure_forward(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, +configure_forward(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig, dns_view_t *view, dns_name_t *origin, - dns_c_iplist_t *forwarders); + cfg_obj_t *forwarders); + +static isc_result_t +configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig, + isc_mem_t *mctx, dns_view_t *view, + ns_aclconfctx_t *aclconf); /* * Configure a single view ACL at '*aclp'. Get its configuration by @@ -128,45 +131,45 @@ configure_forward(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, * (for a global default). */ static isc_result_t -configure_view_acl(dns_c_view_t *cview, - dns_c_ctx_t *cctx, - ns_aclconfctx_t *actx, isc_mem_t *mctx, - isc_result_t (*getvcacl) - (dns_c_view_t *, dns_c_ipmatchlist_t **), - isc_result_t (*getscacl) - (dns_c_ctx_t *, dns_c_ipmatchlist_t **), - dns_acl_t **aclp) +configure_view_acl(cfg_obj_t *vconfig, cfg_obj_t *config, + const char *aclname, ns_aclconfctx_t *actx, + isc_mem_t *mctx, dns_acl_t **aclp) { isc_result_t result; + cfg_obj_t *maps[3]; + cfg_obj_t *aclobj = NULL; + int i = 0; - dns_c_ipmatchlist_t *cacl = NULL; - if (*aclp != NULL) - dns_acl_detach(aclp); - if (getvcacl != NULL && cview != NULL) - (void)(*getvcacl)(cview, &cacl); - if (cacl == NULL && getscacl != NULL) - (void)(*getscacl)(cctx, &cacl); - if (cacl == NULL) { + if (vconfig != NULL) + maps[i++] = cfg_tuple_get(vconfig, "options"); + if (config != NULL) { + cfg_obj_t *options = NULL; + cfg_map_get(config, "options", &options); + if (options != NULL) + maps[i++] = options; + } + maps[i] = NULL; + + result = ns_config_get(maps, aclname, &aclobj); + if (aclobj == NULL) /* * No value available. *aclp == NULL. */ return (ISC_R_SUCCESS); - } - result = ns_acl_fromconfig(cacl, cctx, actx, mctx, aclp); - - dns_c_ipmatchlist_detach(&cacl); + result = ns_acl_fromconfig(aclobj, config, actx, mctx, aclp); return (result); } static isc_result_t -configure_view_dnsseckey(dns_c_view_t *cview, dns_c_tkey_t *ckey, +configure_view_dnsseckey(cfg_obj_t *vconfig, cfg_obj_t *key, dns_keytable_t *keytable, isc_mem_t *mctx) { dns_rdataclass_t viewclass; dns_rdata_key_t keystruct; - isc_int32_t flags, proto, alg; + isc_uint32_t flags, proto, alg; + char *keystr, *keynamestr; unsigned char keydata[4096]; isc_buffer_t keydatabuf; unsigned char rrdata[4096]; @@ -178,39 +181,42 @@ configure_view_dnsseckey(dns_c_view_t *cview, dns_c_tkey_t *ckey, isc_result_t result; dst_key_t *dstkey = NULL; - if (cview == NULL) + flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); + proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); + alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); + keyname = dns_fixedname_name(&fkeyname); + keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); + + if (vconfig == NULL) viewclass = dns_rdataclass_in; - else - CHECK(dns_c_view_getviewclass(cview, - &viewclass)); + else { + cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class"); + CHECK(ns_config_getclass(classobj, &viewclass)); + } keystruct.common.rdclass = viewclass; keystruct.common.rdtype = dns_rdatatype_key; /* - * The key data in keystruct is not - * dynamically allocated. + * The key data in keystruct is not dynamically allocated. */ keystruct.mctx = NULL; ISC_LINK_INIT(&keystruct.common, link); - flags = ckey->pubkey->flags; - proto = ckey->pubkey->protocol; - alg = ckey->pubkey->algorithm; - if (flags < 0 || flags > 0xffff) + if (flags > 0xffff) CHECKM(ISC_R_RANGE, "key flags"); - if (proto < 0 || proto > 0xff) + if (proto > 0xff) CHECKM(ISC_R_RANGE, "key protocol"); - if (alg < 0 || alg > 0xff) + if (alg > 0xff) CHECKM(ISC_R_RANGE, "key algorithm"); - keystruct.flags = flags; - keystruct.protocol = proto; - keystruct.algorithm = alg; + keystruct.flags = (isc_uint16_t)flags; + keystruct.protocol = (isc_uint8_t)proto; + keystruct.algorithm = (isc_uint8_t)alg; isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); - CHECK(isc_base64_decodestring(mctx, ckey->pubkey->key, - &keydatabuf)); + keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); + CHECK(isc_base64_decodestring(mctx, keystr, &keydatabuf)); isc_buffer_usedregion(&keydatabuf, &r); keystruct.datalen = r.length; keystruct.data = r.base; @@ -220,10 +226,8 @@ configure_view_dnsseckey(dns_c_view_t *cview, dns_c_tkey_t *ckey, keystruct.common.rdtype, &keystruct, &rrdatabuf)); dns_fixedname_init(&fkeyname); - keyname = dns_fixedname_name(&fkeyname); - isc_buffer_init(&namebuf, ckey->domain, - strlen(ckey->domain)); - isc_buffer_add(&namebuf, strlen(ckey->domain)); + isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr)); + isc_buffer_add(&namebuf, strlen(keynamestr)); CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, ISC_FALSE, NULL)); @@ -235,11 +239,9 @@ configure_view_dnsseckey(dns_c_view_t *cview, dns_c_tkey_t *ckey, return (ISC_R_SUCCESS); cleanup: - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_SERVER, ISC_LOG_ERROR, - "configuring trusted key for '%s': " - "%s", ckey->domain, - isc_result_totext(result)); + cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, + "configuring trusted key for '%s': %s", + keynamestr, isc_result_totext(result)); result = ISC_R_FAILURE; if (dstkey != NULL) @@ -252,43 +254,46 @@ configure_view_dnsseckey(dns_c_view_t *cview, dns_c_tkey_t *ckey, * Configure DNSSEC keys for a view. Currently used only for * the security roots. * - * The per-view configuration values and their server-global - * defaults are are read from 'cview' and 'cctx' using - * the function 'cgetv' and 'cgets', respectively. - * The variable to be configured is '*target'. + * The per-view configuration values and the server-global defaults are read + * from 'vconfig' and 'config'. The variable to be configured is '*target'. */ static isc_result_t -configure_view_dnsseckeys(dns_c_view_t *cview, - dns_c_ctx_t *cctx, - isc_mem_t *mctx, - isc_result_t (*cgetv) - (dns_c_view_t *, dns_c_tkeylist_t **), - isc_result_t (*cgets) - (dns_c_ctx_t *, dns_c_tkeylist_t **), - dns_keytable_t **target) +configure_view_dnsseckeys(cfg_obj_t *vconfig, cfg_obj_t *config, + isc_mem_t *mctx, dns_keytable_t **target) { isc_result_t result; - dns_c_tkeylist_t *ckeys = NULL; - dns_c_tkey_t *ckey; + cfg_obj_t *keys = NULL; + cfg_obj_t *voptions = NULL; + cfg_listelt_t *element, *element2; + cfg_obj_t *keylist; + cfg_obj_t *key; dns_keytable_t *keytable = NULL; CHECK(dns_keytable_create(mctx, &keytable)); - result = ISC_R_FAILURE; - if (cgetv != NULL && cview != NULL) - result = (*cgetv)(cview, &ckeys); - if (result != ISC_R_SUCCESS) - result = (*cgets)(cctx, &ckeys); + if (vconfig != NULL) + voptions = cfg_tuple_get(vconfig, "options"); - if (result == ISC_R_SUCCESS) { - for (ckey = ISC_LIST_HEAD(ckeys->tkeylist); - ckey != NULL; - ckey = ISC_LIST_NEXT(ckey, next)) { - CHECK(configure_view_dnsseckey(cview, ckey, + keys = NULL; + if (voptions != NULL) + (void)cfg_map_get(voptions, "trusted-keys", &keys); + if (keys == NULL) + (void)cfg_map_get(config, "trusted-keys", &keys); + + for (element = cfg_list_first(keys); + element != NULL; + element = cfg_list_next(element)) + { + keylist = cfg_listelt_value(element); + for (element2 = cfg_list_first(keylist); + element2 != NULL; + element2 = cfg_list_next(element2)) + { + key = cfg_listelt_value(element2); + CHECK(configure_view_dnsseckey(vconfig, key, keytable, mctx)); } - } else if (result != ISC_R_NOTFOUND) - goto cleanup; + } dns_keytable_detach(target); *target = keytable; /* Transfer ownership. */ @@ -304,13 +309,14 @@ configure_view_dnsseckeys(dns_c_view_t *cview, * Get a dispatch appropriate for the resolver of a given view. */ static isc_result_t -get_view_querysource_dispatch(dns_c_ctx_t *cctx, dns_c_view_t *cview, +get_view_querysource_dispatch(cfg_obj_t **maps, int af, dns_dispatch_t **dispatchp) { isc_result_t result; dns_dispatch_t *disp; isc_sockaddr_t sa; unsigned int attrs, attrmask; + cfg_obj_t *obj = NULL; /* * Make compiler happy. @@ -319,27 +325,19 @@ get_view_querysource_dispatch(dns_c_ctx_t *cctx, dns_c_view_t *cview, switch (af) { case AF_INET: - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_getquerysource(cview, &sa); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getquerysource(cctx, &sa); - if (result != ISC_R_SUCCESS) - isc_sockaddr_any(&sa); + result = ns_config_get(maps, "query-source", &obj); + INSIST(result == ISC_R_SUCCESS); + break; case AF_INET6: - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_getquerysourcev6(cview, &sa); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getquerysourcev6(cctx, &sa); - if (result != ISC_R_SUCCESS) - isc_sockaddr_any6(&sa); + result = ns_config_get(maps, "query-source-v6", &obj); + INSIST(result == ISC_R_SUCCESS); break; default: INSIST(0); } + sa = *(cfg_obj_assockaddr(obj)); INSIST(isc_sockaddr_pf(&sa) == af); /* @@ -394,44 +392,151 @@ get_view_querysource_dispatch(dns_c_ctx_t *cctx, dns_c_view_t *cview, return (ISC_R_SUCCESS); } +static isc_result_t +configure_peer(cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { + isc_sockaddr_t *sa; + isc_netaddr_t na; + dns_peer_t *peer; + cfg_obj_t *obj; + char *str; + isc_result_t result; + + sa = cfg_obj_assockaddr(cfg_map_getname(cpeer)); + isc_netaddr_fromsockaddr(&na, sa); + + peer = NULL; + result = dns_peer_new(mctx, &na, &peer); + if (result != ISC_R_SUCCESS) + return (result); + + obj = NULL; + (void)cfg_map_get(cpeer, "bogus", &obj); + if (obj != NULL) + dns_peer_setbogus(peer, cfg_obj_asboolean(obj)); + + obj = NULL; + (void)cfg_map_get(cpeer, "provide-ixfr", &obj); + if (obj != NULL) + dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)); + + obj = NULL; + (void)cfg_map_get(cpeer, "request-ixfr", &obj); + if (obj != NULL) + dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)); + + obj = NULL; + (void)cfg_map_get(cpeer, "transfers", &obj); + if (obj != NULL) + dns_peer_settransfers(peer, cfg_obj_asuint32(obj)); + + obj = NULL; + (void)cfg_map_get(cpeer, "transfer-format", &obj); + if (obj != NULL) { + str = cfg_obj_asstring(obj); + if (strcasecmp(str, "many-answers") == 0) + dns_peer_settransferformat(peer, dns_many_answers); + else if (strcasecmp(str, "one-answer") == 0) + dns_peer_settransferformat(peer, dns_one_answer); + else + INSIST(0); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "keys", &obj); + if (obj != NULL) { + result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + *peerp = peer; + return (ISC_R_SUCCESS); + + cleanup: + dns_peer_detach(&peer); + return (result); +} + /* - * Configure 'view' according to 'cview', taking defaults from 'cctx' - * where values are missing in cview. + * Configure 'view' according to 'vconfig', taking defaults from 'config' + * where values are missing in 'vconfig'. * - * When configuring the default view, cview will be NULL and the - * global defaults in cctx used exclusively. + * When configuring the default view, 'vconfig' will be NULL and the + * global defaults in 'config' used exclusively. */ static isc_result_t -configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview, +configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, isc_mem_t *mctx, ns_aclconfctx_t *actx) { + cfg_obj_t *maps[4]; + cfg_obj_t *cfgmaps[3]; + cfg_obj_t *options = NULL; + cfg_obj_t *voptions = NULL; + cfg_obj_t *forwarders; + cfg_obj_t *zonelist; + cfg_obj_t *obj; + cfg_listelt_t *element; + in_port_t port; dns_cache_t *cache = NULL; isc_result_t result; - isc_uint32_t cleaning_interval; isc_uint32_t max_cache_size; isc_uint32_t lame_ttl; dns_tsig_keyring_t *ring; - dns_c_iplist_t *forwarders; dns_view_t *pview = NULL; /* Production view */ isc_mem_t *cmctx; dns_dispatch_t *dispatch4 = NULL; dns_dispatch_t *dispatch6 = NULL; - in_port_t port; isc_boolean_t reused_cache = ISC_FALSE; - char *cachefile = NULL; + int i; + char *str; REQUIRE(DNS_VIEW_VALID(view)); cmctx = NULL; + if (config != NULL) + cfg_map_get(config, "options", &options); + + i = 0; + if (vconfig != NULL) { + voptions = cfg_tuple_get(vconfig, "options"); + maps[i++] = voptions; + } + if (options != NULL) + maps[i++] = options; + maps[i++] = ns_g_defaults; + maps[i] = NULL; + + i = 0; + if (voptions != NULL) + cfgmaps[i++] = voptions; + if (config != NULL) + cfgmaps[i++] = config; + cfgmaps[i] = NULL; + + /* * Set the view's port number for outgoing queries. */ - result = dns_c_ctx_getport(cctx, &port); - if (result != ISC_R_SUCCESS) - port = 53; + CHECKM(ns_config_getport(config, &port), "port"); dns_view_setdstport(view, port); + /* + * Configure the zones. + */ + zonelist = NULL; + if (voptions != NULL) + (void)cfg_map_get(voptions, "zone", &zonelist); + else + (void)cfg_map_get(config, "zone", &zonelist); + for (element = cfg_list_first(zonelist); + element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *zconfig = cfg_listelt_value(element); + CHECK(configure_zone(config, zconfig, vconfig, mctx, view, + actx)); + } + /* * Configure the view's cache. Try to reuse an existing * cache if possible, otherwise create a new cache. @@ -465,37 +570,46 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview, } dns_view_setcache(view, cache); - if (cview != NULL) - result = dns_c_view_getcachefile(cview, &cachefile); - else - result = dns_c_ctx_getcachefile(cctx, &cachefile); - if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) - goto cleanup; - if (cachefile != NULL) { - dns_cache_setfilename(cache, cachefile); + /* + * cache-file cannot be inherited if views are present, but this + * should be caught by the configuration checking stage. + */ + obj = NULL; + result = ns_config_get(maps, "cache-file", &obj); + if (result == ISC_R_SUCCESS) { + dns_cache_setfilename(cache, cfg_obj_asstring(obj)); if (!reused_cache) CHECK(dns_cache_load(cache)); } - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_getcleaninterval(cview, - &cleaning_interval); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getcleaninterval(cctx, &cleaning_interval); - if (result != ISC_R_SUCCESS) - cleaning_interval = 3600; /* Default is 1 hour. */ - dns_cache_setcleaninginterval(cache, cleaning_interval); + obj = NULL; + result = ns_config_get(maps, "cleaning-interval", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_cache_setcleaninginterval(cache, cfg_obj_asuint32(obj)); + + obj = NULL; + result = ns_config_get(maps, "max-cache-size", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_isstring(obj)) { + str = cfg_obj_asstring(obj); + INSIST(strcasecmp(str, "unlimited") == 0); + max_cache_size = ISC_UINT32_MAX; + } else { + isc_resourcevalue_t value; + value = cfg_obj_asuint64(obj); + if (value > ISC_UINT32_MAX) { + cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, + "'max-cache-size " + "%" ISC_PRINT_QUADFORMAT "d' is too large", + value); + result = ISC_R_RANGE; + goto cleanup; + } + max_cache_size = (isc_uint32_t)value; + } - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_getmaxcachesize(cview, &max_cache_size); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getmaxcachesize(cctx, &max_cache_size); - if (result != ISC_R_SUCCESS) - max_cache_size = 0; /* - * XXX remove once rbt if fixed + * XXX remove once rbt is fixed */ max_cache_size = 0; dns_cache_setcachesize(cache, max_cache_size); @@ -507,10 +621,8 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview, * * XXXRTH Hardwired number of tasks. */ - CHECK(get_view_querysource_dispatch(cctx, cview, AF_INET, - &dispatch4)); - CHECK(get_view_querysource_dispatch(cctx, cview, AF_INET6, - &dispatch6)); + CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4)); + CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6)); CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31, ns_g_socketmgr, ns_g_timermgr, 0, ns_g_dispatchmgr, @@ -523,14 +635,10 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview, /* * Set resolver's lame-ttl. */ - if (cview != NULL) - result = dns_c_view_getlamettl(cview, &lame_ttl); - else - result = ISC_R_NOTFOUND; - if (result == ISC_R_NOTFOUND) - result = dns_c_ctx_getlamettl(cctx, &lame_ttl); - if (result == ISC_R_NOTFOUND) - lame_ttl = 600; + obj = NULL; + result = ns_config_get(maps, "lame-ttl", &obj); + INSIST(result == ISC_R_SUCCESS); + lame_ttl = cfg_obj_asuint32(obj); if (lame_ttl > 18000) lame_ttl = 18000; dns_resolver_setlamettl(view->resolver, lame_ttl); @@ -538,14 +646,10 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview, /* * Set resolver forwarding policy. */ - if ((cview != NULL && - dns_c_view_getforwarders(cview, &forwarders) == ISC_R_SUCCESS) || - (dns_c_ctx_getforwarders(cctx, &forwarders) == ISC_R_SUCCESS)) - { - result = configure_forward(cctx, NULL, cview, view, - dns_rootname, forwarders); - dns_c_iplist_detach(&forwarders); - } + forwarders = NULL; + (void)ns_config_get(maps, "forwarders", &forwarders); + result = configure_forward(config, NULL, vconfig, + view, dns_rootname, forwarders); /* * We have default hints for class IN if we need them. @@ -569,8 +673,7 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview, isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "no root hints for view '%s'", - cview == NULL ? "" : - cview->name); + view->name); } } @@ -578,24 +681,30 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview, * Configure the view's TSIG keys. */ ring = NULL; - CHECK(ns_tsigkeyring_fromconfig(cview, cctx, view->mctx, &ring)); + CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); dns_view_setkeyring(view, ring); /* * Configure the view's peer list. */ { + cfg_obj_t *peers = NULL; + cfg_listelt_t *element; dns_peerlist_t *newpeers = NULL; - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_getpeerlist(cview, &newpeers); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getpeerlist(cctx, &newpeers); - if (result != ISC_R_SUCCESS) - result = dns_peerlist_new(mctx, &newpeers); - CHECK(result); + (void)ns_config_get(cfgmaps, "server", &peers); + CHECK(dns_peerlist_new(mctx, &newpeers)); + for (element = cfg_list_first(peers); + element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *cpeer = cfg_listelt_value(element); + dns_peer_t *peer; + CHECK(configure_peer(cpeer, mctx, &peer)); + dns_peerlist_addpeer(newpeers, peer); + dns_peer_detach(&peer); + } dns_peerlist_detach(&view->peers); view->peers = newpeers; /* Transfer ownership. */ } @@ -603,125 +712,86 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview, /* * Configure the "match-clients" ACL. */ - CHECK(configure_view_acl(cview, cctx, actx, ns_g_mctx, - dns_c_view_getmatchclients, NULL, - &view->matchclients)); + CHECK(configure_view_acl(vconfig, config, "match-clients", actx, + ns_g_mctx, &view->matchclients)); /* * Configure other configurable data. */ - view->recursion = ISC_TRUE; - (void)dns_c_ctx_getrecursion(cctx, &view->recursion); - if (cview != NULL) - (void)dns_c_view_getrecursion(cview, &view->recursion); + obj = NULL; + result = ns_config_get(maps, "recursion", &obj); + INSIST(result == ISC_R_SUCCESS); + view->recursion = cfg_obj_asboolean(obj); - view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */ - (void)dns_c_ctx_getauthnxdomain(cctx, &view->auth_nxdomain); - if (cview != NULL) - (void)dns_c_view_getauthnxdomain(cview, &view->auth_nxdomain); + obj = NULL; + result = ns_config_get(maps, "auth-nxdomain", &obj); + INSIST(result == ISC_R_SUCCESS); + view->auth_nxdomain = cfg_obj_asboolean(obj); - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_gettransferformat(cview, - &view->transfer_format); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_gettransferformat(cctx, - &view->transfer_format); - if (result != ISC_R_SUCCESS) + obj = NULL; + result = ns_config_get(maps, "transfer-format", &obj); + INSIST(result == ISC_R_SUCCESS); + str = cfg_obj_asstring(obj); + if (strcasecmp(str, "many-answers") == 0) view->transfer_format = dns_many_answers; - + else if (strcasecmp(str, "one-answer") == 0) + view->transfer_format = dns_one_answer; + else + INSIST(0); + /* * Set sources where additional data, CNAMEs, and DNAMEs may be found. */ - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_getadditionalfromauth(cview, - &view->additionalfromauth); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getadditionalfromauth(cctx, - &view->additionalfromauth); - if (result != ISC_R_SUCCESS) - view->additionalfromauth = ISC_TRUE; + obj = NULL; + result = ns_config_get(maps, "additional-from-auth", &obj); + INSIST(result == ISC_R_SUCCESS); + view->additionalfromauth = cfg_obj_asboolean(obj); - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_getadditionalfromcache(cview, - &view->additionalfromcache); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getadditionalfromcache(cctx, - &view->additionalfromcache); - if (result != ISC_R_SUCCESS) - view->additionalfromcache = ISC_TRUE; + obj = NULL; + result = ns_config_get(maps, "additional-from-cache", &obj); + INSIST(result == ISC_R_SUCCESS); + view->additionalfromcache = cfg_obj_asboolean(obj); - CHECK(configure_view_acl(cview, cctx, actx, ns_g_mctx, - dns_c_view_getallowquery, - dns_c_ctx_getallowquery, - &view->queryacl)); + CHECK(configure_view_acl(vconfig, config, "allow-query", + actx, ns_g_mctx, &view->queryacl)); - CHECK(configure_view_acl(cview, cctx, actx, ns_g_mctx, - dns_c_view_getrecursionacl, - dns_c_ctx_getallowrecursion, - &view->recursionacl)); + CHECK(configure_view_acl(vconfig, config, "allow-recursion", + actx, ns_g_mctx, &view->recursionacl)); - CHECK(configure_view_acl(cview, cctx, actx, ns_g_mctx, - dns_c_view_getv6synthesisacl, - dns_c_ctx_getallowv6synthesis, - &view->v6synthesisacl)); + CHECK(configure_view_acl(vconfig, config, "allow-v6-synthesis", + actx, ns_g_mctx, &view->v6synthesisacl)); - CHECK(configure_view_acl(cview, cctx, actx, ns_g_mctx, - dns_c_view_getsortlist, - dns_c_ctx_getsortlist, - &view->sortlist)); + CHECK(configure_view_acl(vconfig, config, "sortlist", + actx, ns_g_mctx, &view->sortlist)); - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_getrequestixfr(cview, &view->requestixfr); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getrequestixfr(cctx, &view->requestixfr); - if (result != ISC_R_SUCCESS) - view->requestixfr = ISC_TRUE; + obj = NULL; + result = ns_config_get(maps, "request-ixfr", &obj); + INSIST(result == ISC_R_SUCCESS); + view->requestixfr = cfg_obj_asboolean(obj); - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_getprovideixfr(cview, &view->provideixfr); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getprovideixfr(cctx, &view->provideixfr); - if (result != ISC_R_SUCCESS) - view->provideixfr = ISC_TRUE; + obj = NULL; + result = ns_config_get(maps, "provide-ixfr", &obj); + INSIST(result == ISC_R_SUCCESS); + view->provideixfr = cfg_obj_asboolean(obj); /* * For now, there is only one kind of trusted keys, the * "security roots". */ - CHECK(configure_view_dnsseckeys(cview, cctx, mctx, - dns_c_view_gettrustedkeys, - dns_c_ctx_gettrustedkeys, + CHECK(configure_view_dnsseckeys(vconfig, config, mctx, &view->secroots)); - { - isc_uint32_t val; - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_getmaxcachettl(cview, &val); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getmaxcachettl(cctx, &val); - if (result != ISC_R_SUCCESS) - val = 7 * 24 * 3600; - view->maxcachettl = val; - } - { - isc_uint32_t val; - result = ISC_R_NOTFOUND; - if (cview != NULL) - result = dns_c_view_getmaxncachettl(cview, &val); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getmaxncachettl(cctx, &val); - if (result != ISC_R_SUCCESS) - val = 3 * 3600; - if (val > 7 * 24 * 3600) - val = 7 * 24 * 3600; - view->maxncachettl = val; - } + obj = NULL; + result = ns_config_get(maps, "max-cache-ttl", &obj); + INSIST(result == ISC_R_SUCCESS); + view->maxcachettl = cfg_obj_asuint32(obj); + + obj = NULL; + result = ns_config_get(maps, "max-ncache-ttl", &obj); + INSIST(result == ISC_R_SUCCESS); + view->maxncachettl = cfg_obj_asuint32(obj); + if (view->maxncachettl > 7 * 24 * 3600) + view->maxncachettl = 7 * 24 * 3600; result = ISC_R_SUCCESS; @@ -729,6 +799,9 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview, if (cmctx != NULL) isc_mem_detach(&cmctx); + if (cache != NULL) + dns_cache_detach(&cache); + return (result); } @@ -761,14 +834,12 @@ create_bind_view(dns_view_t **viewp) /* - * Create the zone that handles queries for - * "version.bind. CH". The version string returned is that - * configured in 'cctx', or a compiled-in default if - * there is no "version" configuration option. + * Create the zone that handles queries for "version.bind. CH". The + * version string returned either from the "version" configuration + * option or the global defaults. */ static isc_result_t -create_version_zone(dns_c_ctx_t *cctx, dns_zonemgr_t *zmgr, dns_view_t *view) -{ +create_version_zone(cfg_obj_t **maps, dns_zonemgr_t *zmgr, dns_view_t *view) { isc_result_t result; dns_db_t *db = NULL; dns_zone_t *zone = NULL; @@ -782,6 +853,7 @@ create_version_zone(dns_c_ctx_t *cctx, dns_zonemgr_t *zmgr, dns_view_t *view) dns_rdata_t rdata = DNS_RDATA_INIT; static unsigned char origindata[] = "\007version\004bind"; dns_name_t origin; + cfg_obj_t *obj = NULL; dns_diff_init(ns_g_mctx, &diff); @@ -790,15 +862,9 @@ create_version_zone(dns_c_ctx_t *cctx, dns_zonemgr_t *zmgr, dns_view_t *view) r.length = sizeof(origindata); dns_name_fromregion(&origin, &r); - result = dns_c_ctx_getversion(cctx, &versiontext); - if (result != ISC_R_SUCCESS) - /* - * Removing the const qualifier from ns_g_version is ok - * because the resulting string is not modified, only - * copied into a new buffer. - */ - DE_CONST(ns_g_version, versiontext); - + result = ns_config_get(maps, "version", &obj); + INSIST(result == ISC_R_SUCCESS); + versiontext = cfg_obj_asstring(obj); len = strlen(versiontext); if (len > 255) len = 255; /* Silently truncate. */ @@ -853,7 +919,8 @@ create_version_zone(dns_c_ctx_t *cctx, dns_zonemgr_t *zmgr, dns_view_t *view) * the BIND 9 authors. */ static isc_result_t -create_authors_zone(dns_c_ctx_t *cctx, dns_zonemgr_t *zmgr, dns_view_t *view) { +create_authors_zone(cfg_obj_t *options, dns_zonemgr_t *zmgr, dns_view_t *view) +{ isc_result_t result; dns_db_t *db = NULL; dns_zone_t *zone = NULL; @@ -866,7 +933,6 @@ create_authors_zone(dns_c_ctx_t *cctx, dns_zonemgr_t *zmgr, dns_view_t *view) { static const char origindata[] = "\007authors\004bind"; dns_name_t origin; int i; - char *versiontext; static const char *authors[] = { "\014Mark Andrews", "\015James Brister", @@ -881,12 +947,13 @@ create_authors_zone(dns_c_ctx_t *cctx, dns_zonemgr_t *zmgr, dns_view_t *view) { "\020Brian Wellington", NULL, }; + cfg_obj_t *obj = NULL; /* * If a version string is specified, disable the authors.bind zone. */ - result = dns_c_ctx_getversion(cctx, &versiontext); - if (result == ISC_R_SUCCESS) + if (options != NULL && + cfg_map_get(options, "version", &obj) == ISC_R_SUCCESS) return (ISC_R_SUCCESS); dns_diff_init(ns_g_mctx, &diff); @@ -960,11 +1027,15 @@ configure_hints(dns_view_t *view, const char *filename) { } static isc_result_t -configure_forward(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, - dns_view_t *view, dns_name_t *origin, - dns_c_iplist_t *forwarders) +configure_forward(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig, + dns_view_t *view, dns_name_t *origin, cfg_obj_t *forwarders) { - dns_c_forw_t forward; + cfg_obj_t *obj; + cfg_obj_t *maps[5]; + cfg_obj_t *options; + cfg_obj_t *portobj; + cfg_obj_t *faddresses; + cfg_listelt_t *element; dns_fwdpolicy_t fwdpolicy; isc_sockaddrlist_t addresses; isc_sockaddr_t *sa; @@ -972,30 +1043,59 @@ configure_forward(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, in_port_t port; unsigned int i; + options = NULL; + if (config != NULL) + (void)cfg_map_get(config, "options", &options); + + i = 0; + if (zconfig != NULL) + maps[i++] = cfg_tuple_get(zconfig, "options"); + if (vconfig != NULL) + maps[i++] = cfg_tuple_get(vconfig, "options"); + if (options != NULL) + maps[i++] = options; + maps[i++] = ns_g_defaults; + maps[i++] = NULL; + /* * Determine which port to send forwarded requests to. */ - if (ns_g_port != 0) { - port = ns_g_port; - } else { - result = dns_c_ctx_getport(cctx, &port); - if (result != ISC_R_SUCCESS) - port = 53; + CHECKM(ns_config_getport(config, &port), "port"); + + if (forwarders != NULL) { + portobj = cfg_tuple_get(forwarders, "port"); + if (cfg_obj_isuint32(portobj)) { + isc_uint32_t val = cfg_obj_asuint32(portobj); + if (val > ISC_UINT16_MAX) { + cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, + "port '%u' out of range", val); + return (ISC_R_RANGE); + } + port = (in_port_t) val; + } } + faddresses = NULL; + if (forwarders != NULL) + faddresses = cfg_tuple_get(forwarders, "addresses"); + ISC_LIST_INIT(addresses); - if (forwarders != NULL) { - for (i = 0; i < forwarders->nextidx; i++) { - sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t)); - if (sa == NULL) { - result = ISC_R_NOMEMORY; - goto cleanup; - } - *sa = forwarders->ips[i]; - ISC_LINK_INIT(sa, link); - ISC_LIST_APPEND(addresses, sa, link); + for (element = cfg_list_first(faddresses); + element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *forwarder = cfg_listelt_value(element); + sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t)); + if (sa == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; } + *sa = *cfg_obj_assockaddr(forwarder); + if (isc_sockaddr_getport(sa) == 0) + isc_sockaddr_setport(sa, port); + ISC_LINK_INIT(sa, link); + ISC_LIST_APPEND(addresses, sa, link); } if (ISC_LIST_EMPTY(addresses)) @@ -1003,16 +1103,16 @@ configure_forward(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, else fwdpolicy = dns_fwdpolicy_first; - if ((czone != NULL && - dns_c_zone_getforward(czone, &forward) == ISC_R_SUCCESS) || - (cview != NULL && - dns_c_view_getforward(cview, &forward) == ISC_R_SUCCESS) || - dns_c_ctx_getforward(cctx, &forward) == ISC_R_SUCCESS) - { - INSIST(forward == dns_c_forw_first || - forward == dns_c_forw_only); - if (forward == dns_c_forw_only) + obj = NULL; + result = ns_config_get(maps, "forward", &obj); + if (result == ISC_R_SUCCESS) { + char *forwardstr = cfg_obj_asstring(obj); + if (strcasecmp(forwardstr, "first") == 0) + fwdpolicy = dns_fwdpolicy_first; + else if (strcasecmp(forwardstr, "only") == 0) fwdpolicy = dns_fwdpolicy_only; + else + INSIST(0); } result = dns_fwdtable_add(view->fwdtable, origin, &addresses, @@ -1034,37 +1134,32 @@ configure_forward(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, } /* - * Find an existing view matching the name and class of 'cview' - * in 'viewlist', or create a new one and add it to the list. + * Create a new view and add it to the list. * - * If 'cview' is NULL, find or create the default view. + * If 'vconfig' is NULL, find or create the default view. * * The view found or created is attached to '*viewp'. */ static isc_result_t -find_or_create_view(dns_c_view_t *cview, dns_viewlist_t *viewlist, - dns_view_t **viewp) -{ +create_view(cfg_obj_t *vconfig, dns_viewlist_t *viewlist, dns_view_t **viewp) { isc_result_t result; const char *viewname; dns_rdataclass_t viewclass; dns_view_t *view = NULL; - if (cview != NULL) { - viewname = cview->name; - result = dns_c_view_getviewclass(cview, &viewclass); - if (result != ISC_R_SUCCESS) - return (result); + if (vconfig != NULL) { + cfg_obj_t *classobj = NULL; + + viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); + classobj = cfg_tuple_get(vconfig, "class"); + result = ns_config_getclass(classobj, &viewclass); } else { viewname = "_default"; viewclass = dns_rdataclass_in; } - result = dns_viewlist_find(viewlist, viewname, - viewclass, &view); - if (result == ISC_R_SUCCESS) { - *viewp = view; - return (ISC_R_SUCCESS); - } + result = dns_viewlist_find(viewlist, viewname, viewclass, &view); + if (result == ISC_R_SUCCESS) + return (ISC_R_EXISTS); if (result != ISC_R_NOTFOUND) return (result); INSIST(view == NULL); @@ -1083,72 +1178,89 @@ find_or_create_view(dns_c_view_t *cview, dns_viewlist_t *viewlist, * is called after parsing each "zone" statement in named.conf. */ static isc_result_t -configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, - void *uap) +configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig, + isc_mem_t *mctx, dns_view_t *view, + ns_aclconfctx_t *aclconf) { - ns_load_t *lctx = (ns_load_t *) uap; - dns_view_t *view = NULL; /* New view */ dns_view_t *pview = NULL; /* Production view */ dns_zone_t *zone = NULL; /* New or reused zone */ dns_zone_t *dupzone = NULL; - dns_c_iplist_t *forwarders = NULL; - dns_c_forw_t tfwd; - + cfg_obj_t *options = NULL; + cfg_obj_t *zoptions = NULL; + cfg_obj_t *typeobj = NULL; + cfg_obj_t *forwarders = NULL; isc_result_t result; - - char *corigin; isc_buffer_t buffer; dns_fixedname_t fixorigin; dns_name_t *origin; + const char *zname; + dns_rdataclass_t zclass; + const char *ztypestr; + dns_zonetype_t ztype; + + options = NULL; + (void)cfg_map_get(config, "options", &options); + + zoptions = cfg_tuple_get(zconfig, "options"); /* * Get the zone origin as a dns_name_t. */ - corigin = NULL; - /* XXX casting away const */ - CHECK(dns_c_zone_getname(czone, (const char **) &corigin)); - isc_buffer_init(&buffer, corigin, strlen(corigin)); - isc_buffer_add(&buffer, strlen(corigin)); + zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); + isc_buffer_init(&buffer, zname, strlen(zname)); + isc_buffer_add(&buffer, strlen(zname)); dns_fixedname_init(&fixorigin); CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), &buffer, dns_rootname, ISC_FALSE, NULL)); origin = dns_fixedname_name(&fixorigin); - /* - * Find or create the view in the new view list. - */ - view = NULL; - CHECK(find_or_create_view(cview, &lctx->viewlist, &view)); - - if (czone->zclass != view->rdclass) { + CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"), &zclass)); + if (zclass != view->rdclass) { + const char *vname = NULL; + if (vconfig != NULL) + vname = cfg_obj_asstring(cfg_tuple_get(vconfig, + "name")); + else + vname = ""; + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, - "zone '%s': wrong class for view '%s'", - corigin, cview ? cview->name : ""); + "zone '%s': wrong class for view '%s'", + zname, vname); result = ISC_R_FAILURE; goto cleanup; } + (void)cfg_map_get(zoptions, "type", &typeobj); + if (typeobj == NULL) { + cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, + "zone '%s' 'type' not specified", zname); + return (ISC_R_FAILURE); + } + ztypestr = cfg_obj_asstring(typeobj); + /* * "hints zones" aren't zones. If we've got one, * configure it and return. */ - if (czone->ztype == dns_c_zone_hint) { - if (czone->u.hzone.file == NULL) { + if (strcasecmp(ztypestr, "hint") == 0) { + cfg_obj_t *fileobj = NULL; + if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "zone '%s': 'file' not specified", - corigin); + zname); result = ISC_R_FAILURE; goto cleanup; } if (dns_name_equal(origin, dns_rootname)) { - result = configure_hints(view, czone->u.hzone.file); + result = configure_hints(view, + cfg_obj_asstring(fileobj)); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "ignoring non-root hint zone '%s'", - corigin); + zname); result = ISC_R_SUCCESS; } goto cleanup; @@ -1158,12 +1270,17 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, * "forward zones" aren't zones either. Translate this syntax into * the appropriate selective forwarding configuration and return. */ - if (czone->ztype == dns_c_zone_forward) { - result = configure_forward(cctx, czone, cview, view, origin, - czone->u.fzone.forwarders); + if (strcasecmp(ztypestr, "forward") == 0) { + forwarders = NULL; + + cfg_map_get(zoptions, "forwarders", &forwarders); + result = configure_forward(config, zconfig, vconfig, + view, origin, forwarders); goto cleanup; } + ztype = ns_config_getzonetype(typeobj); + /* * Check for duplicates in the new zone table. */ @@ -1197,7 +1314,7 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) goto cleanup; if (zone != NULL) { - if (! ns_zone_reusable(zone, czone)) + if (! ns_zone_reusable(zone, zconfig)) dns_zone_detach(&zone); } @@ -1212,7 +1329,7 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, * We cannot reuse an existing zone, we have * to create a new one. */ - CHECK(dns_zone_create(&zone, lctx->mctx)); + CHECK(dns_zone_create(&zone, mctx)); CHECK(dns_zone_setorigin(zone, origin)); dns_zone_setview(zone, view); CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); @@ -1222,15 +1339,15 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, * If the zone contains 'forward' or 'forwarders' statements, * configure selective forwarding. */ - if (dns_c_zone_getforwarders(czone, &forwarders) == ISC_R_SUCCESS || - dns_c_zone_getforward(czone, &tfwd) == ISC_R_SUCCESS) - CHECK(configure_forward(cctx, czone, cview, view, - origin, forwarders)); + forwarders = NULL; + if (cfg_map_get(zoptions, "forward", &forwarders) == ISC_R_SUCCESS) + CHECK(configure_forward(config, zconfig, vconfig, + view, origin, forwarders)); /* * Configure the zone. */ - CHECK(ns_zone_configure(cctx, cview, czone, lctx->aclconf, zone)); + CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone)); /* * Add the zone to its view in the new view list. @@ -1242,8 +1359,6 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, dns_zone_detach(&zone); if (pview != NULL) dns_view_detach(&pview); - if (view != NULL) - dns_view_detach(&view); return (result); } @@ -1252,46 +1367,44 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, * Configure a single server quota. */ static void -configure_server_quota(dns_c_ctx_t *cctx, - isc_result_t (*getquota)(dns_c_ctx_t *, isc_uint32_t *), - isc_quota_t *quota, int defaultvalue) +configure_server_quota(cfg_obj_t **maps, const char *name, isc_quota_t *quota) { - isc_uint32_t val = defaultvalue; - (void)(*getquota)(cctx, &val); - quota->max = val; + cfg_obj_t *obj = NULL; + isc_result_t result; + + result = ns_config_get(maps, name, &obj); + INSIST(result == ISC_R_SUCCESS); + quota->max = cfg_obj_asuint32(obj); } /* - * This function is called as soon as the 'options' statement has been - * parsed. + * This function is called as soon as the 'directory' statement has been + * parsed. This can be extended to support other options if necessary. */ static isc_result_t -options_callback(dns_c_ctx_t *cctx, void *uap) { +directory_callback(const char *clausename, cfg_obj_t *obj, void *arg) { isc_result_t result; + char *directory; - UNUSED(uap); + REQUIRE(strcasecmp("directory", clausename) == 0); + + UNUSED(arg); /* * Change directory. */ - if (cctx->options != NULL && - cctx->options->directory != NULL) { - result = isc_dir_chdir(cctx->options->directory); - if (result != ISC_R_SUCCESS) { - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_SERVER, - ISC_LOG_ERROR, "change directory " - "to '%s' failed: %s", - cctx->options->directory, - isc_result_totext(result)); - return (result); - } + directory = cfg_obj_asstring(obj); + result = isc_dir_chdir(directory); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, + "change directory to '%s' failed: %s", + directory, isc_result_totext(result)); + return (result); } return (ISC_R_SUCCESS); } - static void scan_interfaces(ns_server_t *server, isc_boolean_t verbose) { ns_interfacemgr_scan(server->interfacemgr, verbose); @@ -1368,38 +1481,47 @@ setdumpfile(ns_server_t *server, const char *name) { return (ISC_R_SUCCESS); } -#define SETLIMIT(cfgvar, resource, description) \ - if (dns_c_ctx_get ## cfgvar(cctx, &resource) == ISC_R_SUCCESS) { \ - if (resource == DNS_C_SIZE_SPEC_DEFAULT) \ - value = ns_g_init ## resource; \ - else if (resource == DNS_C_SIZE_SPEC_UNLIM) \ - value = ISC_RESOURCE_UNLIMITED; \ - else \ - value = resource; \ - result = isc_resource_setlimit(isc_resource_ ## resource, \ - value); \ - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, \ - NS_LOGMODULE_SERVER, \ - result == ISC_R_SUCCESS ? \ - ISC_LOG_DEBUG(1) : ISC_LOG_WARNING, \ - "set maximum " description " to %" \ - ISC_PRINT_QUADFORMAT "d: %s", value, \ - isc_result_totext(result)); \ - } - static void -set_limits(dns_c_ctx_t *cctx) { - isc_uint32_t stacksize; - isc_uint32_t datasize; - isc_uint32_t coresize; - isc_uint32_t openfiles; +set_limit(cfg_obj_t **maps, const char *configname, const char *description, + isc_resource_t resourceid, isc_resourcevalue_t defaultvalue) +{ + cfg_obj_t *obj = NULL; + char *resource; isc_resourcevalue_t value; isc_result_t result; - SETLIMIT(stacksize, stacksize, "stack size"); - SETLIMIT(datasize, datasize, "data size"); - SETLIMIT(coresize, coresize, "core size"); - SETLIMIT(files, openfiles, "open files"); + if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS) + return; + + if (cfg_obj_isstring(obj)) { + resource = cfg_obj_asstring(obj); + if (strcasecmp(resource, "default") == 0) + value = defaultvalue; + else if (strcasecmp(resource, "unlimited") == 0) + value = ISC_RESOURCE_UNLIMITED; + else + INSIST(0); + } else + value = cfg_obj_asuint64(obj); + + result = isc_resource_setlimit(resourceid, value); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + result == ISC_R_SUCCESS ? + ISC_LOG_DEBUG(1) : ISC_LOG_WARNING, + "set maximum %s to %" ISC_PRINT_QUADFORMAT "d: %s", + description, value, isc_result_totext(result)); +} + +#define SETLIMIT(cfgvar, resource, description) \ + set_limit(maps, cfgvar, description, isc_resource_ ## resource, \ + ns_g_init ## resource) + +static void +set_limits(cfg_obj_t **maps) { + SETLIMIT("stacksize", stacksize, "stack size"); + SETLIMIT("datasize", datasize, "data size"); + SETLIMIT("coresize", coresize, "core size"); + SETLIMIT("files", openfiles, "open files"); } static isc_result_t @@ -1407,88 +1529,111 @@ load_configuration(const char *filename, ns_server_t *server, isc_boolean_t first_time) { isc_result_t result; - ns_load_t lctx; - dns_c_cbks_t callbacks; - dns_c_ctx_t *cctx; + cfg_parser_t *parser = NULL; + cfg_obj_t *config; + cfg_obj_t *options; + cfg_obj_t *views; + cfg_obj_t *obj; + cfg_obj_t *maps[3]; + cfg_listelt_t *element; dns_view_t *view = NULL; dns_view_t *view_next; + dns_viewlist_t viewlist; dns_viewlist_t tmpviewlist; ns_aclconfctx_t aclconfctx; dns_dispatch_t *dispatchv4 = NULL; dns_dispatch_t *dispatchv6 = NULL; - char *pidfilename; - char *statsfilename; - char *dumpfilename; - char *randomdev; isc_uint32_t interface_interval; isc_uint32_t heartbeat_interval; in_port_t listen_port; -#ifdef PATH_RANDOMDEV - char path_randomdev[] = PATH_RANDOMDEV; -#endif + int i; ns_aclconfctx_init(&aclconfctx); + ISC_LIST_INIT(viewlist); /* Ensure exclusive access to configuration data. */ result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); - lctx.mctx = ns_g_mctx; - lctx.aclconf = &aclconfctx; - ISC_LIST_INIT(lctx.viewlist); - - callbacks.zonecbk = configure_zone; - callbacks.zonecbkuap = &lctx; - callbacks.optscbk = options_callback; - callbacks.optscbkuap = NULL; + /* + * Parse the global default pseudo-config file. + */ + if (first_time) { + CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config)); + RUNTIME_CHECK(cfg_map_get(ns_g_config, "options", + &ns_g_defaults) == + ISC_R_SUCCESS); + } /* - * Parse the configuration file creating a parse tree. Any - * 'zone' statements are handled immediately by calling - * configure_zone() through 'callbacks'. + * Parse the configuration file using the new config code. */ - cctx = NULL; - if (ns_g_lwresdonly && lwresd_g_useresolvconf) - result = ISC_R_FILENOTFOUND; - else { + CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); + cfg_parser_setcallback(parser, directory_callback, NULL); + + result = ISC_R_FAILURE; + config = NULL; + + /* + * Unless this is lwresd with the -C option, parse the config file. + */ + if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading configuration from '%s'", filename); - - result = dns_c_parse_namedconf(filename, ns_g_mctx, &cctx, - &callbacks); + result = cfg_parse_file(parser, filename, &cfg_type_namedconf, + &config); } - if (result == ISC_R_FILENOTFOUND && - ns_g_lwresdonly && !ns_g_conffileset) + + /* + * If this is lwresd with the -C option, or lwresd with no -C or -c + * option where the above parsing failed, parse resolv.conf. + */ + if (ns_g_lwresdonly && + (lwresd_g_useresolvconf || + (!ns_g_conffileset && result != ISC_R_FILENOTFOUND))) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading configuration from '%s'", lwresd_g_resolvconffile); - - result = ns_lwresd_parseresolvconf(ns_g_mctx, &cctx); + result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser, + &config); } CHECK(result); + /* + * Check the validity of the configuration. + */ + CHECK(cfg_check_namedconf(config, ns_g_lctx)); + + /* + * Fill in the maps array, used for resolving defaults. + */ + i = 0; + options = NULL; + result = cfg_map_get(config, "options", &options); + if (result == ISC_R_SUCCESS) + maps[i++] = options; + maps[i++] = ns_g_defaults; + maps[i++] = NULL; + /* * Set process limits, which (usually) needs to be done as root. */ - set_limits(cctx); + set_limits(maps); /* * Configure various server options. */ - configure_server_quota(cctx, dns_c_ctx_gettransfersout, - &server->xfroutquota, 10); - configure_server_quota(cctx, dns_c_ctx_gettcpclients, - &server->tcpquota, 100); - configure_server_quota(cctx, dns_c_ctx_getrecursiveclients, - &server->recursionquota, 1000); + configure_server_quota(maps, "transfers-out", &server->xfroutquota); + configure_server_quota(maps, "tcp-clients", &server->tcpquota); + configure_server_quota(maps, "recursive-clients", + &server->recursionquota); - CHECK(configure_view_acl(NULL, cctx, &aclconfctx, ns_g_mctx, NULL, - dns_c_ctx_getblackhole, - &server->blackholeacl)); + CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx, + ns_g_mctx, &server->blackholeacl)); if (server->blackholeacl != NULL) dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, server->blackholeacl); @@ -1496,39 +1641,34 @@ load_configuration(const char *filename, ns_server_t *server, /* * Configure the zone manager. */ - { - isc_uint32_t transfersin = 10; - (void)dns_c_ctx_gettransfersin(cctx, &transfersin); - dns_zonemgr_settransfersin(server->zonemgr, transfersin); - } - { - isc_uint32_t transfersperns = 2; - (void)dns_c_ctx_gettransfersperns(cctx, &transfersperns); - dns_zonemgr_settransfersperns(server->zonemgr, transfersperns); - } + obj = NULL; + result = ns_config_get(maps, "transfers-in", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); + + obj = NULL; + result = ns_config_get(maps, "transfers-per-ns", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); /* * Determine which port to use for listening for incoming connections. */ - if (ns_g_port != 0) { - listen_port = ns_g_port; - } else { - result = dns_c_ctx_getport(cctx, &listen_port); - if (result != ISC_R_SUCCESS) - listen_port = 53; - } + CHECKM(ns_config_getport(config, &listen_port), "port"); + /* * Configure the interface manager according to the "listen-on" * statement. */ { - dns_c_lstnlist_t *clistenon = NULL; + cfg_obj_t *clistenon = NULL; ns_listenlist_t *listenon = NULL; - (void)dns_c_ctx_getlistenlist(cctx, &clistenon); + clistenon = NULL; + (void)cfg_map_get(options, "listen-on", &clistenon); if (clistenon != NULL) { result = ns_listenlist_fromconfig(clistenon, - cctx, + config, &aclconfctx, ns_g_mctx, &listenon); @@ -1549,13 +1689,13 @@ load_configuration(const char *filename, ns_server_t *server, * Ditto for IPv6. */ { - dns_c_lstnlist_t *clistenon = NULL; + cfg_obj_t *clistenon = NULL; ns_listenlist_t *listenon = NULL; - (void)dns_c_ctx_getv6listenlist(cctx, &clistenon); + (void)cfg_map_get(options, "listen-on", &clistenon); if (clistenon != NULL) { result = ns_listenlist_fromconfig(clistenon, - cctx, + config, &aclconfctx, ns_g_mctx, &listenon); @@ -1585,8 +1725,10 @@ load_configuration(const char *filename, ns_server_t *server, * Arrange for further interface scanning to occur periodically * as specified by the "interface-interval" option. */ - interface_interval = 3600; /* Default is 1 hour. */ - (void)dns_c_ctx_getinterfaceinterval(cctx, &interface_interval); + obj = NULL; + result = ns_config_get(maps, "interface-interval", &obj); + INSIST(result == ISC_R_SUCCESS); + interface_interval = cfg_obj_asuint32(obj); if (interface_interval == 0) { isc_timer_reset(server->interface_timer, isc_timertype_inactive, @@ -1602,9 +1744,9 @@ load_configuration(const char *filename, ns_server_t *server, /* * Configure the dialup heartbeat timer. */ - heartbeat_interval = 3600; /* Default is 1 hour. */ - (void)dns_c_ctx_getheartbeatinterval(cctx, &heartbeat_interval); - + obj = NULL; + result = ns_config_get(maps, "heartbeat-interval", &obj); + INSIST(result == ISC_R_SUCCESS); if (heartbeat_interval == 0) { isc_timer_reset(server->heartbeat_timer, isc_timertype_inactive, @@ -1622,65 +1764,49 @@ load_configuration(const char *filename, ns_server_t *server, * views that have zones were already created at parsing * time, but views with no zones must be created here. */ - if (cctx->views != NULL) { - dns_c_view_t *cview; - for (cview = ISC_LIST_HEAD(cctx->views->views); - cview != NULL; - cview = ISC_LIST_NEXT(cview, next)) - { - view = NULL; - CHECK(find_or_create_view(cview, - &lctx.viewlist, &view)); - INSIST(view != NULL); - CHECK(configure_view(view, cctx, cview, ns_g_mctx, - &aclconfctx)); - dns_view_freeze(view); - dns_view_detach(&view); - } + views = NULL; + (void)cfg_map_get(config, "view", &views); + for (element = cfg_list_first(views); + element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *vconfig; + + view = NULL; + vconfig = cfg_listelt_value(element); + CHECK(create_view(vconfig, &viewlist, &view)); + INSIST(view != NULL); + CHECK(configure_view(view, config, vconfig, + ns_g_mctx, &aclconfctx)); + dns_view_freeze(view); + dns_view_detach(&view); } - INSIST(view == NULL); /* * Make sure we have a default view if and only if there * were no explicit views. */ - if (cctx->views == NULL || ISC_LIST_EMPTY(cctx->views->views)) { + if (views == NULL) { /* * No explicit views; there ought to be a default view. * There may already be one created as a side effect * of zone statements, or we may have to create one. * In either case, we need to configure and freeze it. */ - CHECK(find_or_create_view(NULL, &lctx.viewlist, &view)); - CHECK(configure_view(view, cctx, NULL, - ns_g_mctx, &aclconfctx)); + CHECK(create_view(NULL, &viewlist, &view)); + CHECK(configure_view(view, config, NULL, ns_g_mctx, + &aclconfctx)); dns_view_freeze(view); dns_view_detach(&view); - } else { - /* - * There are explicit views. There should not be - * a default view. If there is one, complain. - */ - result = dns_viewlist_find(&lctx.viewlist, "_default", - dns_rdataclass_in, &view); - if (result == ISC_R_SUCCESS) { - dns_view_detach(&view); - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_SERVER, ISC_LOG_ERROR, - "when using 'view' statements, " - "all zones must be in views"); - result = ISC_R_FAILURE; - goto cleanup; - } } /* * Create (or recreate) the internal _bind view. */ CHECK(create_bind_view(&view)); - ISC_LIST_APPEND(lctx.viewlist, view, link); - CHECK(create_version_zone(cctx, server->zonemgr, view)); - CHECK(create_authors_zone(cctx, server->zonemgr, view)); + ISC_LIST_APPEND(viewlist, view, link); + CHECK(create_version_zone(maps, server->zonemgr, view)); + CHECK(create_authors_zone(options, server->zonemgr, view)); dns_view_freeze(view); view = NULL; @@ -1688,16 +1814,16 @@ load_configuration(const char *filename, ns_server_t *server, * Swap our new view list with the production one. */ tmpviewlist = server->viewlist; - server->viewlist = lctx.viewlist; - lctx.viewlist = tmpviewlist; + server->viewlist = viewlist; + viewlist = tmpviewlist; /* * Load the TKEY information from the configuration. */ { dns_tkeyctx_t *t = NULL; - CHECKM(ns_tkeyctx_fromconfig(cctx, ns_g_mctx, ns_g_entropy, - &t), + CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy, + &t), "configuring TKEY"); if (server->tkeyctx != NULL) dns_tkeyctx_destroy(&server->tkeyctx); @@ -1707,30 +1833,27 @@ load_configuration(const char *filename, ns_server_t *server, /* * Bind the OMAPI port(s). */ - CHECKM(ns_omapi_configure(ns_g_mctx, cctx, &aclconfctx), + CHECKM(ns_omapi_configure(ns_g_mctx, config, &aclconfctx), "binding control channel(s)"); /* * Bind the lwresd port(s). */ - CHECKM(ns_lwresd_configure(ns_g_mctx, cctx), + CHECKM(ns_lwresd_configure(ns_g_mctx, config), "binding lightweight resolver ports"); /* * Open the source of entropy. */ if (first_time) { - randomdev = NULL; - (void)dns_c_ctx_getrandomdevice(cctx, &randomdev); -#ifdef PATH_RANDOMDEV - if (randomdev == NULL) - randomdev = path_randomdev; -#endif - if (randomdev == NULL) + obj = NULL; + result = ns_config_get(maps, "random-device", &obj); + if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "no source of entropy found"); - else { + } else { + const char *randomdev = cfg_obj_asstring(obj); result = isc_entropy_createfilesource(ns_g_entropy, randomdev); if (result != ISC_R_SUCCESS) @@ -1764,15 +1887,16 @@ load_configuration(const char *filename, ns_server_t *server, "ignoring config file logging " "statement due to -g option"); } else { - dns_c_logginglist_t *clog = NULL; + cfg_obj_t *logobj = NULL; isc_logconfig_t *logc = NULL; CHECKM(isc_logconfig_create(ns_g_lctx, &logc), "creating new logging configuration"); - (void)dns_c_ctx_getlogging(cctx, &clog); - if (clog != NULL) { - CHECKM(ns_log_configure(logc, clog), + logobj = NULL; + (void)cfg_map_get(config, "logging", &logobj); + if (logobj != NULL) { + CHECKM(ns_log_configure(logc, logobj), "configuring logging"); } else { CHECKM(ns_log_setdefaultchannels(logc), @@ -1800,43 +1924,55 @@ load_configuration(const char *filename, ns_server_t *server, * compatibility. */ if (first_time) { - dns_c_logginglist_t *clog = NULL; - dns_c_logcat_t *ccat; - (void)dns_c_ctx_getlogging(cctx, &clog); - for (ccat = ISC_LIST_HEAD(clog->categories); - ccat != NULL; - ccat = ISC_LIST_NEXT(ccat, next)) { - if (strcmp(ccat->catname, "queries") == 0) - server->log_queries = ISC_TRUE; + cfg_obj_t *logobj = NULL; + cfg_obj_t *categories = NULL; + (void)cfg_map_get(config, "logging", &logobj); + if (logobj != NULL) + (void)cfg_map_get(logobj, "category", &categories); + if (categories != NULL) { + cfg_listelt_t *element; + for (element = cfg_list_first(categories); + element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *catobj; + char *str; + + obj = cfg_listelt_value(element); + catobj = cfg_tuple_get(obj, "name"); + str = cfg_obj_asstring(catobj); + if (strcasecmp(str, "queries") == 0) + server->log_queries = ISC_TRUE; + } } } - if (dns_c_ctx_getpidfilename(cctx, &pidfilename) != ISC_R_NOTFOUND) - ns_os_writepidfile(pidfilename); + obj = NULL; + if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) + ns_os_writepidfile(cfg_obj_asstring(obj)); else if (ns_g_lwresdonly) ns_os_writepidfile(lwresd_g_defaultpidfile); else ns_os_writepidfile(ns_g_defaultpidfile); - result = dns_c_ctx_getstatsfilename(cctx, &statsfilename); - if (result == ISC_R_NOTFOUND) { - CHECKM(setstatsfile(server, "named.stats"), "strdup"); - } else { - CHECKM(setstatsfile(server, statsfilename), "strdup"); - } + obj = NULL; + result = ns_config_get(maps, "statistics-file", &obj); + INSIST(result == ISC_R_SUCCESS); + CHECKM(setstatsfile(server, cfg_obj_asstring(obj)), "strdup"); - result = dns_c_ctx_getdumpfilename(cctx, &dumpfilename); - if (result == ISC_R_NOTFOUND) { - CHECKM(setdumpfile(server, "named_dump.db"), "strdup"); - } else { - CHECKM(setdumpfile(server, dumpfilename), "strdup"); - } + obj = NULL; + result = ns_config_get(maps, "dump-file", &obj); + INSIST(result == ISC_R_SUCCESS); + CHECKM(setdumpfile(server, cfg_obj_asstring(obj)), "strdup"); cleanup: ns_aclconfctx_destroy(&aclconfctx); - if (cctx != NULL) - dns_c_ctx_delete(&cctx); + if (config != NULL) + cfg_obj_destroy(parser, &config); + + if (parser != NULL) + cfg_parser_destroy(&parser); if (view != NULL) dns_view_detach(&view); @@ -1846,11 +1982,11 @@ load_configuration(const char *filename, ns_server_t *server, * or our temporary list depending on whether they * were swapped above or not. */ - for (view = ISC_LIST_HEAD(lctx.viewlist); + for (view = ISC_LIST_HEAD(viewlist); view != NULL; view = view_next) { view_next = ISC_LIST_NEXT(view, link); - ISC_LIST_UNLINK(lctx.viewlist, view, link); + ISC_LIST_UNLINK(viewlist, view, link); dns_view_detach(&view); } @@ -1929,6 +2065,9 @@ run_server(isc_task_t *task, isc_event_t *event) { server, &server->heartbeat_timer), "creating heartbeat timer"); + CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser), + "creating default configuration parser"); + if (ns_g_lwresdonly) CHECKFATAL(load_configuration(lwresd_g_conffile, server, ISC_TRUE), @@ -1969,6 +2108,9 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { ISC_LOG_INFO, "shutting down%s", flush ? ": flushing changes" : ""); + cfg_obj_destroy(ns_g_parser, &ns_g_config); + cfg_parser_destroy(&ns_g_parser); + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = view_next) { @@ -2323,12 +2465,12 @@ ns_server_togglequerylog(ns_server_t *server) { } static isc_result_t -ns_listenlist_fromconfig(dns_c_lstnlist_t *clist, dns_c_ctx_t *cctx, - ns_aclconfctx_t *actx, - isc_mem_t *mctx, ns_listenlist_t **target) +ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config, + ns_aclconfctx_t *actx, + isc_mem_t *mctx, ns_listenlist_t **target) { - dns_c_lstnon_t *ce; isc_result_t result; + cfg_listelt_t *element; ns_listenlist_t *dlist = NULL; REQUIRE(target != NULL && *target == NULL); @@ -2337,12 +2479,14 @@ ns_listenlist_fromconfig(dns_c_lstnlist_t *clist, dns_c_ctx_t *cctx, if (result != ISC_R_SUCCESS) return (result); - for (ce = ISC_LIST_HEAD(clist->elements); - ce != NULL; - ce = ISC_LIST_NEXT(ce, next)) + for (element = cfg_list_first(listenlist); + element != NULL; + element = cfg_list_next(element)) { ns_listenelt_t *delt = NULL; - result = ns_listenelt_fromconfig(ce, cctx, actx, mctx, &delt); + cfg_obj_t *listener = cfg_listelt_value(element); + result = ns_listenelt_fromconfig(listener, config, actx, + mctx, &delt); if (result != ISC_R_SUCCESS) goto cleanup; ISC_LIST_APPEND(dlist->elts, delt, link); @@ -2360,18 +2504,37 @@ ns_listenlist_fromconfig(dns_c_lstnlist_t *clist, dns_c_ctx_t *cctx, * data structure. */ static isc_result_t -ns_listenelt_fromconfig(dns_c_lstnon_t *celt, dns_c_ctx_t *cctx, - ns_aclconfctx_t *actx, - isc_mem_t *mctx, ns_listenelt_t **target) +ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config, + ns_aclconfctx_t *actx, + isc_mem_t *mctx, ns_listenelt_t **target) { isc_result_t result; + cfg_obj_t *portobj; + in_port_t port; ns_listenelt_t *delt = NULL; REQUIRE(target != NULL && *target == NULL); - result = ns_listenelt_create(mctx, celt->port, NULL, &delt); + + portobj = cfg_tuple_get(listener, "port"); + if (!cfg_obj_isuint32(portobj)) { + result = ns_config_getport(config, &port); + if (result != ISC_R_SUCCESS) + return (result); + } else { + if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) { + cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, + "port value '%u' is out of range", + cfg_obj_asuint32(portobj)); + return (ISC_R_RANGE); + } + port = (in_port_t)cfg_obj_asuint32(portobj); + } + + result = ns_listenelt_create(mctx, port, NULL, &delt); if (result != ISC_R_SUCCESS) return (result); - result = ns_acl_fromconfig(celt->iml, cctx, actx, mctx, &delt->acl); + result = ns_acl_fromconfig(cfg_tuple_get(listener, "acl"), + config, actx, mctx, &delt->acl); if (result != ISC_R_SUCCESS) { ns_listenelt_destroy(delt); return (result); diff --git a/bin/named/tkeyconf.c b/bin/named/tkeyconf.c index d4be4f5c57..71b2017fbc 100644 --- a/bin/named/tkeyconf.c +++ b/bin/named/tkeyconf.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tkeyconf.c,v 1.17 2001/01/09 21:40:05 bwelling Exp $ */ +/* $Id: tkeyconf.c,v 1.18 2001/03/04 21:21:27 bwelling Exp $ */ #include @@ -23,6 +23,8 @@ #include /* Required for HP/UX (and others?) */ #include +#include + #include #include #include @@ -40,7 +42,7 @@ isc_result_t -ns_tkeyctx_fromconfig(dns_c_ctx_t *cfg, isc_mem_t *mctx, isc_entropy_t *ectx, +ns_tkeyctx_fromconfig(cfg_obj_t *options, isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp) { isc_result_t result; @@ -50,14 +52,17 @@ ns_tkeyctx_fromconfig(dns_c_ctx_t *cfg, isc_mem_t *mctx, isc_entropy_t *ectx, dns_fixedname_t fname; dns_name_t *name; isc_buffer_t b; + cfg_obj_t *obj; result = dns_tkeyctx_create(mctx, ectx, &tctx); if (result != ISC_R_SUCCESS) return (result); - s = NULL; - result = dns_c_ctx_gettkeydhkey(cfg, &s, &n); + obj = NULL; + result = cfg_map_get(options, "tkey-dhkey", &obj); if (result == ISC_R_SUCCESS) { + s = cfg_obj_asstring(cfg_tuple_get(obj, "name")); + n = cfg_obj_asuint32(cfg_tuple_get(obj, "keyid")); isc_buffer_init(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); @@ -67,12 +72,12 @@ ns_tkeyctx_fromconfig(dns_c_ctx_t *cfg, isc_mem_t *mctx, isc_entropy_t *ectx, RETERR(dst_key_fromfile(name, n, DNS_KEYALG_DH, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, NULL, mctx, &tctx->dhkey)); - } else if (result != ISC_R_NOTFOUND) - goto failure; + } - s = NULL; - result = dns_c_ctx_gettkeydomain(cfg, &s); + obj = NULL; + result = cfg_map_get(options, "tkey-domain", &obj); if (result == ISC_R_SUCCESS) { + s = cfg_obj_asstring(obj); isc_buffer_init(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); @@ -86,11 +91,12 @@ ns_tkeyctx_fromconfig(dns_c_ctx_t *cfg, isc_mem_t *mctx, isc_entropy_t *ectx, } dns_name_init(tctx->domain, NULL); RETERR(dns_name_dup(name, mctx, tctx->domain)); - } else if (result != ISC_R_NOTFOUND) - goto failure; + } - result = dns_c_ctx_gettkeygsscred(cfg, &s); + obj = NULL; + result = cfg_map_get(options, "tkey-gssapi-credential", &obj); if (result == ISC_R_SUCCESS) { + s = cfg_obj_asstring(obj); isc_buffer_init(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); @@ -99,8 +105,7 @@ ns_tkeyctx_fromconfig(dns_c_ctx_t *cfg, isc_mem_t *mctx, isc_entropy_t *ectx, NULL)); RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, &tctx->gsscred)); - } else if (result != ISC_R_NOTFOUND) - goto failure; + } *tctxp = tctx; return (ISC_R_SUCCESS); diff --git a/bin/named/tsigconf.c b/bin/named/tsigconf.c index ec85d580b5..884df841ec 100644 --- a/bin/named/tsigconf.c +++ b/bin/named/tsigconf.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tsigconf.c,v 1.15 2001/01/09 21:40:06 bwelling Exp $ */ +/* $Id: tsigconf.c,v 1.16 2001/03/04 21:21:28 bwelling Exp $ */ #include @@ -24,38 +24,54 @@ #include #include +#include + #include +#include #include #include static isc_result_t -add_initial_keys(dns_c_kdeflist_t *list, dns_tsig_keyring_t *ring, - isc_mem_t *mctx) -{ - dns_c_kdef_t *key; +add_initial_keys(cfg_obj_t *list, dns_tsig_keyring_t *ring, isc_mem_t *mctx) { + cfg_listelt_t *element; + cfg_obj_t *key = NULL; + char *keyid = NULL; unsigned char *secret = NULL; int secretalloc = 0; int secretlen = 0; isc_result_t ret; isc_stdtime_t now; - key = ISC_LIST_HEAD(list->keydefs); - while (key != NULL) { + for (element = cfg_list_first(list); + element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *algobj = NULL; + cfg_obj_t *secretobj = NULL; dns_name_t keyname; - dns_name_t *alg, tempalg; - char keynamedata[1024], algdata[1024]; - isc_buffer_t keynamesrc, keynamebuf, algsrc, algbuf; + dns_name_t *alg; + char keynamedata[1024]; + isc_buffer_t keynamesrc, keynamebuf; + char *secretstr; isc_buffer_t secretbuf; - dns_name_init(&keyname, NULL); + key = cfg_listelt_value(element); + keyid = cfg_obj_asstring(cfg_map_getname(key)); + + algobj = NULL; + secretobj = NULL; + (void)cfg_map_get(key, "algorithm", &algobj); + (void)cfg_map_get(key, "secret", &secretobj); + INSIST(algobj != NULL && secretobj != NULL); /* * Create the key name. */ - isc_buffer_init(&keynamesrc, key->keyid, strlen(key->keyid)); - isc_buffer_add(&keynamesrc, strlen(key->keyid)); + dns_name_init(&keyname, NULL); + isc_buffer_init(&keynamesrc, keyid, strlen(keyid)); + isc_buffer_add(&keynamesrc, strlen(keyid)); isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata)); ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname, ISC_TRUE, &keynamebuf); @@ -65,30 +81,25 @@ add_initial_keys(dns_c_kdeflist_t *list, dns_tsig_keyring_t *ring, /* * Create the algorithm. */ - if (strcasecmp(key->algorithm, "hmac-md5") == 0) + if (strcasecmp(cfg_obj_asstring(algobj), "hmac-md5") == 0) alg = dns_tsig_hmacmd5_name; else { - dns_name_init(&tempalg, NULL); - isc_buffer_init(&algsrc, key->algorithm, - strlen(key->algorithm)); - isc_buffer_add(&algsrc, strlen(key->algorithm)); - isc_buffer_init(&algbuf, algdata, sizeof(algdata)); - ret = dns_name_fromtext(&tempalg, &algsrc, - dns_rootname, - ISC_TRUE, &algbuf); - if (ret != ISC_R_SUCCESS) - goto failure; - alg = &tempalg; + cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR, + "key '%s': the only supported algorithm " + "is hmac-md5", keyid); + ret = DNS_R_BADALG; + goto failure; } - secretalloc = secretlen = strlen(key->secret) * 3 / 4; + secretstr = cfg_obj_asstring(secretobj); + secretalloc = secretlen = strlen(secretstr) * 3 / 4; secret = isc_mem_get(mctx, secretlen); if (secret == NULL) { ret = ISC_R_NOMEMORY; goto failure; } isc_buffer_init(&secretbuf, secret, secretlen); - ret = isc_base64_decodestring(mctx, key->secret, &secretbuf); + ret = isc_base64_decodestring(mctx, secretstr, &secretbuf); if (ret != ISC_R_SUCCESS) goto failure; secretlen = isc_buffer_usedlength(&secretbuf); @@ -101,21 +112,15 @@ add_initial_keys(dns_c_kdeflist_t *list, dns_tsig_keyring_t *ring, secret = NULL; if (ret != ISC_R_SUCCESS) goto failure; - - key = ISC_LIST_NEXT(key, next); - continue; - - failure: - isc_log_write(ns_g_lctx, - NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, - ISC_LOG_ERROR, "configuring TSIG key '%s': %s", - key->keyid, isc_result_totext(ret)); - ret = ISC_R_FAILURE; - goto cleanup; } + return (ISC_R_SUCCESS); - cleanup: + failure: + cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, + "configuring TSIG key '%s': %s", keyid, + isc_result_totext(ret)); + if (secret != NULL) isc_mem_put(mctx, secret, secretalloc); return (ret); @@ -123,33 +128,34 @@ add_initial_keys(dns_c_kdeflist_t *list, dns_tsig_keyring_t *ring, } isc_result_t -ns_tsigkeyring_fromconfig(dns_c_view_t *confview, dns_c_ctx_t *confctx, - isc_mem_t *mctx, dns_tsig_keyring_t **ringp) +ns_tsigkeyring_fromconfig(cfg_obj_t *config, cfg_obj_t *vconfig, + isc_mem_t *mctx, dns_tsig_keyring_t **ringp) { - dns_c_kdeflist_t *keylist; + cfg_obj_t *maps[3]; + cfg_obj_t *keylist; dns_tsig_keyring_t *ring = NULL; isc_result_t result; + int i; + + i = 0; + if (config != NULL) + maps[i++] = config; + if (vconfig != NULL) + maps[i++] = cfg_tuple_get(vconfig, "options"); + maps[i] = NULL; result = dns_tsigkeyring_create(mctx, &ring); if (result != ISC_R_SUCCESS) return (result); - keylist = NULL; - result = dns_c_ctx_getkdeflist(confctx, &keylist); - if (result == ISC_R_SUCCESS) - result = add_initial_keys(keylist, ring, mctx); - else if (result == ISC_R_NOTFOUND) - result = ISC_R_SUCCESS; - if (result != ISC_R_SUCCESS) - goto failure; - - if (confview != NULL) { + for (i = 0; ; i++) { + if (maps[i] == NULL) + break; keylist = NULL; - result = dns_c_view_getkeydefs(confview, &keylist); - if (result == ISC_R_SUCCESS) - result = add_initial_keys(keylist, ring, mctx); - else if (result == ISC_R_NOTFOUND) - result = ISC_R_SUCCESS; + result = cfg_map_get(maps[i], "key", &keylist); + if (result != ISC_R_SUCCESS) + continue; + result = add_initial_keys(keylist, ring, mctx); if (result != ISC_R_SUCCESS) goto failure; } diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 67f87492ce..706f6cbe9e 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -15,19 +15,24 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.c,v 1.82 2001/02/24 00:58:52 bwelling Exp $ */ +/* $Id: zoneconf.c,v 1.83 2001/03/04 21:21:30 bwelling Exp $ */ #include +#include #include #include /* Required for HP/UX (and others?) */ #include #include +#include #include +#include +#include #include #include +#include #include #include #include @@ -36,10 +41,6 @@ * These are BIND9 server defaults, not necessarily identical to the * library defaults defined in zone.c. */ -#define MAX_XFER_TIME (2*3600) /* Documented default is 2 hours. */ -#define DNS_DEFAULT_IDLEIN 3600 /* 1 hour */ -#define DNS_DEFAULT_IDLEOUT 3600 /* 1 hour */ - #define RETERR(x) do { \ isc_result_t _r = (x); \ if (_r != ISC_R_SUCCESS) \ @@ -50,64 +51,195 @@ * Convenience function for configuring a single zone ACL. */ static isc_result_t -configure_zone_acl(dns_c_zone_t *czone, dns_c_ctx_t *cctx, dns_c_view_t *cview, - ns_aclconfctx_t *aclconfctx, dns_zone_t *zone, - isc_result_t (*getcacl)(dns_c_zone_t *, - dns_c_ipmatchlist_t **), - isc_result_t (*getviewcacl)(dns_c_view_t * - , dns_c_ipmatchlist_t **), - isc_result_t (*getglobalcacl)(dns_c_ctx_t *, - dns_c_ipmatchlist_t **), +configure_zone_acl(cfg_obj_t *zconfig, cfg_obj_t *vconfig, cfg_obj_t *config, + const char *aclname, ns_aclconfctx_t *actx, + dns_zone_t *zone, void (*setzacl)(dns_zone_t *, dns_acl_t *), void (*clearzacl)(dns_zone_t *)) { isc_result_t result; - dns_c_ipmatchlist_t *cacl; + cfg_obj_t *maps[4]; + cfg_obj_t *aclobj = NULL; + int i = 0; dns_acl_t *dacl = NULL; - result = (*getcacl)(czone, &cacl); - if (result == ISC_R_NOTFOUND && getviewcacl != NULL && cview != NULL) { - result = (*getviewcacl)(cview, &cacl); + + if (zconfig != NULL) + maps[i++] = cfg_tuple_get(zconfig, "options"); + if (vconfig != NULL) + maps[i++] = cfg_tuple_get(vconfig, "options"); + if (config != NULL) { + cfg_obj_t *options = NULL; + (void)cfg_map_get(config, "options", &options); + if (options != NULL) + maps[i++] = options; } - if (result == ISC_R_NOTFOUND && getglobalcacl != NULL) { - result = (*getglobalcacl)(cctx, &cacl); - } - if (result == ISC_R_SUCCESS) { - result = ns_acl_fromconfig(cacl, cctx, aclconfctx, - dns_zone_getmctx(zone), &dacl); - dns_c_ipmatchlist_detach(&cacl); - if (result != ISC_R_SUCCESS) - return (result); - (*setzacl)(zone, dacl); - dns_acl_detach(&dacl); - return (ISC_R_SUCCESS); - } else if (result == ISC_R_NOTFOUND) { + maps[i] = NULL; + + result = ns_config_get(maps, aclname, &aclobj); + if (aclobj == NULL) { (*clearzacl)(zone); return (ISC_R_SUCCESS); - } else { - return (result); } + + result = ns_acl_fromconfig(aclobj, config, actx, + dns_zone_getmctx(zone), &dacl); + if (result != ISC_R_SUCCESS) + return (result); + (*setzacl)(zone, dacl); + dns_acl_detach(&dacl); + return (ISC_R_SUCCESS); } /* - * Conver a config file zone type into a server zone type. + * Parse the zone update-policy statement. */ -static dns_zonetype_t -zonetype_fromconf(dns_c_zonetype_t cztype) { - switch (cztype) { - case dns_c_zone_master: - return dns_zone_master; - case dns_c_zone_slave: - return dns_zone_slave; - case dns_c_zone_stub: - return dns_zone_stub; - default: - /* - * Hint and forward zones are not really zones; - * they should never get this far. - */ - INSIST(0); - return (dns_zone_none); /*NOTREACHED*/ +static isc_result_t +configure_zone_ssutable(cfg_obj_t *zconfig, dns_zone_t *zone) { + cfg_obj_t *updatepolicy = NULL; + cfg_listelt_t *element, *element2; + dns_ssutable_t *table = NULL; + isc_mem_t *mctx = dns_zone_getmctx(zone); + isc_result_t result; + + (void)cfg_map_get(zconfig, "update-policy", &updatepolicy); + if (updatepolicy == NULL) + return (ISC_R_SUCCESS); + + result = dns_ssutable_create(mctx, &table); + if (result != ISC_R_SUCCESS) + return (result); + + for (element = cfg_list_first(updatepolicy); + element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *stmt = cfg_listelt_value(element); + cfg_obj_t *mode = cfg_tuple_get(stmt, "mode"); + cfg_obj_t *identity = cfg_tuple_get(stmt, "identity"); + cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype"); + cfg_obj_t *dname = cfg_tuple_get(stmt, "name"); + cfg_obj_t *typelist = cfg_tuple_get(stmt, "types"); + char *str; + isc_boolean_t grant; + unsigned int mtype; + dns_fixedname_t fname, fident; + isc_buffer_t b; + dns_rdatatype_t *types; + unsigned int i, n; + + str = cfg_obj_asstring(mode); + if (strcasecmp(str, "grant") == 0) + grant = ISC_TRUE; + else if (strcasecmp(str, "deny") == 0) + grant = ISC_FALSE; + else + INSIST(0); + + str = cfg_obj_asstring(matchtype); + if (strcasecmp(str, "name") == 0) + mtype = DNS_SSUMATCHTYPE_NAME; + else if (strcasecmp(str, "subdomain") == 0) + mtype = DNS_SSUMATCHTYPE_SUBDOMAIN; + else if (strcasecmp(str, "wildcard") == 0) + mtype = DNS_SSUMATCHTYPE_WILDCARD; + else if (strcasecmp(str, "self") == 0) + mtype = DNS_SSUMATCHTYPE_SELF; + else + INSIST(0); + + dns_fixedname_init(&fident); + str = cfg_obj_asstring(identity); + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + result = dns_name_fromtext(dns_fixedname_name(&fident), &b, + dns_rootname, ISC_FALSE, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, + "'%s' is not a valid name", str); + goto cleanup; + } + + dns_fixedname_init(&fname); + str = cfg_obj_asstring(dname); + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + result = dns_name_fromtext(dns_fixedname_name(&fname), &b, + dns_rootname, ISC_FALSE, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, + "'%s' is not a valid name", str); + goto cleanup; + } + + n = ns_config_listcount(typelist); + if (n == 0) + types = NULL; + else { + types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t)); + if (types == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + } + + i = 0; + for (element2 = cfg_list_first(typelist); + element2 != NULL; + element2 = cfg_list_next(element2)) + { + cfg_obj_t *typeobj; + isc_textregion_t r; + + INSIST(i < n); + + typeobj = cfg_listelt_value(element2); + str = cfg_obj_asstring(typeobj); + r.base = str; + r.length = strlen(str); + + result = dns_rdatatype_fromtext(&types[i++], &r); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, + "'%s' is not a valid type", str); + isc_mem_put(mctx, types, + n * sizeof(dns_rdatatype_t)); + goto cleanup; + } + } + INSIST(i == n); + + result = dns_ssutable_addrule(table, grant, + dns_fixedname_name(&fident), + mtype, + dns_fixedname_name(&fname), + n, types); + if (types != NULL) + isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t)); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } + + result = ISC_R_SUCCESS; + dns_zone_setssutable(zone, table); + + cleanup: + dns_ssutable_detach(&table); + return (result); +} + +/* + * Convert a config file zone type into a server zone type. + */ +static inline dns_zonetype_t +zonetype_fromconfig(cfg_obj_t *map) { + cfg_obj_t *obj = NULL; + isc_result_t result; + + result = cfg_map_get(map, "type", &obj); + INSIST(result == ISC_R_SUCCESS); + return (ns_config_getzonetype(obj)); } /* @@ -157,49 +289,61 @@ strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) { } isc_result_t -ns_zone_configure(dns_c_ctx_t *cctx, dns_c_view_t *cview, - dns_c_zone_t *czone, ns_aclconfctx_t *ac, - dns_zone_t *zone) +ns_zone_configure(cfg_obj_t *config, cfg_obj_t *vconfig, cfg_obj_t *zconfig, + ns_aclconfctx_t *ac, dns_zone_t *zone) { isc_result_t result; + char *zname; + dns_rdataclass_t zclass; + cfg_obj_t *maps[5]; + cfg_obj_t *zoptions = NULL; + cfg_obj_t *options = NULL; + cfg_obj_t *obj; const char *filename = NULL; dns_notifytype_t notifytype; -#ifdef notyet - dns_c_severity_t severity; -#endif - dns_c_iplist_t *iplist; - isc_sockaddr_t sockaddr; - isc_uint32_t uintval; - isc_sockaddr_t sockaddr_any4, sockaddr_any6; - dns_ssutable_t *ssutable = NULL; + isc_sockaddr_t *addrs; + dns_name_t **keynames; + isc_uint32_t count; char *cpval; unsigned int dbargc; char **dbargv; static char default_dbtype[] = "rbt"; isc_mem_t *mctx = dns_zone_getmctx(zone); dns_dialuptype_t dialup; - isc_boolean_t statistics; - - isc_sockaddr_any(&sockaddr_any4); - isc_sockaddr_any6(&sockaddr_any6); + dns_zonetype_t ztype; + int i; + i = 0; + if (zconfig != NULL) { + zoptions = cfg_tuple_get(zconfig, "options"); + maps[i++] = zoptions; + } + if (vconfig != NULL) + maps[i++] = cfg_tuple_get(vconfig, "options"); + if (config != NULL) { + (void)cfg_map_get(config, "options", &options); + if (options != NULL) + maps[i++] = options; + } + maps[i++] = ns_g_defaults; + maps[i++] = NULL; /* * Configure values common to all zone types. */ - dns_zone_setclass(zone, czone->zclass); + zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); - dns_zone_settype(zone, zonetype_fromconf(czone->ztype)); + RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"), &zclass)); + dns_zone_setclass(zone, zclass); - cpval = NULL; - result = dns_c_zone_getdatabase(czone, &cpval); -#ifdef notyet - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getdatabase(cview, &cpval); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getdatabase(cview, &cpval); -#endif - if (result != ISC_R_SUCCESS) + ztype = zonetype_fromconfig(zoptions); + dns_zone_settype(zone, ztype); + + obj = NULL; + result = cfg_map_get(zoptions, "database", &obj); + if (result == ISC_R_SUCCESS) + cpval = cfg_obj_asstring(obj); + else cpval = default_dbtype; RETERR(strtoargv(mctx, cpval, &dbargc, &dbargv)); /* @@ -210,141 +354,127 @@ ns_zone_configure(dns_c_ctx_t *cctx, dns_c_view_t *cview, RETERR(dns_zone_setdbtype(zone, dbargc, (const char * const *)dbargv)); isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv)); - result = dns_c_zone_getfile(czone, &filename); - if (result != ISC_R_SUCCESS) - filename = NULL; + obj = NULL; + result = cfg_map_get(zoptions, "file", &obj); + if (result == ISC_R_SUCCESS) + filename = cfg_obj_asstring(obj); RETERR(dns_zone_setfile(zone, filename)); -#ifdef notyet - result = dns_c_zone_getchecknames(czone, &severity); - if (result == ISC_R_SUCCESS) - dns_zone_setchecknames(zone, severity); - else - dns_zone_setchecknames(zone, dns_c_severity_warn); -#endif - - if (czone->ztype == dns_c_zone_slave) - RETERR(configure_zone_acl(czone, cctx, cview, ac, zone, - dns_c_zone_getallownotify, - dns_c_view_getallownotify, - dns_c_ctx_getallownotify, + if (ztype == dns_zone_slave) + RETERR(configure_zone_acl(zconfig, vconfig, config, + "allow-notify", ac, zone, dns_zone_setnotifyacl, dns_zone_clearnotifyacl)); /* * XXXAG This probably does not make sense for stubs. */ - RETERR(configure_zone_acl(czone, cctx, cview, ac, zone, - dns_c_zone_getallowquery, - dns_c_view_getallowquery, - dns_c_ctx_getallowquery, + RETERR(configure_zone_acl(zconfig, vconfig, config, + "allow-query", ac, zone, dns_zone_setqueryacl, dns_zone_clearqueryacl)); - result = dns_c_zone_getdialup(czone, &dialup); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getdialup(cview, &dialup); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getdialup(cctx, &dialup); - if (result != ISC_R_SUCCESS) - dialup = dns_dialuptype_no; + obj = NULL; + result = ns_config_get(maps, "dialup", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) + dialup = dns_dialuptype_yes; + else + dialup = dns_dialuptype_no; + } else { + char *dialupstr = cfg_obj_asstring(obj); + if (strcasecmp(dialupstr, "notify") == 0) + dialup = dns_dialuptype_notify; + else if (strcasecmp(dialupstr, "notify-passive") == 0) + dialup = dns_dialuptype_notifypassive; + else if (strcasecmp(dialupstr, "refresh") == 0) + dialup = dns_dialuptype_refresh; + else if (strcasecmp(dialupstr, "passive") == 0) + dialup = dns_dialuptype_passive; + else + INSIST(0); + } dns_zone_setdialup(zone, dialup); - result = dns_c_zone_getstatistics(czone, &statistics); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getstatistics(cview, &statistics); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getstatistics(cctx, &statistics); - if (result != ISC_R_SUCCESS) - statistics = ISC_FALSE; - dns_zone_setstatistics(zone, statistics); + obj = NULL; + result = ns_config_get(maps, "zone-statistics", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setstatistics(zone, cfg_obj_asboolean(obj)); /* * Configure master functionality. This applies * to primary masters (type "master") and slaves * acting as masters (type "slave"), but not to stubs. */ - if (czone->ztype != dns_c_zone_stub) { - result = dns_c_zone_getnotify(czone, ¬ifytype); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getnotify(cview, ¬ifytype); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getnotify(cctx, ¬ifytype); - if (result != ISC_R_SUCCESS) - notifytype = dns_notifytype_yes; + if (ztype != dns_zone_stub) { + obj = NULL; + result = ns_config_get(maps, "notify", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) + notifytype = dns_notifytype_yes; + else + notifytype = dns_notifytype_no; + } else { + char *notifystr = cfg_obj_asstring(obj); + if (strcasecmp(notifystr, "explicit") == 0) + notifytype = dns_notifytype_explicit; + else + INSIST(0); + } dns_zone_setnotifytype(zone, notifytype); - iplist = NULL; - result = dns_c_zone_getalsonotify(czone, &iplist); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getalsonotify(cview, &iplist); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getalsonotify(cctx, &iplist); + obj = NULL; + result = ns_config_get(maps, "also-notify", &obj); if (result == ISC_R_SUCCESS) { - result = dns_zone_setalsonotify(zone, iplist->ips, - iplist->nextidx); - dns_c_iplist_detach(&iplist); + isc_sockaddr_t *addrs = NULL; + isc_uint32_t addrcount; + result = ns_config_getiplist(config, obj, 0, mctx, + &addrs, &addrcount); + if (result != ISC_R_SUCCESS) + return (result); + result = dns_zone_setalsonotify(zone, addrs, + addrcount); + ns_config_putiplist(mctx, &addrs, addrcount); if (result != ISC_R_SUCCESS) return (result); } else RETERR(dns_zone_setalsonotify(zone, NULL, 0)); - result = dns_c_zone_getnotifysource(czone, &sockaddr); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getnotifysource(cview, &sockaddr); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getnotifysource(cctx, &sockaddr); - if (result != ISC_R_SUCCESS) - sockaddr = sockaddr_any4; - dns_zone_setnotifysrc4(zone, &sockaddr); + obj = NULL; + result = ns_config_get(maps, "notify-source", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)); - result = dns_c_zone_getnotifysourcev6(czone, &sockaddr); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getnotifysourcev6(cview, &sockaddr); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getnotifysourcev6(cctx, &sockaddr); - if (result != ISC_R_SUCCESS) - sockaddr = sockaddr_any6; - dns_zone_setnotifysrc6(zone, &sockaddr); + obj = NULL; + result = ns_config_get(maps, "notify-source-v6", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)); - RETERR(configure_zone_acl(czone, cctx, cview, ac, zone, - dns_c_zone_getallowtransfer, - dns_c_view_gettransferacl, - dns_c_ctx_getallowtransfer, + RETERR(configure_zone_acl(zconfig, vconfig, config, + "allow-transfer", ac, zone, dns_zone_setxfracl, dns_zone_clearxfracl)); - result = dns_c_zone_getmaxtranstimeout(czone, &uintval); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getmaxtransfertimeout(cview, - &uintval); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getmaxtransfertimeout(cctx, - &uintval); - if (result != ISC_R_SUCCESS) - uintval = MAX_XFER_TIME; - dns_zone_setmaxxfrout(zone, uintval); + obj = NULL; + result = ns_config_get(maps, "max-transfer-time-out", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj)); - result = dns_c_zone_getmaxtransidleout(czone, &uintval); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getmaxtransferidleout(cview, - &uintval); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getmaxtransferidleout(cctx, - &uintval); - if (result != ISC_R_SUCCESS) - uintval = DNS_DEFAULT_IDLEOUT; - dns_zone_setidleout(zone, uintval); + obj = NULL; + result = ns_config_get(maps, "max-transfer-idle-out", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setidleout(zone, cfg_obj_asuint32(obj)); } /* * Configure update-related options. These apply to * primary masters only. */ - if (czone->ztype == dns_c_zone_master) { + if (ztype == dns_zone_master) { dns_acl_t *updateacl; - RETERR(configure_zone_acl(czone, cctx, NULL, ac, zone, - dns_c_zone_getallowupd, - NULL, NULL, + RETERR(configure_zone_acl(zconfig, NULL, config, + "allow-update", ac, zone, dns_zone_setupdateacl, dns_zone_clearupdateacl)); @@ -354,118 +484,82 @@ ns_zone_configure(dns_c_ctx_t *cctx, dns_c_view_t *cview, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "zone '%s' allows updates by IP " "address, which is insecure", - czone->name); + zname); - result = dns_c_zone_getssuauth(czone, &ssutable); - if (result == ISC_R_SUCCESS) - dns_zone_setssutable(zone, ssutable); + RETERR(configure_zone_ssutable(zoptions, zone)); - result = dns_c_zone_getsigvalidityinterval(czone, &uintval); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getsigvalidityinterval(cview, - &uintval); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getsigvalidityinterval(cctx, - &uintval); - if (result != ISC_R_SUCCESS) - uintval = 30 * 24 * 3600; - dns_zone_setsigvalidityinterval(zone, uintval); - } else if (czone->ztype == dns_c_zone_slave) { - RETERR(configure_zone_acl(czone, cctx, NULL, ac, zone, - dns_c_zone_getallowupdateforwarding, - dns_c_view_getallowupdateforwarding, - dns_c_ctx_getallowupdateforwarding, + obj = NULL; + result = ns_config_get(maps, "sig-validity-interval", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setsigvalidityinterval(zone, cfg_obj_asuint32(obj)); + } else if (ztype == dns_zone_slave) { + RETERR(configure_zone_acl(zconfig, NULL, config, + "allow-update-forwarding", ac, zone, dns_zone_setforwardacl, dns_zone_clearforwardacl)); } - result = dns_c_zone_gettransfersource(czone, &sockaddr); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_gettransfersource(cview, &sockaddr); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_gettransfersource(cctx, &sockaddr); - if (result != ISC_R_SUCCESS) - sockaddr = sockaddr_any4; - dns_zone_setxfrsource4(zone, &sockaddr); + obj = NULL; + result = ns_config_get(maps, "transfer-source", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setxfrsource4(zone, cfg_obj_assockaddr(obj)); - result = dns_c_zone_gettransfersourcev6(czone, &sockaddr); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_gettransfersourcev6(cview, &sockaddr); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_gettransfersourcev6(cctx, &sockaddr); - if (result != ISC_R_SUCCESS) - sockaddr = sockaddr_any6; - dns_zone_setxfrsource6(zone, &sockaddr); + obj = NULL; + result = ns_config_get(maps, "transfer-source-v6", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setxfrsource6(zone, cfg_obj_assockaddr(obj)); /* * Configure slave functionality. */ - switch (czone->ztype) { - case dns_c_zone_slave: - case dns_c_zone_stub: - iplist = NULL; - result = dns_c_zone_getmasterips(czone, &iplist); - if (result == ISC_R_SUCCESS) { - result = dns_zone_setmasterswithkeys(zone, - iplist->ips, - iplist->keys, - iplist->nextidx); - dns_c_iplist_detach(&iplist); + switch (ztype) { + case dns_zone_slave: + case dns_zone_stub: + obj = NULL; + result = cfg_map_get(zoptions, "masters", &obj); + if (obj != NULL) { + addrs = NULL; + keynames = NULL; + RETERR(ns_config_getipandkeylist(config, obj, mctx, + &addrs, &keynames, + &count)); + result = dns_zone_setmasterswithkeys(zone, addrs, + keynames, count); + ns_config_putipandkeylist(mctx, &addrs, &keynames, + count); } else result = dns_zone_setmasters(zone, NULL, 0); RETERR(result); - result = dns_c_zone_getmaxtranstimein(czone, &uintval); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getmaxtransfertimein(cctx, - &uintval); - if (result != ISC_R_SUCCESS) - uintval = MAX_XFER_TIME; - dns_zone_setmaxxfrin(zone, uintval); + obj = NULL; + result = ns_config_get(maps, "max-transfer-time-in", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setmaxxfrin(zone, cfg_obj_asuint32(obj)); - result = dns_c_zone_getmaxtransidlein(czone, &uintval); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getmaxtransferidlein(cctx, - &uintval); - if (result != ISC_R_SUCCESS) - uintval = DNS_DEFAULT_IDLEIN; - dns_zone_setidlein(zone, uintval); + obj = NULL; + result = ns_config_get(maps, "max-transfer-idle-in", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setidlein(zone, cfg_obj_asuint32(obj)); - result = dns_c_zone_getmaxrefreshtime(czone, &uintval); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getmaxrefreshtime(cview, &uintval); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getmaxrefreshtime(cctx, &uintval); - if (result != ISC_R_SUCCESS) - uintval = DNS_ZONE_MAXREFRESH; - dns_zone_setmaxrefreshtime(zone, uintval); + obj = NULL; + result = ns_config_get(maps, "max-refresh-time", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setmaxrefreshtime(zone, cfg_obj_asuint32(obj)); - result = dns_c_zone_getminrefreshtime(czone, &uintval); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getminrefreshtime(cview, &uintval); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getminrefreshtime(cctx, &uintval); - if (result != ISC_R_SUCCESS) - uintval = DNS_ZONE_MINREFRESH; - dns_zone_setminrefreshtime(zone, uintval); + obj = NULL; + result = ns_config_get(maps, "min-refresh-time", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setminrefreshtime(zone, cfg_obj_asuint32(obj)); - result = dns_c_zone_getmaxretrytime(czone, &uintval); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getmaxretrytime(cview, &uintval); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getmaxretrytime(cctx, &uintval); - if (result != ISC_R_SUCCESS) - uintval = DNS_ZONE_MAXRETRY; - dns_zone_setmaxretrytime(zone, uintval); + obj = NULL; + result = ns_config_get(maps, "max-retry-time", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setmaxretrytime(zone, cfg_obj_asuint32(obj)); - result = dns_c_zone_getminretrytime(czone, &uintval); - if (result != ISC_R_SUCCESS && cview != NULL) - result = dns_c_view_getminretrytime(cview, &uintval); - if (result != ISC_R_SUCCESS) - result = dns_c_ctx_getminretrytime(cctx, &uintval); - if (result != ISC_R_SUCCESS) - uintval = DNS_ZONE_MINRETRY; - dns_zone_setminretrytime(zone, uintval); + obj = NULL; + result = ns_config_get(maps, "min-retry-time", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setminretrytime(zone, cfg_obj_asuint32(obj)); break; @@ -477,15 +571,23 @@ ns_zone_configure(dns_c_ctx_t *cctx, dns_c_view_t *cview, } isc_boolean_t -ns_zone_reusable(dns_zone_t *zone, dns_c_zone_t *czone) { +ns_zone_reusable(dns_zone_t *zone, cfg_obj_t *zconfig) { + cfg_obj_t *zoptions = NULL; + cfg_obj_t *obj = NULL; const char *cfilename; const char *zfilename; - if (zonetype_fromconf(czone->ztype) != dns_zone_gettype(zone)) + zoptions = cfg_tuple_get(zconfig, "options"); + + if (zonetype_fromconfig(zoptions) != dns_zone_gettype(zone)) return (ISC_FALSE); - cfilename = NULL; - (void) dns_c_zone_getfile(czone, &cfilename); + obj = NULL; + (void)cfg_map_get(zoptions, "file", &obj); + if (obj != NULL) + cfilename = cfg_obj_asstring(obj); + else + cfilename = NULL; zfilename = dns_zone_getfile(zone); if (cfilename == NULL || zfilename == NULL || strcmp(cfilename, zfilename) != 0) @@ -493,22 +595,3 @@ ns_zone_reusable(dns_zone_t *zone, dns_c_zone_t *czone) { return (ISC_TRUE); } - -isc_result_t -ns_zonemgr_configure(dns_c_ctx_t *cctx, dns_zonemgr_t *zmgr) { - isc_uint32_t val; - isc_result_t result; - - result = dns_c_ctx_gettransfersin(cctx, &val); - if (result != ISC_R_SUCCESS) - val = 10; - dns_zonemgr_settransfersin(zmgr, val); - - result = dns_c_ctx_gettransfersperns(cctx, &val); - if (result != ISC_R_SUCCESS) - val = 2; - dns_zonemgr_settransfersperns(zmgr, val); - - return (ISC_R_SUCCESS); -} - diff --git a/util/copyrights b/util/copyrights index d971eda4f3..005e198fbe 100644 --- a/util/copyrights +++ b/util/copyrights @@ -41,8 +41,10 @@ ./bin/named/Makefile.in MAKE 1998,1999,2000,2001 ./bin/named/aclconf.c C 1999,2000,2001 ./bin/named/client.c C 1999,2000,2001 +./bin/named/config.c C 2001 ./bin/named/include/named/aclconf.h C 1999,2000,2001 ./bin/named/include/named/client.h C 1999,2000,2001 +./bin/named/include/named/config.h C 2001 ./bin/named/include/named/globals.h C 1999,2000,2001 ./bin/named/include/named/interfacemgr.h C 1999,2000,2001 ./bin/named/include/named/listenlist.h C 2000,2001