diff options
Diffstat (limited to 'lib/dns/config')
-rw-r--r-- | lib/dns/config/.cvsignore | 3 | ||||
-rw-r--r-- | lib/dns/config/Makefile.in | 67 | ||||
-rw-r--r-- | lib/dns/config/confacl.c | 416 | ||||
-rw-r--r-- | lib/dns/config/confcache.c | 48 | ||||
-rw-r--r-- | lib/dns/config/confcommon.c | 553 | ||||
-rw-r--r-- | lib/dns/config/confctl.c | 267 | ||||
-rw-r--r-- | lib/dns/config/confctx.c | 4424 | ||||
-rw-r--r-- | lib/dns/config/confip.c | 1044 | ||||
-rw-r--r-- | lib/dns/config/confkeys.c | 1177 | ||||
-rw-r--r-- | lib/dns/config/conflog.c | 1345 | ||||
-rw-r--r-- | lib/dns/config/conflsn.c | 213 | ||||
-rw-r--r-- | lib/dns/config/confparser.y | 4508 | ||||
-rw-r--r-- | lib/dns/config/confpvt.h | 41 | ||||
-rw-r--r-- | lib/dns/config/confresolv.c | 47 | ||||
-rw-r--r-- | lib/dns/config/confrrset.c | 300 | ||||
-rw-r--r-- | lib/dns/config/confserv.c | 414 | ||||
-rw-r--r-- | lib/dns/config/confview.c | 1056 | ||||
-rw-r--r-- | lib/dns/config/confzone.c | 3596 |
18 files changed, 19519 insertions, 0 deletions
diff --git a/lib/dns/config/.cvsignore b/lib/dns/config/.cvsignore new file mode 100644 index 00000000..78fed989 --- /dev/null +++ b/lib/dns/config/.cvsignore @@ -0,0 +1,3 @@ +Makefile +confparser_p.h +confparser.c diff --git a/lib/dns/config/Makefile.in b/lib/dns/config/Makefile.in new file mode 100644 index 00000000..a3206271 --- /dev/null +++ b/lib/dns/config/Makefile.in @@ -0,0 +1,67 @@ +# Copyright (C) 1998, 1999, 2000 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. + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +@BIND9_INCLUDES@ + +CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} + +CDEFINES = +CWARNINGS = + +LIBS = @LIBS@ + +# Alphabetically + +OBJS = confparser.@O@ confcommon.@O@ confacl.@O@ confcache.@O@ \ + confctl.@O@ confctx.@O@ confip.@O@ confkeys.@O@ conflog.@O@ \ + conflsn.@O@ confresolv.@O@ confrrset.@O@ confserv.@O@ \ + confview.@O@ confzone.@O@ + +SRCS = confparser.c confcommon.c confacl.c confcache.c \ + confctl.c confctx.c confip.c confkeys.c conflog.c \ + conflsn.c confresolv.c confrrset.c confserv.c \ + confview.c confzone.c + +SUBDIRS = +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ + +##confparser.c: confparser.y +## ${YACC} -d ${srcdir}/confparser.y +## rm -f confparser.c confparser_p.h +## mv y.tab.c confparser.c +## mv y.tab.h confparser_p.h + +## This rule is here during development to help debugging. +## Remove and uncomment the rule above before release. +confparser.c: confparser.y + ${YACC} -d ${srcdir}/confparser.y + rm -f confparser.c confparser_p.h + sed -e '/^\#line/d' < y.tab.c > confparser.c + rm -f y.tab.c + chmod a-w confparser.c + mv y.tab.h confparser_p.h + +depend: confparser.c + +distclean:: + rm -f confparser.c confparser_p.h diff --git a/lib/dns/config/confacl.c b/lib/dns/config/confacl.c new file mode 100644 index 00000000..c7c522c8 --- /dev/null +++ b/lib/dns/config/confacl.c @@ -0,0 +1,416 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <string.h> + +#include <isc/assertions.h> +#include <isc/magic.h> + +#include <dns/log.h> +#include <dns/confacl.h> +#include <dns/confcommon.h> + + +static isc_result_t acl_delete(dns_c_acl_t **aclptr); + + + +isc_result_t +dns_c_acltable_new(isc_mem_t *mem, dns_c_acltable_t **newtable) +{ + dns_c_acltable_t *table; + + REQUIRE(mem != NULL); + REQUIRE(newtable != NULL); + + table = isc_mem_get(mem, sizeof *table); + if (table == NULL) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Out of memory"); + return (ISC_R_NOMEMORY); + } + + table->mem = mem; + table->magic = DNS_C_CONFACLTABLE_MAGIC; + + ISC_LIST_INIT(table->acl_list); + + *newtable = table; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_acltable_delete(dns_c_acltable_t **table) +{ + dns_c_acltable_t *acltable; + isc_mem_t *mem; + + REQUIRE(table != NULL); + REQUIRE(*table != NULL); + + acltable = *table; + + REQUIRE(DNS_C_CONFACLTABLE_VALID(acltable)); + + dns_c_acltable_clear(acltable); + + mem = acltable->mem; + + acltable->magic = 0; + acltable->mem = NULL; + + + isc_mem_put(mem, acltable, sizeof *acltable); + + return (ISC_R_SUCCESS); +} + + +void +dns_c_acltable_print(FILE *fp, int indent, dns_c_acltable_t *table) +{ + dns_c_acl_t *acl; + dns_c_acl_t *acltmp; + + REQUIRE(fp != NULL); + REQUIRE(indent >= 0); + + if (table == NULL) { + return; + } + + REQUIRE(DNS_C_CONFACLTABLE_VALID(table)); + + acl = ISC_LIST_HEAD(table->acl_list); + while (acl != NULL) { + acltmp = ISC_LIST_NEXT(acl, next); + + if (!acl->is_special) { /* don't print specials */ + dns_c_acl_print(fp, indent, acl); + fprintf(fp, "\n"); + } + + acl = acltmp; + } +} + + +isc_result_t +dns_c_acltable_clear(dns_c_acltable_t *table) +{ + dns_c_acl_t *elem; + dns_c_acl_t *tmpelem; + isc_result_t r; + + REQUIRE(DNS_C_CONFACLTABLE_VALID(table)); + + elem = ISC_LIST_HEAD(table->acl_list); + while (elem != NULL) { + tmpelem = ISC_LIST_NEXT(elem, next); + ISC_LIST_UNLINK(table->acl_list, elem, next); + + r = acl_delete(&elem); + if (r != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_CRITICAL, + "Failed to delete acl element."); + return (r); + } + + elem = tmpelem; + } + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_acltable_getacl(dns_c_acltable_t *table, + const char *aclname, dns_c_acl_t **retval) +{ + dns_c_acl_t *elem; + + REQUIRE(DNS_C_CONFACLTABLE_VALID(table)); + REQUIRE(retval != NULL); + REQUIRE(aclname != NULL); + REQUIRE(strlen(aclname) > 0); + + + elem = ISC_LIST_HEAD(table->acl_list); + while (elem != NULL) { + if (strcmp(aclname, elem->name) == 0) { + break; + } + + elem = ISC_LIST_NEXT(elem, next); + } + + if (elem != NULL) { + REQUIRE(DNS_C_CONFACL_VALID(elem)); + *retval = elem; + } + + return (elem == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_acltable_removeacl(dns_c_acltable_t *table, const char *aclname) +{ + dns_c_acl_t *acl; + dns_c_acl_t *tmpacl; + + REQUIRE(DNS_C_CONFACLTABLE_VALID(table)); + REQUIRE(aclname != NULL); + + acl = ISC_LIST_HEAD(table->acl_list); + while (acl != NULL) { + tmpacl = ISC_LIST_NEXT(acl, next); + if (strcmp(aclname, acl->name) == 0) { + ISC_LIST_UNLINK(table->acl_list, acl, next); + acl_delete(&acl); + return (ISC_R_SUCCESS); + } + + acl = tmpacl; + } + + return (ISC_R_NOTFOUND); +} + + +isc_result_t +dns_c_acl_new(dns_c_acltable_t *table, const char *aclname, + isc_boolean_t isspecial, dns_c_acl_t **newacl) +{ + dns_c_acl_t *acl; + + REQUIRE(DNS_C_CONFACLTABLE_VALID(table)); + REQUIRE(aclname != NULL); + REQUIRE(strlen(aclname) > 0); + REQUIRE(newacl != NULL); + + acl = isc_mem_get(table->mem, sizeof *acl); + if (acl == NULL) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Not enough memory"); + return (ISC_R_NOMEMORY); + } + + acl->mytable = table; + acl->magic = DNS_C_CONFACL_MAGIC; + acl->name = NULL; + acl->ipml = NULL; + acl->is_special = isspecial; + + acl->name = isc_mem_strdup(table->mem, aclname); + if (acl->name == NULL) { + isc_mem_put(table->mem, acl, sizeof *acl); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Not enough memory"); + return (ISC_R_NOMEMORY); + } + + ISC_LIST_APPEND(table->acl_list, acl, next); + + *newacl = acl; + + return (ISC_R_SUCCESS); +} + + +void +dns_c_acl_print(FILE *fp, int indent, dns_c_acl_t *acl) +{ + REQUIRE(DNS_C_CONFACL_VALID(acl)); + + dns_c_printtabs(fp, indent); + fprintf(fp, "acl "); + if (acl->name == NULL) { + fprintf(fp, "anon-acl-%p ", acl); + } else { + fprintf(fp, "%s ", acl->name); + } + + if (acl->ipml != NULL) { + dns_c_ipmatchlist_print(fp, indent + 1, acl->ipml); + } else { + fprintf(fp, "{\n"); + dns_c_printtabs(fp, indent); + fprintf(fp, "}"); + } + fprintf(fp, ";\n"); +} + + +isc_result_t +dns_c_acl_setipml(dns_c_acl_t *acl, + dns_c_ipmatchlist_t *ipml, isc_boolean_t deepcopy) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFACL_VALID(acl)); + REQUIRE(ipml != NULL); + + if (acl->ipml != NULL) { + dns_c_ipmatchlist_detach(&acl->ipml); + } + + if (deepcopy) { + res = dns_c_ipmatchlist_copy(acl->mytable->mem, + &acl->ipml, ipml); + } else { + acl->ipml = ipml; + res = ISC_R_SUCCESS; + } + + return (res); +} + + +isc_result_t +dns_c_acl_getipmlexpanded(isc_mem_t *mem, dns_c_acl_t *acl, + dns_c_ipmatchlist_t **retval) +{ + dns_c_ipmatchlist_t *newlist; + isc_result_t r; + + REQUIRE(DNS_C_CONFACL_VALID(acl)); + + if (acl->ipml == NULL) { + newlist = NULL; + r = ISC_R_SUCCESS; + } else { + r = dns_c_ipmatchlist_copy(mem, &newlist, acl->ipml); + if (r != ISC_R_SUCCESS) { + return (r); + } + + r = dns_c_acl_expandacls(acl->mytable, newlist); + } + + *retval = newlist; + + return (r); +} + + + +/* XXX this should really be a function in the confip module */ + +isc_result_t +dns_c_acl_expandacls(dns_c_acltable_t *table, + dns_c_ipmatchlist_t *list) +{ + dns_c_ipmatchelement_t *elem; + dns_c_ipmatchelement_t *tmpelem; + dns_c_acl_t *acl; + isc_result_t r; + isc_boolean_t isneg; + + REQUIRE(DNS_C_CONFACLTABLE_VALID(table)); + + if (list == NULL) { + return (ISC_R_SUCCESS); + } + + elem = ISC_LIST_HEAD(list->elements); + while (elem != NULL) { + switch (elem->type) { + case dns_c_ipmatch_indirect: + dns_c_acl_expandacls(table, + elem->u.indirect.list); + break; + + case dns_c_ipmatch_acl: + r = dns_c_acltable_getacl(table, + elem->u.aclname, &acl); + if (r != ISC_R_SUCCESS) { + return (ISC_R_FAILURE); + } + + if (acl->ipml != NULL) { + isneg = dns_c_ipmatchelement_isneg(elem); + + /* XXX I this should be inserted in place and + * not appended + */ + dns_c_ipmatchlist_append(list, + acl->ipml, isneg); + } + + default: + ; /* Do nothing */ + } + + tmpelem = ISC_LIST_NEXT(elem, next); + + if (elem->type == dns_c_ipmatch_acl) { + ISC_LIST_UNLINK(list->elements, elem, next); + } + + elem = tmpelem; + } + + + return (ISC_R_SUCCESS); +} + + + + +static isc_result_t +acl_delete(dns_c_acl_t **aclptr) +{ + dns_c_acl_t *acl; + isc_result_t res; + isc_mem_t *mem; + + REQUIRE(aclptr != NULL); + REQUIRE(*aclptr != NULL); + + acl = *aclptr; + + REQUIRE(DNS_C_CONFACL_VALID(acl)); + + mem = acl->mytable->mem; + + acl->mytable = NULL; + + isc_mem_free(mem, acl->name); + + if (acl->ipml != NULL) + res = dns_c_ipmatchlist_detach(&acl->ipml); + else + res = ISC_R_SUCCESS; + + acl->magic = 0; + + isc_mem_put(mem, acl, sizeof *acl); + + return (res); +} + + diff --git a/lib/dns/config/confcache.c b/lib/dns/config/confcache.c new file mode 100644 index 00000000..5bdb7092 --- /dev/null +++ b/lib/dns/config/confcache.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <dns/confcache.h> +#include <dns/result.h> + +#include "confpvt.h" + +isc_result_t +dns_c_cache_new(isc_mem_t *mem, dns_c_cache_t **cfgcache) +{ + + (void) mem ; (void) cfgcache; /* lint */ + + /* XXX nothing yet */ + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_cache_delete(dns_c_cache_t **cfgcache) +{ + (void) cfgcache ; /* lint */ + + /* XXX nothin yet */ + + return (ISC_R_SUCCESS); +} + + + diff --git a/lib/dns/config/confcommon.c b/lib/dns/config/confcommon.c new file mode 100644 index 00000000..23235835 --- /dev/null +++ b/lib/dns/config/confcommon.c @@ -0,0 +1,553 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <sys/types.h> /* XXXRTH */ + +#include <limits.h> +#include <syslog.h> /* XXXRTH */ +#include <ctype.h> +#include <string.h> + +#include <isc/assertions.h> +#include <isc/buffer.h> + +/* XXX this next include is needed by <dns/rdataclass.h> */ +#include <dns/result.h> + +#include <dns/rdataclass.h> +#include <dns/rdatatype.h> + +#include <dns/confcommon.h> + + + +/*** + *** TYPES + ***/ + +#define ordering_nametable_size \ + (sizeof (ordering_nametable) / sizeof (struct dns_c_pvt_ont)) +static struct dns_c_pvt_ont { + dns_c_ordering_t val; + const char *strval; +} ordering_nametable[] = { + { dns_c_ordering_fixed, "fixed" }, + { dns_c_ordering_random, "random" }, + { dns_c_ordering_cyclic, "cyclic" } +}; + + +#define log_severity_nametable_size \ + (sizeof (log_severity_nametable) / sizeof (struct dns_c_pvt_lsnt)) +static struct dns_c_pvt_lsnt { + dns_c_logseverity_t val; + const char *strval; +} log_severity_nametable[] = { + { dns_c_log_critical, "critical" }, + { dns_c_log_error, "error" }, + { dns_c_log_info, "info" }, + { dns_c_log_notice, "notice" }, + { dns_c_log_warn, "warning" }, + { dns_c_log_debug, "debug" }, + { dns_c_log_dynamic, "dynamic" } +}; + + +static struct dsn_c_pvt_sfnt { + int val; + const char *strval; +} syslog_facil_nametable[] = { + { LOG_KERN, "kern" }, + { LOG_USER, "user" }, + { LOG_MAIL, "mail" }, + { LOG_DAEMON, "daemon" }, + { LOG_AUTH, "auth" }, + { LOG_SYSLOG, "syslog" }, + { LOG_LPR, "lpr" }, +#ifdef LOG_NEWS + { LOG_NEWS, "news" }, +#endif +#ifdef LOG_UUCP + { LOG_UUCP, "uucp" }, +#endif +#ifdef LOG_CRON + { LOG_CRON, "cron" }, +#endif +#ifdef LOG_AUTHPRIV + { LOG_AUTHPRIV, "authpriv" }, +#endif +#ifdef LOG_FTP + { LOG_FTP, "ftp" }, +#endif + { LOG_LOCAL0, "local0"}, + { LOG_LOCAL1, "local1"}, + { LOG_LOCAL2, "local2"}, + { LOG_LOCAL3, "local3"}, + { LOG_LOCAL4, "local4"}, + { LOG_LOCAL5, "local5"}, + { LOG_LOCAL6, "local6"}, + { LOG_LOCAL7, "local7"}, + { 0, NULL } +}; + + +#define category_nametable_size \ + (sizeof (category_nametable) / sizeof(struct dns_c_pvt_cntable)) +static struct dns_c_pvt_cntable { + dns_c_category_t val; + const char *strval; +} category_nametable[] = { + { dns_c_cat_default, "default" }, + { dns_c_cat_config, "config" }, + { dns_c_cat_parser, "parser" }, + { dns_c_cat_queries, "queries" }, + { dns_c_cat_lameservers, "lame-servers" }, + { dns_c_cat_statistics, "statistics" }, + { dns_c_cat_panic, "panic" }, + { dns_c_cat_update, "update" }, + { dns_c_cat_ncache, "ncache" }, + { dns_c_cat_xferin, "xfer-in" }, + { dns_c_cat_xferout, "xfer-out" }, + { dns_c_cat_db, "db" }, + { dns_c_cat_eventlib, "eventlib" }, + { dns_c_cat_packet, "packet" }, + { dns_c_cat_notify, "notify" }, + { dns_c_cat_cname, "cname" }, + { dns_c_cat_security, "security" }, + { dns_c_cat_os, "os" }, + { dns_c_cat_insist, "insist" }, + { dns_c_cat_maint, "maintenance" }, + { dns_c_cat_load, "load" }, + { dns_c_cat_respchecks, "response-checks" }, + { dns_c_cat_control, "control" } +}; + + + +/*** + *** DATA + ***/ + +isc_boolean_t debug_mem_print; +FILE *debug_mem_print_stream; + + + +/*** + *** FUNCTIONS + ***/ + +#if 0 /* XXXJAB delete this code */ +static void default_cfgerror(isc_result_t result, const char *fmt, + va_list args); +#endif + + + +void +dns_c_printinunits(FILE *fp, isc_uint32_t val) +{ + isc_uint32_t one_gig = (1024 * 1024 * 1024); + isc_uint32_t one_meg = (1024 * 1024); + isc_uint32_t one_k = 1024; + + if (val == DNS_C_SIZE_SPEC_DEFAULT) + fprintf(fp, "default"); + else if (val == 0) + fprintf(fp, "0"); + else if ((val % one_gig) == 0) + fprintf(fp, "%luG", (unsigned long) val / one_gig); + else if ((val % one_meg) == 0) + fprintf(fp, "%luM", (unsigned long) val / one_meg); + else if ((val % one_k) == 0) + fprintf(fp, "%luK", (unsigned long) val / one_k); + else if (val == DNS_C_SIZE_SPEC_UNLIM) + fprintf(fp, "unlimited"); + else + fprintf(fp, "%lu", (unsigned long) val); +} + + +void +dns_c_dataclass_tostream(FILE *fp, dns_rdataclass_t rclass) +{ + char buffer[64]; + isc_buffer_t sourceb; + + isc_buffer_init(&sourceb, buffer, sizeof buffer, + ISC_BUFFERTYPE_GENERIC); + + if (dns_rdataclass_totext(rclass, &sourceb) == DNS_R_SUCCESS) { + INSIST(sourceb.used + 1 < sizeof buffer); + buffer[sourceb.used] = '\0'; + fputs(buffer, fp); + } else { + fprintf(fp, "UNKNOWN-CLASS(%d)",(int) rclass); + } +} + + +void +dns_c_datatype_tostream(FILE *fp, dns_rdatatype_t rtype) +{ + char buffer[64]; + isc_buffer_t sourceb; + + isc_buffer_init(&sourceb, buffer, sizeof buffer, + ISC_BUFFERTYPE_GENERIC); + + if (dns_rdatatype_totext(rtype, &sourceb) == DNS_R_SUCCESS) { + INSIST(sourceb.used + 1 < sizeof buffer); + buffer[sourceb.used] = '\0'; + fputs(buffer, fp); + } else { + fprintf(fp, "UNKNOWN-RDATATYPE(%d)",(int) rtype); + } +} + + +void +dns_c_printtabs(FILE *fp, int count) +{ + + while (count > 0) { + fputc('\t', fp); + count--; + } +} + + + +isc_result_t +dns_c_string2ordering(char *name, dns_c_ordering_t *ordering) +{ + unsigned int i; + isc_result_t rval = ISC_R_FAILURE; + + for (i = 0 ; i < ordering_nametable_size ; i++) { + if (strcmp(ordering_nametable[i].strval, name) == 0) { + *ordering = ordering_nametable[i].val; + rval = ISC_R_SUCCESS; + break; + } + } + + return (rval); +} + + +const char * +dns_c_ordering2string(dns_c_ordering_t ordering, + isc_boolean_t printable) +{ + unsigned int i; + const char *rval = NULL; + + for (i = 0 ; i < ordering_nametable_size ; i++) { + if (ordering_nametable[i].val == ordering) { + rval = ordering_nametable[i].strval; + break; + } + } + + return (rval == NULL && printable ? "UNKNOWN_ORDERING" : rval); +} + + +const char * +dns_c_logseverity2string(dns_c_logseverity_t severity, + isc_boolean_t printable) +{ + unsigned int i; + const char *rval = NULL; + + for (i = 0 ; i < log_severity_nametable_size ; i++) { + if (log_severity_nametable[i].val == severity) { + rval = log_severity_nametable[i].strval; + break; + } + } + + return (rval == NULL && printable ? "UNKNOWN_SEVERITY" : rval); +} + + +isc_result_t +dns_c_string2logseverity(const char *string, + dns_c_logseverity_t *result) +{ + unsigned int i; + isc_result_t rval = ISC_R_FAILURE; + + REQUIRE(result != NULL); + + for (i = 0 ; i < log_severity_nametable_size ; i++) { + if (strcmp(log_severity_nametable[i].strval, string) == 0) { + *result = log_severity_nametable[i].val; + rval = ISC_R_SUCCESS; + break; + } + } + + return rval; +} + + +const char * +dns_c_category2string(dns_c_category_t cat, + isc_boolean_t printable) +{ + unsigned int i; + const char *rval = NULL; + + for (i = 0 ; i < category_nametable_size ; i++) { + if (category_nametable[i].val == cat) { + rval = category_nametable[i].strval; + break; + } + } + + return (rval == NULL && printable ? "UNKNOWN_CATEGORY" : rval); +} + + +isc_result_t +dns_c_string2category(const char *string, + dns_c_category_t *category) +{ + unsigned int i; + isc_result_t rval = ISC_R_FAILURE; + + REQUIRE (category != NULL); + + for (i = 0 ; i < category_nametable_size ; i++) { + if (strcmp(category_nametable[i].strval, string) == 0) { + *category = category_nametable[i].val; + rval = ISC_R_SUCCESS; + break; + } + } + + return (rval); +} + + + +const char * +dns_c_facility2string(int facility, isc_boolean_t printable) +{ + int i; + const char *rval = NULL; + + for (i = 0 ; syslog_facil_nametable[i].strval != NULL ; i++) { + if (syslog_facil_nametable[i].val == facility) { + rval = syslog_facil_nametable[i].strval; + break; + } + } + + return (rval == NULL && printable ? "UNKNOWN_FACILITY" : rval); +} + + +isc_result_t +dns_c_string2facility(const char *string, int *result) +{ + int i; + isc_result_t rval = ISC_R_FAILURE; + + for (i = 0 ; syslog_facil_nametable[i].strval != NULL ; i++) { + if (strcmp(syslog_facil_nametable[i].strval, string) == 0) { + *result = syslog_facil_nametable[i].val; + rval = ISC_R_SUCCESS; + break; + } + } + + return rval; +} + + +const char * +dns_c_transformat2string(dns_transfer_format_t tformat, + isc_boolean_t printable) +{ + const char *rval = NULL; + + switch (tformat) { + case dns_one_answer: + rval = "one-answer"; + break; + + case dns_many_answers: + rval = "many-answers"; + break; + } + + return (rval == NULL && printable ? "UNKNOWN_TRANSFER_FORMAT" : rval); +} + + + + +const char * +dns_c_transport2string(dns_c_trans_t transport, + isc_boolean_t printable) +{ + const char *rval = NULL; + + switch (transport) { + case dns_trans_primary: + rval = "master"; + break; + + case dns_trans_secondary: + rval = "slave"; + break; + + case dns_trans_response: + rval = "response"; + break; + } + + return (rval == NULL && printable ? "UNKNOWN_TRANSPORT" : rval); +} + + +const char * +dns_c_nameseverity2string(dns_severity_t severity, + isc_boolean_t printable) +{ + const char *rval = NULL; + + switch (severity) { + case dns_severity_ignore: + rval = "ignore"; + break; + + case dns_severity_warn: + rval = "warn"; + break; + + case dns_severity_fail: + rval = "fail"; + break; + } + + return (rval == NULL && printable ? "UNKNOWN_NAME_SEVERITY" : rval); +} + + +const char * +dns_c_forward2string(dns_c_forw_t forw, + isc_boolean_t printable) +{ + const char *rval = NULL; + + switch (forw) { + case dns_c_forw_only: + rval = "only"; + break; + + case dns_c_forw_first: + rval = "first"; + break; + + case dns_c_forw_noanswer: + rval = "if-no-answer"; + break; + + case dns_c_forw_nodomain: + rval = "if-no-domain"; + break; + } + + return (rval == NULL && printable ? "UNKNOWN_FORWARDING" : rval); +} + + + +int +dns_c_isanyaddr(isc_sockaddr_t *inaddr) +{ + int result = 0; + + if (inaddr->type.sa.sa_family == AF_INET) { + if (inaddr->type.sin.sin_addr.s_addr == htonl(INADDR_ANY)) { + result = 1; + } + } else { + if (memcmp(&inaddr->type.sin6.sin6_addr, + &in6addr_any, sizeof in6addr_any) == 0) { + result = 1; + } + } + + return (result); +} + + + +void +dns_c_print_ipaddr(FILE *fp, isc_sockaddr_t *inaddr) +{ + const char *p; + char tmpaddrstr[64]; + int family = inaddr->type.sa.sa_family; + void *addr; + + if (dns_c_isanyaddr(inaddr)) { + if (family == AF_INET) { + fprintf(fp, "*"); + } else { + fprintf(fp, "0::0"); + } + } else { + addr = (family == AF_INET ? + (void *)&inaddr->type.sin.sin_addr : + (void *)&inaddr->type.sin6.sin6_addr); + + p = inet_ntop(family, addr, tmpaddrstr, sizeof tmpaddrstr); + if (p == NULL) { + fprintf(fp, "BAD-IP-ADDRESS"); + } else { + fprintf(fp, "%s", tmpaddrstr); + } + } +} + + +isc_boolean_t +dns_c_need_quote(const char *string) +{ + isc_boolean_t rval = ISC_FALSE; + + while (string != NULL && *string != '\0') { + if (!(isalnum(*string & 0xff) || *string == '_')) { + rval = ISC_TRUE; + break; + } + string++; + } + + return rval; +} + + + diff --git a/lib/dns/config/confctl.c b/lib/dns/config/confctl.c new file mode 100644 index 00000000..5e8e7009 --- /dev/null +++ b/lib/dns/config/confctl.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <sys/types.h> + +#include <isc/assertions.h> +#include <isc/net.h> +#include <isc/magic.h> + +#include <dns/confctl.h> +#include <dns/confcommon.h> + + +isc_result_t +dns_c_ctrllist_new(isc_mem_t *mem, dns_c_ctrllist_t **newlist) +{ + dns_c_ctrllist_t *newl; + + REQUIRE(mem != NULL); + REQUIRE (newlist != NULL); + + newl = isc_mem_get(mem, sizeof *newl); + if (newl == NULL) { + /* XXXJAB logwrite */ + return (ISC_R_NOMEMORY); + } + + newl->mem = mem; + newl->magic = DNS_C_CONFCTLLIST_MAGIC; + + ISC_LIST_INIT(newl->elements); + + *newlist = newl; + + return (ISC_R_SUCCESS); +} + + + +void +dns_c_ctrllist_print(FILE *fp, int indent, dns_c_ctrllist_t *cl) +{ + dns_c_ctrl_t *ctl; + + if (cl == NULL) { + return; + } + + REQUIRE(DNS_C_CONFCTLLIST_VALID(cl)); + + fprintf(fp, "controls {\n"); + ctl = ISC_LIST_HEAD(cl->elements); + if (ctl == NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp,"/* empty list */\n"); + } else { + while (ctl != NULL) { + dns_c_printtabs(fp, indent + 1); + dns_c_ctrl_print(fp, indent + 1, ctl); + ctl = ISC_LIST_NEXT(ctl, next); + } + } + fprintf(fp, "};\n"); +} + + + +isc_result_t +dns_c_ctrllist_delete(dns_c_ctrllist_t **list) +{ + dns_c_ctrl_t *ctrl; + dns_c_ctrl_t *tmpctrl; + dns_c_ctrllist_t *clist; + + REQUIRE(list != NULL); + REQUIRE(*list != NULL); + + clist = *list; + + REQUIRE(DNS_C_CONFCTLLIST_VALID(clist)); + + ctrl = ISC_LIST_HEAD(clist->elements); + while (ctrl != NULL) { + tmpctrl = ISC_LIST_NEXT(ctrl, next); + dns_c_ctrl_delete(&ctrl); + ctrl = tmpctrl; + } + + clist->magic = 0; + isc_mem_put(clist->mem, clist, sizeof *clist); + + *list = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctrlinet_new(isc_mem_t *mem, dns_c_ctrl_t **control, + isc_sockaddr_t addr, in_port_t port, + dns_c_ipmatchlist_t *iml, isc_boolean_t copy) +{ + dns_c_ctrl_t *ctrl; + isc_result_t res; + + REQUIRE(mem != NULL); + REQUIRE(control != NULL); + + ctrl = isc_mem_get(mem, sizeof *ctrl); + if (ctrl == NULL) { + return (ISC_R_NOMEMORY); + } + + ctrl->magic = DNS_C_CONFCTL_MAGIC; + ctrl->mem = mem; + ctrl->control_type = dns_c_inet_control; + ctrl->u.inet_v.addr = addr; + ctrl->u.inet_v.port = port; + + if (copy) { + res = dns_c_ipmatchlist_copy(mem, + &ctrl->u.inet_v.matchlist, iml); + if (res != ISC_R_SUCCESS) { + isc_mem_put(mem, ctrl, sizeof *ctrl); + return (res); + } + } else { + ctrl->u.inet_v.matchlist = iml; + } + + *control = ctrl; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctrlunix_new(isc_mem_t *mem, dns_c_ctrl_t **control, + const char *path, int perm, uid_t uid, gid_t gid) +{ + dns_c_ctrl_t *ctrl; + + REQUIRE(mem != NULL); + REQUIRE(control != NULL); + + ctrl = isc_mem_get(mem, sizeof *ctrl); + if (ctrl == NULL) { + return (ISC_R_NOMEMORY); + } + + ctrl->magic = DNS_C_CONFCTL_MAGIC; + ctrl->mem = mem; + ctrl->control_type = dns_c_unix_control; + ctrl->u.unix_v.pathname = isc_mem_strdup(mem, path); + if (ctrl->u.unix_v.pathname == NULL) { + isc_mem_put(mem, ctrl, sizeof *ctrl); + /* XXXJAB logwrite */ + return (ISC_R_NOMEMORY); + } + + ctrl->u.unix_v.perm = perm; + ctrl->u.unix_v.owner = uid; + ctrl->u.unix_v.group = gid; + + *control = ctrl; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctrl_delete(dns_c_ctrl_t **control) +{ + isc_result_t res = ISC_R_SUCCESS; + isc_result_t rval; + isc_mem_t *mem; + dns_c_ctrl_t *ctrl; + + REQUIRE(control != NULL); + REQUIRE(*control != NULL); + + ctrl = *control; + + REQUIRE(DNS_C_CONFCTL_VALID(ctrl)); + + mem = ctrl->mem; + + switch (ctrl->control_type) { + case dns_c_inet_control: + if (ctrl->u.inet_v.matchlist != NULL) + res = dns_c_ipmatchlist_detach(&ctrl->u.inet_v.matchlist); + else + res = ISC_R_SUCCESS; + break; + + case dns_c_unix_control: + isc_mem_free(mem, ctrl->u.unix_v.pathname); + res = ISC_R_SUCCESS; + break; + } + + rval = res; + + ctrl->magic = 0; + + isc_mem_put(mem, ctrl, sizeof *ctrl); + + *control = NULL; + + return (res); +} + + +void +dns_c_ctrl_print(FILE *fp, int indent, dns_c_ctrl_t *ctl) +{ + in_port_t port; + dns_c_ipmatchlist_t *iml; + + REQUIRE(DNS_C_CONFCTL_VALID(ctl)); + + (void) indent; + + if (ctl->control_type == dns_c_inet_control) { + port = ctl->u.inet_v.port; + iml = ctl->u.inet_v.matchlist; + + fprintf(fp, "inet "); + dns_c_print_ipaddr(fp, &ctl->u.inet_v.addr); + + if (port == 0) { + fprintf(fp, " port *\n"); + } else { + fprintf(fp, " port %d\n", port); + } + + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "allow "); + dns_c_ipmatchlist_print(fp, indent + 2, iml); + fprintf(fp, ";\n"); + } else { + /* The "#" means force a leading zero */ + fprintf(fp, "unix \"%s\" perm %#o owner %lu group %lu;\n", + ctl->u.unix_v.pathname, + ctl->u.unix_v.perm, + (unsigned long)ctl->u.unix_v.owner, + (unsigned long)ctl->u.unix_v.group); + } +} + + diff --git a/lib/dns/config/confctx.c b/lib/dns/config/confctx.c new file mode 100644 index 00000000..9ed62fd7 --- /dev/null +++ b/lib/dns/config/confctx.c @@ -0,0 +1,4424 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <syslog.h> /* XXXRTH */ +#include <string.h> + +#include <isc/assertions.h> +#include <isc/error.h> +#include <isc/magic.h> + +#include <dns/confctx.h> +#include <dns/confcommon.h> +#include <dns/log.h> + +#include "confpvt.h" + + + +/* + * Bit positions in the flags fields of the dns_c_options_t structure. + */ +#define MAX_NCACHE_TTL_BIT 0 +#define TRANSFERS_IN_BIT 1 +#define TRANSFERS_PER_NS_BIT 2 +#define TRANSFERS_OUT_BIT 3 +#define MAX_LOG_SIZE_IXFR_BIT 4 +#define CLEAN_INTERVAL_BIT 5 +#define INTERFACE_INTERVAL_BIT 6 +#define STATS_INTERVAL_BIT 7 +#define HEARTBEAT_INTERVAL_BIT 8 +#define MAX_TRANSFER_TIME_IN_BIT 9 +#define MAX_TRANSFER_TIME_OUT_BIT 10 +#define MAX_TRANSFER_IDLE_IN_BIT 11 +#define MAX_TRANSFER_IDLE_OUT_BIT 12 +#define DATA_SIZE_BIT 13 +#define STACK_SIZE_BIT 14 +#define CORE_SIZE_BIT 15 +#define FILES_BIT 16 +#define QUERY_SOURCE_ADDR_BIT 17 +#define QUERY_SOURCE_PORT_BIT 18 +#define FAKE_IQUERY_BIT 19 +#define RECURSION_BIT 20 +#define FETCH_GLUE_BIT 21 +#define NOTIFY_BIT 22 +#define HOST_STATISTICS_BIT 23 +#define DEALLOC_ON_EXIT_BIT 24 +#define USE_IXFR_BIT 25 +#define MAINTAIN_IXFR_BASE_BIT 26 +#define HAS_OLD_CLIENTS_BIT 27 +#define AUTH_NX_DOMAIN_BIT 28 +#define MULTIPLE_CNAMES_BIT 29 +#define USE_ID_POOL_BIT 30 +#define DIALUP_BIT 31 +#define CHECKNAME_PRIM_BIT 32 +#define CHECKNAME_SEC_BIT 33 +#define CHECKNAME_RESP_BIT 34 +#define OPTIONS_TRANSFER_FORMAT_BIT 35 +#define FORWARD_BIT 36 +#define EXPERT_MODE_BIT 37 +#define RFC2308_TYPE1_BIT 38 +#define TCP_CLIENTS_BIT 39 +#define RECURSIVE_CLIENTS_BIT 40 +#define TRANSFER_SOURCE_BIT 41 + + +static isc_result_t cfg_set_iplist(dns_c_options_t *options, + dns_c_iplist_t **fieldaddr, + dns_c_iplist_t *newval, + isc_boolean_t copy); +static isc_result_t cfg_set_ipmatchlist(dns_c_options_t *options, + dns_c_ipmatchlist_t **fieldaddr, + dns_c_ipmatchlist_t *newval, + isc_boolean_t copy); +static isc_result_t cfg_set_boolean(dns_c_options_t *options, + isc_boolean_t *fieldaddr, + isc_boolean_t newval, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber); +static isc_result_t cfg_set_int32(dns_c_options_t *options, + isc_int32_t *fieldaddr, + isc_int32_t newval, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber); +static isc_result_t cfg_set_uint32(dns_c_options_t *options, + isc_uint32_t *fieldaddr, + isc_uint32_t newval, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber); +static isc_result_t cfg_set_string(dns_c_options_t *options, + char **field, + const char *newval); + +static isc_result_t cfg_get_uint32(dns_c_options_t *options, + isc_uint32_t *field, + isc_uint32_t *result, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber); +static isc_result_t cfg_get_int32(dns_c_options_t *options, + isc_int32_t *field, + isc_int32_t *result, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber); +static isc_result_t cfg_get_boolean(dns_c_options_t *options, + isc_boolean_t *field, + isc_boolean_t *result, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber); +static isc_result_t cfg_get_ipmatchlist(dns_c_options_t *options, + dns_c_ipmatchlist_t *field, + dns_c_ipmatchlist_t **resval); +static isc_result_t cfg_get_iplist(dns_c_options_t *options, + dns_c_iplist_t *field, + dns_c_iplist_t **resval); +static isc_result_t acl_init(dns_c_ctx_t *cfg); +static isc_result_t logging_init (dns_c_ctx_t *cfg); +static isc_result_t make_options(dns_c_ctx_t *cfg); + + + +isc_result_t +dns_c_checkconfig(dns_c_ctx_t *ctx) +{ + isc_boolean_t bval; + char *cpval; + dns_severity_t severity; + isc_int32_t intval; + dns_c_ipmatchlist_t *ipml; + + if (dns_c_ctx_getnamedxfer(ctx, &cpval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "named-xfer is now obsolete"); + } + + + if (dns_c_ctx_getdumpfilename(ctx, &cpval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "dump-file is not yet implemented."); + } + + + if (dns_c_ctx_getmemstatsfilename(ctx, &cpval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "memstatistics-file is not yet implemented."); + } + + + if ((dns_c_ctx_getauthnxdomain(ctx, &bval)) == ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "the default for auth-nxdomain is now ``no''"); + } + + + if (dns_c_ctx_getdealloconexit(ctx, &bval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "deallocate-on-exit is obsolete."); + } + + + if (dns_c_ctx_getfakeiquery(ctx, &bval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "fake-iquery is obsolete."); + } + + + if (dns_c_ctx_getfetchglue(ctx, &bval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "fetch-glue is not yet implemented."); + } + + + if (dns_c_ctx_gethasoldclients(ctx, &bval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "has-old-clients is obsolete."); + } + + + if (dns_c_ctx_gethoststatistics(ctx, &bval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "host-statistics is not yet implemented."); + } + + + if (dns_c_ctx_getmultiplecnames(ctx, &bval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "multiple-cnames is obsolete."); + } + + + if (dns_c_ctx_getuseidpool(ctx, &bval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "use-id-pool is obsolete."); + } + + + if ((dns_c_ctx_getchecknames(ctx, dns_trans_primary, + &severity) != ISC_R_NOTFOUND) || + (dns_c_ctx_getchecknames(ctx, dns_trans_secondary, + &severity) != ISC_R_NOTFOUND) || + (dns_c_ctx_getchecknames(ctx, dns_trans_response, + &severity) != ISC_R_NOTFOUND)) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "check-names are not yet implemented."); + } + + + if (dns_c_ctx_getmaxlogsizeixfr(ctx, &intval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "max-ixfr-log-size is not yet implemented."); + } + + + if (dns_c_ctx_getstatsinterval(ctx, &intval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "statistics-interval is not yet implemented."); + } + + + if (dns_c_ctx_gettopology(ctx, &ipml) != ISC_R_NOTFOUND) { + dns_c_ipmatchlist_detach(&ipml); + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "topology is not yet implemented."); + } + + if (dns_c_ctx_getsortlist(ctx, &ipml) != ISC_R_NOTFOUND) { + dns_c_ipmatchlist_detach(&ipml); + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "sortlist is not yet implemented."); + } + + + if (dns_c_ctx_getrfc2308type1(ctx, &bval) != ISC_R_NOTFOUND) { + isc_log_write(dns_lctx,DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, + "rfc2308-type-1 is not yet implemented."); + } + + + + /* + named-xfer obsolete + dump-file not yet implemented + memstatistics-file not yet implemented + auth-nxdomain default changed (to "no") + deallocate-on-exit obsolete (always "yes") + fake-iquery obsolete (always "no") + fetch-glue not yet implemented (always "no") + has-old-clients obsolete (always "no") + host-statistics not yet implemented + multiple-cnames obsolete (always "no") + use-id-pool obosolete (always "yes") + maintain-ixfr-base obosolete (always "yes") + check-names not yet implemented + max-ixfr-log-size not yet implemented + statistics-interval not yet implemented + topology not yet implemented + sortlist not yet implemented + */ + + + return (ISC_R_SUCCESS); +} + + +/* ************************************************************************ */ + +isc_result_t +dns_c_ctx_new(isc_mem_t *mem, dns_c_ctx_t **ctx) +{ + dns_c_ctx_t *cfg; + isc_result_t r; + + REQUIRE(mem != NULL); + + cfg = isc_mem_get(mem, sizeof *cfg); + if (cfg == NULL) { + return (ISC_R_NOMEMORY); + } + + cfg->magic = DNS_C_CONFIG_MAGIC; + cfg->mem = mem; + cfg->warnings = 0; + cfg->errors = 0; + cfg->acls = NULL; + cfg->options = NULL; + cfg->zlist = NULL; + cfg->servers = NULL; + cfg->acls = NULL; + cfg->keydefs = NULL; + cfg->trusted_keys = NULL; + cfg->logging = NULL; + cfg->resolver = NULL; + cfg->cache = NULL; + cfg->views = NULL; + + cfg->currview = NULL; + cfg->currzone = NULL; + + r = acl_init(cfg); + if (r != ISC_R_SUCCESS) { + return (r); + } + + r = logging_init(cfg); + if (r != ISC_R_SUCCESS) { + return (r); + } + + +#if 1 /* XXX brister */ + cfg->controls = NULL; +#else + r = dns_c_ctrllist_new(mem, &cfg->controls); + if (r != ISC_R_SUCCESS) { + dns_c_ctx_delete(&cfg); + return r; + } +#endif + + *ctx = cfg; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_delete(dns_c_ctx_t **cfg) +{ + dns_c_ctx_t *c; + + REQUIRE(cfg != NULL); + REQUIRE(*cfg != NULL); + REQUIRE(DNS_C_CONFCTX_VALID(*cfg)); + + c = *cfg; + + REQUIRE(c->mem != NULL); + + if (c->options != NULL) + dns_c_ctx_optionsdelete(&c->options); + + if (c->controls != NULL) + dns_c_ctrllist_delete(&c->controls); + + if (c->servers != NULL) + dns_c_srvlist_delete(&c->servers); + + if (c->acls != NULL) + dns_c_acltable_delete(&c->acls); + + if (c->keydefs != NULL) + dns_c_kdeflist_delete(&c->keydefs); + + if (c->zlist != NULL) + dns_c_zonelist_delete(&c->zlist); + + if (c->trusted_keys != NULL) + dns_c_tkeylist_delete(&c->trusted_keys); + + if (c->logging != NULL) + dns_c_logginglist_delete(&c->logging); + + if (c->views != NULL) + dns_c_viewtable_delete(&c->views); + + c->magic = 0; + isc_mem_put(c->mem, c, sizeof *c); + *cfg = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_setcontrols(dns_c_ctx_t *cfg, dns_c_ctrllist_t *ctrls) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(DNS_C_CONFCTLLIST_VALID(ctrls)); + + if (cfg->controls != NULL) { + existed = ISC_TRUE; + dns_c_ctrllist_delete(&cfg->controls); + } + + cfg->controls = ctrls; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + +isc_result_t +dns_c_ctx_getcontrols(dns_c_ctx_t *cfg, dns_c_ctrllist_t **ctrls) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + *ctrls = cfg->controls; + + return (cfg->controls != NULL ? ISC_R_SUCCESS : ISC_R_NOTFOUND); +} + + + + +isc_result_t +dns_c_ctx_setcurrzone(dns_c_ctx_t *cfg, dns_c_zone_t *zone) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + cfg->currzone = zone; /* zone may be NULL */ + + /* XXX should we validate that the zone is in our table? */ + + return (ISC_R_SUCCESS); +} + + + +dns_c_zone_t * +dns_c_ctx_getcurrzone(dns_c_ctx_t *cfg) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + return (cfg->currzone); +} + + + +isc_result_t +dns_c_ctx_setcurrview(dns_c_ctx_t *cfg, + dns_c_view_t *view) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + cfg->currview = view; + + /* XXX should we validate that the zone is in our table? */ + + return (ISC_R_SUCCESS); +} + + + +dns_c_view_t * +dns_c_ctx_getcurrview(dns_c_ctx_t *cfg) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + return (cfg->currview); +} + + + +void +dns_c_ctx_print(FILE *fp, int indent, dns_c_ctx_t *cfg) +{ + REQUIRE(fp != NULL); + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->logging != NULL) { + dns_c_logginglist_print(fp, indent, + cfg->logging, ISC_FALSE); + fprintf(fp,"\n"); + } + + + if (cfg->keydefs != NULL) { + dns_c_kdeflist_print(fp, indent, cfg->keydefs); + fprintf(fp, "\n"); + } + + + if (cfg->trusted_keys != NULL) { + dns_c_tkeylist_print(fp, indent, cfg->trusted_keys); + fprintf(fp, "\n"); + } + + + if (cfg->acls != NULL) { + dns_c_acltable_print(fp, indent, cfg->acls); + fprintf(fp,"\n"); + } + + + if (cfg->zlist != NULL) { + dns_c_zonelist_printpreopts(fp, indent, cfg->zlist); + fprintf(fp, "\n"); + } + + + if (cfg->options != NULL) { + dns_c_ctx_optionsprint(fp, indent, cfg->options); + fprintf(fp,"\n"); + } + + + if (cfg->views != NULL) { + dns_c_viewtable_print(fp, indent, cfg->views); + fprintf(fp, "\n"); + } + + + if (cfg->zlist != NULL) { + dns_c_zonelist_printpostopts(fp, indent, cfg->zlist); + fprintf(fp, "\n"); + } + + if (cfg->controls != NULL) { + dns_c_ctrllist_print(fp, indent, cfg->controls); + fprintf(fp, "\n"); + } + + + if (cfg->servers != NULL) { + dns_c_srvlist_print(fp, indent, cfg->servers); + fprintf(fp, "\n"); + } +} + + +void +dns_c_ctx_forwarderprint(FILE *fp, int indent, dns_c_options_t *options) +{ + REQUIRE(fp != NULL); + REQUIRE(indent >= 0); + + if (options == NULL) { + return; + } + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + + if (DNS_C_CHECKBIT(FORWARD_BIT, &options->setflags1)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "forward %s;\n", + dns_c_forward2string(options->forward, ISC_TRUE)); + } + + if (options->forwarders != NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, "forwarders "); + dns_c_iplist_print(fp, indent + 1, + options->forwarders); + fprintf(fp, ";\n"); + } +} + + +isc_result_t +dns_c_ctx_getoptions(dns_c_ctx_t *cfg, dns_c_options_t **options) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(options != NULL); + + if (cfg->options != NULL) { + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + } + + *options = cfg->options; + + return (cfg->options == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + + +isc_result_t +dns_c_ctx_getlogging(dns_c_ctx_t *cfg, dns_c_logginglist_t **retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + *retval = cfg->logging; + + return (cfg->logging == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_setlogging(dns_c_ctx_t *cfg, dns_c_logginglist_t *newval, + isc_boolean_t deepcopy) +{ + dns_c_logginglist_t *ll; + isc_result_t res; + isc_boolean_t existed; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + existed = ISC_TF(cfg->logging != NULL); + + if (deepcopy) { + res = dns_c_logginglist_copy(cfg->mem, &ll, newval); + if (res != ISC_R_SUCCESS) { + return (res); + } + } else { + ll = newval; + } + + cfg->logging = ll; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_getkdeflist(dns_c_ctx_t *cfg, + dns_c_kdeflist_t **retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + *retval = cfg->keydefs; + + if (cfg->keydefs == NULL) { + return (ISC_R_NOTFOUND); + } else { + return (ISC_R_SUCCESS); + } +} + + +isc_result_t +dns_c_ctx_setkdeflist(dns_c_ctx_t *cfg, + dns_c_kdeflist_t *newval, isc_boolean_t deepcopy) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->keydefs != NULL) { + dns_c_kdeflist_delete(&cfg->keydefs); + } + + if (newval == NULL) { + cfg->keydefs = NULL; + res = ISC_R_SUCCESS; + } else if (deepcopy) { + res = dns_c_kdeflist_copy(cfg->mem, + &cfg->keydefs, newval); + } else { + cfg->keydefs = newval; + res = ISC_R_SUCCESS; + } + + return (res); +} + + +isc_result_t +dns_c_ctx_addfile_channel(dns_c_ctx_t *cfg, const char *name, + dns_c_logchan_t **chan) +{ + dns_c_logchan_t *newc; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(name != NULL); + REQUIRE(chan != NULL); + REQUIRE(cfg->logging != NULL); + + res = dns_c_logchan_new(cfg->mem, name, dns_c_logchan_file, + &newc); + if (res != ISC_R_SUCCESS) { + return (res); + } + + res = dns_c_logginglist_addchannel(cfg->logging, newc, + ISC_FALSE); + + *chan = newc; + + return (res); +} + + +isc_result_t +dns_c_ctx_addsyslogchannel(dns_c_ctx_t *cfg, const char *name, + dns_c_logchan_t **chan) +{ + dns_c_logchan_t *newc; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(name != NULL); + REQUIRE(chan != NULL); + REQUIRE(cfg->logging != NULL); + + res = dns_c_logchan_new(cfg->mem, name, + dns_c_logchan_syslog, &newc); + if (res != ISC_R_SUCCESS) { + return (res); + } + + res = dns_c_logginglist_addchannel(cfg->logging, newc, + ISC_FALSE); + + *chan = newc; + + return (res); +} + + +isc_result_t +dns_c_ctx_addnullchannel(dns_c_ctx_t *cfg, const char *name, + dns_c_logchan_t **chan) +{ + dns_c_logchan_t *newc; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(name != NULL); + REQUIRE(chan != NULL); + REQUIRE(cfg->logging != NULL); + + res = dns_c_logchan_new(cfg->mem, name, dns_c_logchan_null, + &newc); + if (res != ISC_R_SUCCESS) { + return (res); + } + + res = dns_c_logginglist_addchannel(cfg->logging, newc, + ISC_FALSE); + + *chan = newc; + + return (res); +} + + +isc_result_t +dns_c_ctx_addcategory(dns_c_ctx_t *cfg, dns_c_category_t category, + dns_c_logcat_t **newcat) +{ + dns_c_logcat_t *newc; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(newcat != NULL); + REQUIRE(cfg->logging != NULL); + + res = dns_c_logcat_new(cfg->mem, category, &newc); + if (res != ISC_R_SUCCESS) { + return (res); + } + + res = dns_c_logginglist_addcategory(cfg->logging, newc, + ISC_FALSE); + + *newcat = newc; + + return (res); +} + + +isc_result_t +dns_c_ctx_currchannel(dns_c_ctx_t *cfg, dns_c_logchan_t **channel) +{ + dns_c_logchan_t *newc; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(channel != NULL); + REQUIRE(cfg->logging != NULL); + + newc = ISC_LIST_TAIL(cfg->logging->channels); + + *channel = newc; + + return (newc == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_boolean_t +dns_c_ctx_channeldefinedp(dns_c_ctx_t *cfg, const char *name) +{ + isc_result_t res; + dns_c_logchan_t *chan; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + + res = dns_c_logginglist_chanbyname(cfg->logging, name, &chan); + + return (ISC_TF(res == ISC_R_SUCCESS)); +} + + + +isc_result_t +dns_c_ctx_currcategory(dns_c_ctx_t *cfg, dns_c_logcat_t **category) +{ + dns_c_logcat_t *newc; + dns_c_logginglist_t *llist; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(category != NULL); + + res = dns_c_ctx_getlogging(cfg, &llist); + if (res != ISC_R_SUCCESS) { + return (res); + } + + newc = ISC_LIST_TAIL(llist->categories); + + *category = newc; + + return (newc == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +/* + * Modifiers for options. + * + */ + + +isc_result_t +dns_c_ctx_setdirectory(dns_c_ctx_t *cfg, const char *newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_string(cfg->options, + &cfg->options->directory, + newval)); +} + + +isc_result_t +dns_c_ctx_setversion(dns_c_ctx_t *cfg, const char *newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_string(cfg->options, + &cfg->options->version, + newval)); +} + + +isc_result_t +dns_c_ctx_setdumpfilename(dns_c_ctx_t *cfg, const char *newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_string(cfg->options, + &cfg->options->dump_filename, + newval)); +} + + +isc_result_t +dns_c_ctx_setpidfilename(dns_c_ctx_t *cfg, const char *newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_string(cfg->options, + &cfg->options->pid_filename, + newval)); +} + + +isc_result_t +dns_c_ctx_setstatsfilename(dns_c_ctx_t *cfg, const char *newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_string(cfg->options, + &cfg->options->stats_filename, + newval)); +} + + +isc_result_t +dns_c_ctx_setmemstatsfilename(dns_c_ctx_t *cfg, const char *newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_string(cfg->options, + &cfg->options->memstats_filename, + newval)); +} + + +isc_result_t +dns_c_ctx_setnamedxfer(dns_c_ctx_t *cfg, const char *newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_string(cfg->options, + &cfg->options->named_xfer, + newval)); +} + + +isc_result_t +dns_c_ctx_settkeydomain(dns_c_ctx_t *cfg, const char *newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_string(cfg->options, + &cfg->options->tkeydomain, + newval)); +} + + +isc_result_t +dns_c_ctx_settkeydhkey(dns_c_ctx_t *cfg, + const char *charval, isc_int32_t intval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + cfg->options->tkeydhkeyi = intval; + return (cfg_set_string(cfg->options, + &cfg->options->tkeydhkeycp, + charval)); +} + + +isc_result_t +dns_c_ctx_setmaxncachettl(dns_c_ctx_t *cfg, isc_uint32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_uint32(cfg->options, + &cfg->options->max_ncache_ttl, + newval, + &cfg->options->setflags1, + MAX_NCACHE_TTL_BIT)); +} + + +isc_result_t +dns_c_ctx_settransfersin(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->transfers_in, + newval, + &cfg->options->setflags1, + TRANSFERS_IN_BIT)); +} + + +isc_result_t +dns_c_ctx_settransfersperns(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->transfers_per_ns, + newval, + &cfg->options->setflags1, + TRANSFERS_PER_NS_BIT)); +} + + +isc_result_t +dns_c_ctx_settransfersout(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->transfers_out, + newval, + &cfg->options->setflags1, + TRANSFERS_OUT_BIT)); +} + + +isc_result_t +dns_c_ctx_setmaxlogsizeixfr(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->max_log_size_ixfr, + newval, + &cfg->options->setflags1, + MAX_LOG_SIZE_IXFR_BIT)); +} + + +isc_result_t +dns_c_ctx_setcleaninterval(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->clean_interval, + newval, + &cfg->options->setflags1, + CLEAN_INTERVAL_BIT)); +} + + +isc_result_t +dns_c_ctx_setinterfaceinterval(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->interface_interval, + newval, + &cfg->options->setflags1, + INTERFACE_INTERVAL_BIT)); +} + + +isc_result_t +dns_c_ctx_setstatsinterval(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->stats_interval, + newval, + &cfg->options->setflags1, + STATS_INTERVAL_BIT)); +} + + +isc_result_t +dns_c_ctx_setheartbeat_interval(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->heartbeat_interval, + newval, + &cfg->options->setflags1, + HEARTBEAT_INTERVAL_BIT)); +} + + +isc_result_t +dns_c_ctx_setmaxtransfertimein(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->max_transfer_time_in, + newval, + &cfg->options->setflags1, + MAX_TRANSFER_TIME_IN_BIT)); +} + + +isc_result_t +dns_c_ctx_setmaxtransfertimeout(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->max_transfer_time_out, + newval, + &cfg->options->setflags1, + MAX_TRANSFER_TIME_OUT_BIT)); +} + + +isc_result_t +dns_c_ctx_setmaxtransferidlein(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->max_transfer_idle_in, + newval, + &cfg->options->setflags1, + MAX_TRANSFER_IDLE_IN_BIT)); +} + + +isc_result_t +dns_c_ctx_setmaxtransferidleout(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->max_transfer_idle_out, + newval, + &cfg->options->setflags1, + MAX_TRANSFER_IDLE_OUT_BIT)); +} + + +isc_result_t +dns_c_ctx_settcpclients(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->tcp_clients, + newval, + &cfg->options->setflags1, + TCP_CLIENTS_BIT)); +} + +isc_result_t +dns_c_ctx_setrecursiveclients(dns_c_ctx_t *cfg, isc_int32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_int32(cfg->options, + &cfg->options->recursive_clients, + newval, + &cfg->options->setflags1, + RECURSIVE_CLIENTS_BIT)); +} + + +isc_result_t +dns_c_ctx_setdatasize(dns_c_ctx_t *cfg, isc_uint32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_uint32(cfg->options, + &cfg->options->data_size, + newval, + &cfg->options->setflags1, + DATA_SIZE_BIT)); +} + + +isc_result_t +dns_c_ctx_setstacksize(dns_c_ctx_t *cfg, isc_uint32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_uint32(cfg->options, + &cfg->options->stack_size, + newval, + &cfg->options->setflags1, + STACK_SIZE_BIT)); +} + + +isc_result_t +dns_c_ctx_setcoresize(dns_c_ctx_t *cfg, isc_uint32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_uint32(cfg->options, + &cfg->options->core_size, + newval, + &cfg->options->setflags1, + CORE_SIZE_BIT)); +} + + +isc_result_t +dns_c_ctx_setfiles(dns_c_ctx_t *cfg, isc_uint32_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_uint32(cfg->options, + &cfg->options->files, + newval, + &cfg->options->setflags1, + FILES_BIT)); +} + + +isc_result_t +dns_c_ctx_setexpertmode(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->expert_mode, + newval, + &cfg->options->setflags1, + EXPERT_MODE_BIT)); +} + + +isc_result_t +dns_c_ctx_setfakeiquery(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->fake_iquery, + newval, + &cfg->options->setflags1, + FAKE_IQUERY_BIT)); +} + + +isc_result_t +dns_c_ctx_setrecursion(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->recursion, + newval, + &cfg->options->setflags1, + RECURSION_BIT)); +} + + +isc_result_t +dns_c_ctx_setfetchglue(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->fetch_glue, + newval, + &cfg->options->setflags1, + FETCH_GLUE_BIT)); +} + + +isc_result_t +dns_c_ctx_setnotify(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->notify, + newval, + &cfg->options->setflags1, + NOTIFY_BIT)); +} + + +isc_result_t +dns_c_ctx_sethoststatistics(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->host_statistics, + newval, + &cfg->options->setflags1, + HOST_STATISTICS_BIT)); +} + + +isc_result_t +dns_c_ctx_setdealloconexit(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->dealloc_on_exit, + newval, + &cfg->options->setflags1, + DEALLOC_ON_EXIT_BIT)); +} + + +isc_result_t +dns_c_ctx_setuseixfr(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->use_ixfr, + newval, + &cfg->options->setflags1, + USE_IXFR_BIT)); +} + + +isc_result_t +dns_c_ctx_setmaintainixfrbase(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->maintain_ixfr_base, + newval, + &cfg->options->setflags1, + MAINTAIN_IXFR_BASE_BIT)); +} + + +isc_result_t +dns_c_ctx_sethasoldclients(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->has_old_clients, + newval, + &cfg->options->setflags1, + HAS_OLD_CLIENTS_BIT)); +} + + +isc_result_t +dns_c_ctx_setauthnxdomain(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->auth_nx_domain, + newval, + &cfg->options->setflags1, + AUTH_NX_DOMAIN_BIT)); +} + + +isc_result_t +dns_c_ctx_setmultiplecnames(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->multiple_cnames, + newval, + &cfg->options->setflags1, + MULTIPLE_CNAMES_BIT)); +} + + +isc_result_t +dns_c_ctx_setuseidpool(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->use_id_pool, + newval, + &cfg->options->setflags1, + USE_ID_POOL_BIT)); +} + + +isc_result_t +dns_c_ctx_setrfc2308type1(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->rfc2308_type1, + newval, + &cfg->options->setflags1, + RFC2308_TYPE1_BIT)); +} + + +isc_result_t +dns_c_ctx_setdialup(dns_c_ctx_t *cfg, isc_boolean_t newval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + return (cfg_set_boolean(cfg->options, + &cfg->options->dialup, + newval, + &cfg->options->setflags1, + DIALUP_BIT)); +} + + +isc_result_t +dns_c_ctx_setquerysourceaddr(dns_c_ctx_t *cfg, isc_sockaddr_t addr) +{ + isc_boolean_t existed; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + existed = DNS_C_CHECKBIT(QUERY_SOURCE_ADDR_BIT, + &cfg->options->setflags1); + DNS_C_SETBIT(QUERY_SOURCE_ADDR_BIT, &cfg->options->setflags1); + + cfg->options->query_source_addr = addr; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_setquerysourceport(dns_c_ctx_t *cfg, in_port_t port) +{ + isc_boolean_t existed; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + existed = DNS_C_CHECKBIT(QUERY_SOURCE_PORT_BIT, + &cfg->options->setflags1); + DNS_C_SETBIT(QUERY_SOURCE_PORT_BIT, &cfg->options->setflags1); + + cfg->options->query_source_port = port; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_settransferformat(dns_c_ctx_t *cfg, + dns_transfer_format_t newval) +{ + isc_boolean_t existed; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + existed = DNS_C_CHECKBIT(OPTIONS_TRANSFER_FORMAT_BIT, + &cfg->options->setflags1); + DNS_C_SETBIT(OPTIONS_TRANSFER_FORMAT_BIT, &cfg->options->setflags1); + + cfg->options->transfer_format = newval; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_setchecknames(dns_c_ctx_t *cfg, + dns_c_trans_t transtype, + dns_severity_t sever) +{ + isc_boolean_t existed = ISC_FALSE; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + switch(transtype) { + case dns_trans_primary: + existed = DNS_C_CHECKBIT(CHECKNAME_PRIM_BIT, + &cfg->options->setflags1); + DNS_C_SETBIT(CHECKNAME_PRIM_BIT, &cfg->options->setflags1); + break; + + case dns_trans_secondary: + existed = DNS_C_CHECKBIT(CHECKNAME_SEC_BIT, + &cfg->options->setflags1); + DNS_C_SETBIT(CHECKNAME_SEC_BIT, &cfg->options->setflags1); + break; + + case dns_trans_response: + existed = DNS_C_CHECKBIT(CHECKNAME_RESP_BIT, + &cfg->options->setflags1); + DNS_C_SETBIT(CHECKNAME_RESP_BIT, &cfg->options->setflags1); + break; + + default: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "bad transport value: %d", transtype); + return (ISC_R_FAILURE); + } + + cfg->options->check_names[transtype] = sever; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_setqueryacl(dns_c_ctx_t *cfg, isc_boolean_t copy, + dns_c_ipmatchlist_t *iml) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + REQUIRE(iml != NULL); + + res = cfg_set_ipmatchlist(cfg->options, &cfg->options->queryacl, + iml, copy); + + return (res); +} + + +isc_result_t +dns_c_ctx_settransferacl(dns_c_ctx_t *cfg, isc_boolean_t copy, + dns_c_ipmatchlist_t *iml) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + REQUIRE(iml != NULL); + + res = cfg_set_ipmatchlist(cfg->options, &cfg->options->transferacl, + iml, copy); + + return (res); +} + + +isc_result_t +dns_c_ctx_setrecursionacl(dns_c_ctx_t *cfg, isc_boolean_t copy, + dns_c_ipmatchlist_t *iml) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + REQUIRE(iml != NULL); + + res = cfg_set_ipmatchlist(cfg->options, &cfg->options->recursionacl, + iml, copy); + + return (res); +} + + +isc_result_t +dns_c_ctx_setblackhole(dns_c_ctx_t *cfg, isc_boolean_t copy, + dns_c_ipmatchlist_t *iml) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + REQUIRE(iml != NULL); + + res = cfg_set_ipmatchlist(cfg->options, &cfg->options->blackhole, + iml, copy); + + return (res); +} + + +isc_result_t +dns_c_ctx_settopology(dns_c_ctx_t *cfg, isc_boolean_t copy, + dns_c_ipmatchlist_t *iml) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + REQUIRE(iml != NULL); + + res = cfg_set_ipmatchlist(cfg->options, &cfg->options->topology, + iml, copy); + + return (res); +} + + +isc_result_t +dns_c_ctx_setsortlist(dns_c_ctx_t *cfg, isc_boolean_t copy, + dns_c_ipmatchlist_t *iml) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + REQUIRE(iml != NULL); + + res = cfg_set_ipmatchlist(cfg->options, &cfg->options->sortlist, + iml, copy); + + return (res); +} + + +isc_result_t +dns_c_ctx_setforward(dns_c_ctx_t *cfg, dns_c_forw_t forw) +{ + isc_boolean_t existed; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + existed = DNS_C_CHECKBIT(FORWARD_BIT, &cfg->options->setflags1); + DNS_C_SETBIT(FORWARD_BIT, &cfg->options->setflags1); + + cfg->options->forward = forw; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_setforwarders(dns_c_ctx_t *cfg, isc_boolean_t copy, + dns_c_iplist_t *ipl) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + res = cfg_set_iplist(cfg->options, &cfg->options->forwarders, + ipl, copy); + + return (res); +} + + +isc_result_t +dns_c_ctx_setrrsetorderlist(dns_c_ctx_t *cfg, isc_boolean_t copy, + dns_c_rrsolist_t *olist) +{ + isc_boolean_t existed; + dns_c_options_t *opts; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + opts = cfg->options; + + existed = (opts->ordering == NULL ? ISC_FALSE : ISC_TRUE); + + if (copy) { + if (opts->ordering == NULL) { + res = dns_c_rrsolist_new(opts->mem, + &opts->ordering); + if (res != ISC_R_SUCCESS) { + return (res); + } + } else { + dns_c_rrsolist_clear(opts->ordering); + } + + res = dns_c_rrsolist_append(opts->ordering, olist); + } else { + if (opts->ordering != NULL) { + dns_c_rrsolist_delete(&opts->ordering); + } + + opts->ordering = olist; + res = ISC_R_SUCCESS; + } + + if (res == ISC_R_SUCCESS && existed) { + res = ISC_R_EXISTS; + } + + return (res); +} + + +isc_result_t +dns_c_ctx_addlisten_on(dns_c_ctx_t *cfg,int port, dns_c_ipmatchlist_t *ml, + isc_boolean_t copy) +{ + dns_c_lstnon_t *lo; + isc_result_t res; + dns_c_options_t *opts; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(port >= 0 && port <= 65535); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + opts = cfg->options; + + if (opts->listens == NULL) { + res = dns_c_lstnlist_new(cfg->mem, &opts->listens); + if (res != ISC_R_SUCCESS) { + return (res); + } + } + +#if 0 + lo = ISC_LIST_HEAD(opts->listens->elements); + while (lo != NULL) { + /* XXX we should probably check that a listen on statement + * hasn't been done for the same post, ipmatch list + * combination + */ + if (lo->port == port) { /* XXX incomplete */ + return (ISC_R_FAILURE); + } + lo = ISC_LIST_NEXT(lo, next); + } +#endif + + res = dns_c_lstnon_new(cfg->mem, &lo); + if (res != ISC_R_SUCCESS) { + return (res); + } + + lo->port = port; + res = dns_c_lstnon_setiml(lo, ml, copy); + + ISC_LIST_APPEND(opts->listens->elements, lo, next); + + return (res); +} + + +isc_result_t +dns_c_ctx_settrustedkeys(dns_c_ctx_t *cfg, dns_c_tkeylist_t *list, + isc_boolean_t copy) +{ + isc_boolean_t existed; + dns_c_tkeylist_t *newl; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + existed = (cfg->trusted_keys == NULL ? ISC_FALSE : ISC_TRUE); + + if (cfg->trusted_keys != NULL) { + res = dns_c_tkeylist_delete(&cfg->trusted_keys); + if (res != ISC_R_SUCCESS) { + return (res); + } + } + + if (copy) { + res = dns_c_tkeylist_copy(cfg->mem, &newl, list); + if (res != ISC_R_SUCCESS) { + return (res); + } + } else { + newl = list; + } + + cfg->trusted_keys = newl; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +/** + ** Accessors + **/ + +isc_result_t +dns_c_ctx_getdirectory(dns_c_ctx_t *cfg, char **retval) +{ + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + *retval = cfg->options->directory; + + return (*retval == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_getversion(dns_c_ctx_t *cfg, char **retval) +{ + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + *retval = cfg->options->version; + + return (*retval == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_getdumpfilename(dns_c_ctx_t *cfg, char **retval) +{ + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + *retval = cfg->options->dump_filename; + + return (*retval == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_getpidfilename(dns_c_ctx_t *cfg, char **retval) +{ + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + *retval = cfg->options->pid_filename; + + return (*retval == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_getstatsfilename(dns_c_ctx_t *cfg, char **retval) +{ + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + *retval = cfg->options->stats_filename; + + return (*retval == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_getmemstatsfilename(dns_c_ctx_t *cfg, char **retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + *retval = cfg->options->memstats_filename; + + return (*retval == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_getnamedxfer(dns_c_ctx_t *cfg, char **retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + *retval = cfg->options->named_xfer; + + return (*retval == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_gettkeydomain(dns_c_ctx_t *cfg, char **retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + *retval = cfg->options->tkeydomain; + + return (*retval == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_gettkeydhkey(dns_c_ctx_t *cfg, + char **charpval, isc_int32_t *intval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(charpval != NULL); + REQUIRE(intval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + if (cfg->options->tkeydhkeycp == NULL) { + res = ISC_R_NOTFOUND; + } else { + *charpval = cfg->options->tkeydhkeycp; + *intval = cfg->options->tkeydhkeyi; + res = ISC_R_SUCCESS; + } + + return (res); +} + + +isc_result_t +dns_c_ctx_getmaxncachettl(dns_c_ctx_t *cfg, isc_uint32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + return (cfg_get_uint32(cfg->options, + &cfg->options->max_ncache_ttl, + retval, + &cfg->options->setflags1, + MAX_NCACHE_TTL_BIT)); +} + + +isc_result_t +dns_c_ctx_gettransfersin(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + + return (cfg_get_int32(cfg->options, + &cfg->options->transfers_in, + retval, + &cfg->options->setflags1, + TRANSFERS_IN_BIT)); +} + + +isc_result_t +dns_c_ctx_gettransfersperns(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + return (cfg_get_int32(cfg->options, + &cfg->options->transfers_per_ns, + retval, + &cfg->options->setflags1, + TRANSFERS_PER_NS_BIT)); +} + + +isc_result_t +dns_c_ctx_gettransfersout(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + return (cfg_get_int32(cfg->options, + &cfg->options->transfers_out, + retval, + &cfg->options->setflags1, + TRANSFERS_OUT_BIT)); +} + + +isc_result_t +dns_c_ctx_getmaxlogsizeixfr(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + return (cfg_get_int32(cfg->options, + &cfg->options->max_log_size_ixfr, + retval, + &cfg->options->setflags1, + MAX_LOG_SIZE_IXFR_BIT)); +} + + +isc_result_t +dns_c_ctx_getcleaninterval(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + return (cfg_get_int32(cfg->options, + &cfg->options->clean_interval, + retval, + &cfg->options->setflags1, + CLEAN_INTERVAL_BIT)); +} + + +isc_result_t +dns_c_ctx_getinterfaceinterval(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_int32(cfg->options, + &cfg->options->interface_interval, + retval, + &cfg->options->setflags1, + INTERFACE_INTERVAL_BIT)); +} + + +isc_result_t +dns_c_ctx_getstatsinterval(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_int32(cfg->options, + &cfg->options->stats_interval, + retval, + &cfg->options->setflags1, + STATS_INTERVAL_BIT)); +} + + +isc_result_t +dns_c_ctx_getheartbeatinterval(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_int32(cfg->options, + &cfg->options->heartbeat_interval, + retval, + &cfg->options->setflags1, + HEARTBEAT_INTERVAL_BIT)); +} + + +isc_result_t +dns_c_ctx_getmaxtransfertimein(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_int32(cfg->options, + &cfg->options->max_transfer_time_in, + retval, + &cfg->options->setflags1, + MAX_TRANSFER_TIME_IN_BIT)); +} + + +isc_result_t +dns_c_ctx_getmaxtransfertimeout(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_int32(cfg->options, + &cfg->options->max_transfer_time_out, + retval, + &cfg->options->setflags1, + MAX_TRANSFER_TIME_OUT_BIT)); +} + + +isc_result_t +dns_c_ctx_getmaxtransferidlein(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_int32(cfg->options, + &cfg->options->max_transfer_idle_in, + retval, + &cfg->options->setflags1, + MAX_TRANSFER_IDLE_IN_BIT)); +} + + +isc_result_t +dns_c_ctx_getmaxtransferidleout(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_int32(cfg->options, + &cfg->options->max_transfer_idle_out, + retval, + &cfg->options->setflags1, + MAX_TRANSFER_IDLE_OUT_BIT)); +} + + +isc_result_t +dns_c_ctx_gettcpclients(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_int32(cfg->options, + &cfg->options->tcp_clients, + retval, + &cfg->options->setflags1, + TCP_CLIENTS_BIT)); +} + + +isc_result_t +dns_c_ctx_getrecursiveclients(dns_c_ctx_t *cfg, isc_int32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_int32(cfg->options, + &cfg->options->recursive_clients, + retval, + &cfg->options->setflags1, + RECURSIVE_CLIENTS_BIT)); +} + + +isc_result_t +dns_c_ctx_getdatasize(dns_c_ctx_t *cfg, isc_uint32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_uint32(cfg->options, + &cfg->options->data_size, + retval, + &cfg->options->setflags1, + DATA_SIZE_BIT)); +} + + +isc_result_t +dns_c_ctx_getstacksize(dns_c_ctx_t *cfg, isc_uint32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_uint32(cfg->options, + &cfg->options->stack_size, + retval, + &cfg->options->setflags1, + STACK_SIZE_BIT)); +} + + +isc_result_t +dns_c_ctx_getcoresize(dns_c_ctx_t *cfg, isc_uint32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_uint32(cfg->options, + &cfg->options->core_size, + retval, + &cfg->options->setflags1, + CORE_SIZE_BIT)); +} + + +isc_result_t +dns_c_ctx_getfiles(dns_c_ctx_t *cfg, isc_uint32_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_uint32(cfg->options, + &cfg->options->files, + retval, + &cfg->options->setflags1, + FILES_BIT)); +} + + +isc_result_t +dns_c_ctx_getexpertmode(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->expert_mode, + retval, + &cfg->options->setflags1, + EXPERT_MODE_BIT)); +} + + +isc_result_t +dns_c_ctx_getfakeiquery(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->fake_iquery, + retval, + &cfg->options->setflags1, + FAKE_IQUERY_BIT)); +} + + +isc_result_t +dns_c_ctx_getrecursion(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->recursion, + retval, + &cfg->options->setflags1, + RECURSION_BIT)); +} + + +isc_result_t +dns_c_ctx_getfetchglue(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->fetch_glue, + retval, + &cfg->options->setflags1, + FETCH_GLUE_BIT)); +} + + +isc_result_t +dns_c_ctx_getnotify(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->notify, + retval, + &cfg->options->setflags1, + NOTIFY_BIT)); +} + + +isc_result_t +dns_c_ctx_gethoststatistics(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->host_statistics, + retval, + &cfg->options->setflags1, + HOST_STATISTICS_BIT)); +} + + +isc_result_t +dns_c_ctx_getdealloconexit(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->dealloc_on_exit, + retval, + &cfg->options->setflags1, + DEALLOC_ON_EXIT_BIT)); +} + + +isc_result_t +dns_c_ctx_getuseixfr(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->use_ixfr, + retval, + &cfg->options->setflags1, + USE_IXFR_BIT)); +} + + +isc_result_t +dns_c_ctx_getmaintainixfrbase(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->maintain_ixfr_base, + retval, + &cfg->options->setflags1, + MAINTAIN_IXFR_BASE_BIT)); +} + + +isc_result_t +dns_c_ctx_gethasoldclients(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->has_old_clients, + retval, + &cfg->options->setflags1, + HAS_OLD_CLIENTS_BIT)); +} + + + +isc_result_t +dns_c_ctx_getauthnxdomain(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->auth_nx_domain, + retval, + &cfg->options->setflags1, + AUTH_NX_DOMAIN_BIT)); +} + + +isc_result_t +dns_c_ctx_getmultiplecnames(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->multiple_cnames, + retval, + &cfg->options->setflags1, + MULTIPLE_CNAMES_BIT)); +} + + +isc_result_t +dns_c_ctx_getuseidpool(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->use_id_pool, + retval, + &cfg->options->setflags1, + USE_ID_POOL_BIT)); +} + + +isc_result_t +dns_c_ctx_getrfc2308type1(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->rfc2308_type1, + retval, + &cfg->options->setflags1, + RFC2308_TYPE1_BIT)); +} + + +isc_result_t +dns_c_ctx_getdialup(dns_c_ctx_t *cfg, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + return (cfg_get_boolean(cfg->options, + &cfg->options->dialup, + retval, + &cfg->options->setflags1, + DIALUP_BIT)); +} + + +isc_result_t +dns_c_ctx_getquerysourceaddr(dns_c_ctx_t *cfg, isc_sockaddr_t *addr) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(addr != NULL); + + if (DNS_C_CHECKBIT(QUERY_SOURCE_ADDR_BIT, &cfg->options->setflags1)) { + *addr = cfg->options->query_source_addr; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_ctx_getquerysourceport(dns_c_ctx_t *cfg, in_port_t *port) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(port != NULL); + + if (DNS_C_CHECKBIT(QUERY_SOURCE_PORT_BIT, &cfg->options->setflags1)) { + *port = cfg->options->query_source_port; + return (ISC_R_SUCCESS); + } else { + return (ISC_R_NOTFOUND); + } +} + + +isc_result_t +dns_c_ctx_gettransferformat(dns_c_ctx_t *cfg, + dns_transfer_format_t *retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + + if (DNS_C_CHECKBIT(OPTIONS_TRANSFER_FORMAT_BIT, + &cfg->options->setflags1)) { + *retval = cfg->options->transfer_format; + return (ISC_R_SUCCESS); + } else { + return (ISC_R_NOTFOUND); + } +} + + +isc_result_t +dns_c_ctx_getchecknames(dns_c_ctx_t *cfg, + dns_c_trans_t transtype, + dns_severity_t *sever) +{ + isc_boolean_t isset = ISC_FALSE; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(sever != NULL); + + switch (transtype) { + case dns_trans_primary: + isset = DNS_C_CHECKBIT(CHECKNAME_PRIM_BIT, + &cfg->options->setflags1); + break; + + case dns_trans_secondary: + isset = DNS_C_CHECKBIT(CHECKNAME_SEC_BIT, + &cfg->options->setflags1); + break; + + case dns_trans_response: + isset = DNS_C_CHECKBIT(CHECKNAME_RESP_BIT, + &cfg->options->setflags1); + break; + + default: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "bad transport value: %d", transtype); + return (ISC_R_FAILURE); + } + + if (isset) { + *sever = cfg->options->check_names[transtype]; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_ctx_getqueryacl(dns_c_ctx_t *cfg, dns_c_ipmatchlist_t **list) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(list != NULL); + + return (cfg_get_ipmatchlist(cfg->options, cfg->options->queryacl, + list)); +} + + +isc_result_t +dns_c_ctx_gettransferacl(dns_c_ctx_t *cfg, dns_c_ipmatchlist_t **list) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(list != NULL); + + return (cfg_get_ipmatchlist(cfg->options, + cfg->options->transferacl, list)); +} + + +isc_result_t +dns_c_ctx_getrecursionacl(dns_c_ctx_t *cfg, dns_c_ipmatchlist_t **list) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(list != NULL); + + return (cfg_get_ipmatchlist(cfg->options, cfg->options->recursionacl, + list)); +} + + +isc_result_t +dns_c_ctx_getblackhole(dns_c_ctx_t *cfg, dns_c_ipmatchlist_t **list) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(list != NULL); + + return (cfg_get_ipmatchlist(cfg->options, + cfg->options->blackhole, list)); +} + + +isc_result_t +dns_c_ctx_gettopology(dns_c_ctx_t *cfg, dns_c_ipmatchlist_t **list) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(list != NULL); + + return (cfg_get_ipmatchlist(cfg->options, + cfg->options->topology, list)); +} + + +isc_result_t +dns_c_ctx_getsortlist(dns_c_ctx_t *cfg, dns_c_ipmatchlist_t **list) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(list != NULL); + + return (cfg_get_ipmatchlist(cfg->options, + cfg->options->sortlist, list)); +} + + +isc_result_t +dns_c_ctx_getlistenlist(dns_c_ctx_t *cfg, dns_c_lstnlist_t **ll) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(ll != NULL); + + *ll = NULL; + + if (cfg->options->listens != NULL) { + *ll = cfg->options->listens; + } + + return (*ll == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_getforward(dns_c_ctx_t *cfg, dns_c_forw_t *forw) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(forw != NULL); + + if (DNS_C_CHECKBIT(FORWARD_BIT, &cfg->options->setflags1)) { + return (ISC_R_NOTFOUND); + } else { + *forw = cfg->options->forward; + res = ISC_R_SUCCESS; + } + + return (res); +} + + +isc_result_t +dns_c_ctx_getforwarders(dns_c_ctx_t *cfg, dns_c_iplist_t **list) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(list != NULL); + + return (cfg_get_iplist(cfg->options, + cfg->options->forwarders, list)); +} + + +isc_result_t +dns_c_ctx_getrrsetorderlist(dns_c_ctx_t *cfg, dns_c_rrsolist_t **retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->options == NULL || cfg->options->ordering == NULL) { + return (ISC_R_NOTFOUND); + } else { + *retval = cfg->options->ordering; + return (ISC_R_SUCCESS); + } +} + + +isc_result_t +dns_c_ctx_gettrustedkeys(dns_c_ctx_t *cfg, dns_c_tkeylist_t **retval) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(retval != NULL); + + if (cfg->trusted_keys == NULL) { + return (ISC_R_NOTFOUND); + } else { + *retval = cfg->trusted_keys; + return (ISC_R_SUCCESS); + } +} + + + +isc_result_t +dns_c_ctx_optionsnew(isc_mem_t *mem, dns_c_options_t **options) +{ + int i; + dns_c_options_t *opts = NULL; + + REQUIRE(mem != NULL); + REQUIRE(options != NULL); + + *options = NULL; + + opts = isc_mem_get(mem, sizeof *opts); + if (opts == NULL) { + return (ISC_R_NOMEMORY); + } + + opts->directory = NULL; + opts->version = NULL; + opts->dump_filename = NULL; + opts->pid_filename = NULL; + opts->stats_filename = NULL; + opts->memstats_filename = NULL; + opts->named_xfer = NULL; + opts->tkeydomain = NULL; + opts->also_notify = NULL; + opts->tkeydhkeycp = NULL; + opts->tkeydhkeyi = 0; + + opts->mem = mem; + opts->magic = DNS_C_OPTION_MAGIC; + opts->flags = 0; + opts->max_ncache_ttl = 0; + + opts->transfers_in = 0; + opts->transfers_per_ns = 0; + opts->transfers_out = 0; + opts->max_log_size_ixfr = 0; + opts->clean_interval = 0; + opts->interface_interval = 0; + opts->stats_interval = 0; + opts->heartbeat_interval = 0; + + opts->fake_iquery = ISC_FALSE; + opts->recursion = ISC_FALSE; + opts->fetch_glue = ISC_FALSE; + opts->notify = ISC_FALSE; + opts->host_statistics = ISC_FALSE; + opts->dealloc_on_exit = ISC_FALSE; + opts->use_ixfr = ISC_FALSE; + opts->maintain_ixfr_base = ISC_FALSE; + opts->has_old_clients = ISC_FALSE; + opts->expert_mode = ISC_FALSE; + opts->auth_nx_domain = ISC_FALSE; + opts->multiple_cnames = ISC_FALSE; + opts->use_id_pool = ISC_FALSE; + opts->rfc2308_type1 = ISC_FALSE; + opts->dialup = ISC_FALSE; + + opts->tcp_clients = 0; + opts->recursive_clients = 0; + + opts->max_transfer_time_in = 0; + opts->max_transfer_time_out = 0; + opts->max_transfer_idle_in = 0; + opts->max_transfer_idle_out = 0; + + opts->data_size = 0; + opts->stack_size = 0; + opts->core_size = 0; + opts->files = 0; + + opts->transfer_format = dns_one_answer; + + for (i = 0 ; i < DNS_C_TRANSCOUNT ; i++) { + opts->check_names[i] = dns_severity_fail; + } + + opts->queryacl = NULL; + opts->transferacl = NULL; + opts->recursionacl = NULL; + opts->blackhole = NULL; + opts->topology = NULL; + opts->sortlist = NULL; + opts->listens = NULL; + opts->ordering = NULL; + + opts->forward = dns_c_forw_only; + opts->forwarders = NULL; + + memset(&opts->setflags1, 0x0, sizeof opts->setflags1); + + *options = opts; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_optionsdelete(dns_c_options_t **opts) +{ + dns_c_options_t *options; + isc_result_t r, result; + + REQUIRE(opts != NULL); + + options = *opts; + if (options == NULL) { + return (ISC_R_SUCCESS); + } + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + + if (options->directory != NULL) { + isc_mem_free(options->mem, options->directory); + } + + if (options->version != NULL) { + isc_mem_free(options->mem, options->version); + } + + if (options->dump_filename != NULL) { + isc_mem_free(options->mem, options->dump_filename); + } + + if (options->pid_filename != NULL) { + isc_mem_free(options->mem, options->pid_filename); + } + + if (options->stats_filename != NULL) { + isc_mem_free(options->mem, options->stats_filename); + } + + if (options->memstats_filename != NULL) { + isc_mem_free(options->mem, options->memstats_filename); + } + + if (options->named_xfer != NULL) { + isc_mem_free(options->mem, options->named_xfer); + } + + if (options->also_notify != NULL) { + dns_c_iplist_detach(&options->also_notify); + } + + if (options->tkeydomain != NULL) { + isc_mem_free(options->mem, options->tkeydomain); + } + + if (options->tkeydhkeycp != NULL) { + isc_mem_free(options->mem, options->tkeydhkeycp); + } + + result = ISC_R_SUCCESS; + + if (options->queryacl != NULL) { + r = dns_c_ipmatchlist_detach(&options->queryacl); + if (r != ISC_R_SUCCESS) + result = r; + } + + if (options->transferacl != NULL) { + r = dns_c_ipmatchlist_detach(&options->transferacl); + if (r != ISC_R_SUCCESS) + result = r; + } + + if (options->recursionacl != NULL) { + r = dns_c_ipmatchlist_detach(&options->recursionacl); + if (r != ISC_R_SUCCESS) + result = r; + } + + if (options->blackhole != NULL) { + r = dns_c_ipmatchlist_detach(&options->blackhole); + if (r != ISC_R_SUCCESS) + result = r; + } + + if (options->topology != NULL) { + r = dns_c_ipmatchlist_detach(&options->topology); + if (r != ISC_R_SUCCESS) + result = r; + } + + if (options->sortlist != NULL) { + r = dns_c_ipmatchlist_detach(&options->sortlist); + if (r != ISC_R_SUCCESS) + result = r; + } + + if (options->listens != NULL) { + r = dns_c_lstnlist_delete(&options->listens); + if (r != ISC_R_SUCCESS) + result = r; + } + + if (options->ordering != NULL) { + r = dns_c_rrsolist_delete(&options->ordering); + if (r != ISC_R_SUCCESS) + result = r; + } + + if (options->forwarders != NULL) { + r = dns_c_iplist_detach(&options->forwarders); + if (r != ISC_R_SUCCESS) + result = r; + } + + *opts = NULL; + options->magic = 0; + + isc_mem_put(options->mem, options, sizeof *options); + + return (result); +} + + +void +dns_c_ctx_optionsprint(FILE *fp, int indent, dns_c_options_t *options) +{ + dns_severity_t nameseverity; + + REQUIRE(fp != NULL); + + if (options == NULL) { + return; + } + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + +#define PRINT_INTEGER(field, bit, name, bitfield) \ + if (DNS_C_CHECKBIT(bit, &options->bitfield)) { \ + dns_c_printtabs(fp, indent + 1); \ + fprintf(fp, "%s %d;\n",name,(int)options->field); \ + } + +#define PRINT_AS_MINUTES(field, bit, name, bitfield) \ + if (DNS_C_CHECKBIT(bit, &options->bitfield)) { \ + dns_c_printtabs(fp, indent + 1); \ + fprintf(fp, "%s %lu;\n",name, \ + (unsigned long)options->field / 60); \ + } + +#define PRINT_AS_BOOLEAN(field, bit, name, bitfield) \ + if (DNS_C_CHECKBIT(bit, &options->bitfield)) { \ + dns_c_printtabs(fp, indent + 1); \ + fprintf(fp, "%s %s;\n",name, \ + (options->field ? "true" : "false")); \ + } + +#define PRINT_AS_SIZE_CLAUSE(field, bit, name, bitfield) \ + if (DNS_C_CHECKBIT(bit, &options->bitfield)) { \ + dns_c_printtabs(fp, indent + 1); \ + fprintf(fp, "%s ",name); \ + if (options->field == DNS_C_SIZE_SPEC_DEFAULT) { \ + fprintf(fp, "default"); \ + } else { \ + dns_c_printinunits(fp, options->field); \ + } \ + fprintf(fp, ";\n"); \ + } + +#define PRINT_CHAR_P(field, name) \ + if (options->field != NULL) { \ + dns_c_printtabs(fp, indent + 1); \ + fprintf(fp, "%s \"%s\";\n", name, options->field); \ + } + + + + dns_c_printtabs(fp, indent); + fprintf (fp, "options {\n"); + + PRINT_CHAR_P(version, "version"); + PRINT_CHAR_P(directory, "directory"); + PRINT_CHAR_P(dump_filename, "dump-file"); + PRINT_CHAR_P(pid_filename, "pid-file"); + PRINT_CHAR_P(stats_filename, "statistics-file"); + PRINT_CHAR_P(memstats_filename, "memstatistics-file"); + PRINT_CHAR_P(named_xfer, "named-xfer"); + PRINT_CHAR_P(tkeydomain, "tkey-domain"); + + if (options->tkeydhkeycp != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "tkey-dhkey \"%s\" %d ;\n", + options->tkeydhkeycp, options->tkeydhkeyi); + } + + PRINT_INTEGER(transfers_in, TRANSFERS_IN_BIT, + "transfers-in", setflags1); + PRINT_INTEGER(transfers_per_ns, TRANSFERS_PER_NS_BIT, + "transfers-per-ns", setflags1); + PRINT_INTEGER(transfers_out, TRANSFERS_OUT_BIT, + "transfers-out", setflags1); + PRINT_INTEGER(max_log_size_ixfr, MAX_LOG_SIZE_IXFR_BIT, + "max-ixfr-log-size", setflags1); + PRINT_INTEGER(tcp_clients, TCP_CLIENTS_BIT, + "tcp-clients", setflags1); + PRINT_INTEGER(recursive_clients, RECURSIVE_CLIENTS_BIT, + "recursive-clients", setflags1); + + + PRINT_INTEGER(max_ncache_ttl, MAX_NCACHE_TTL_BIT, + "max-ncache-ttl", setflags1); + + PRINT_AS_MINUTES(clean_interval, CLEAN_INTERVAL_BIT, + "cleaning-interval", setflags1); + PRINT_AS_MINUTES(interface_interval, INTERFACE_INTERVAL_BIT, + "interface-interval", setflags1); + PRINT_AS_MINUTES(stats_interval, STATS_INTERVAL_BIT, + "statistics-interval", setflags1); + PRINT_AS_MINUTES(heartbeat_interval, HEARTBEAT_INTERVAL_BIT, + "heartbeat-interval", setflags1); + PRINT_AS_MINUTES(max_transfer_time_in, MAX_TRANSFER_TIME_IN_BIT, + "max-transfer-time-in", setflags1); + PRINT_AS_MINUTES(max_transfer_time_out, MAX_TRANSFER_TIME_OUT_BIT, + "max-transfer-time-out", setflags1); + PRINT_AS_MINUTES(max_transfer_idle_in, MAX_TRANSFER_IDLE_IN_BIT, + "max-transfer-idle-in", setflags1); + PRINT_AS_MINUTES(max_transfer_idle_out, MAX_TRANSFER_IDLE_OUT_BIT, + "max-transfer-idle-out", setflags1); + + PRINT_AS_SIZE_CLAUSE(data_size, DATA_SIZE_BIT, "datasize", + setflags1); + PRINT_AS_SIZE_CLAUSE(stack_size, STACK_SIZE_BIT, "stacksize", + setflags1); + PRINT_AS_SIZE_CLAUSE(core_size, CORE_SIZE_BIT, "coresize", + setflags1); + PRINT_AS_SIZE_CLAUSE(files, FILES_BIT, "files", + setflags1); + + PRINT_AS_BOOLEAN(expert_mode, EXPERT_MODE_BIT, + "expert-mode", setflags1); + PRINT_AS_BOOLEAN(fake_iquery, FAKE_IQUERY_BIT, + "fake-iquery", setflags1); + PRINT_AS_BOOLEAN(recursion, RECURSION_BIT, + "recursion", setflags1); + PRINT_AS_BOOLEAN(fetch_glue, FETCH_GLUE_BIT, + "fetch-glue", setflags1); + PRINT_AS_BOOLEAN(notify, NOTIFY_BIT, + "notify", setflags1); + PRINT_AS_BOOLEAN(host_statistics, HOST_STATISTICS_BIT, + "host-statistics", setflags1); + PRINT_AS_BOOLEAN(dealloc_on_exit, DEALLOC_ON_EXIT_BIT, + "deallocate-on-exit", setflags1); + PRINT_AS_BOOLEAN(use_ixfr, USE_IXFR_BIT, + "use-ixfr", setflags1); + PRINT_AS_BOOLEAN(maintain_ixfr_base, MAINTAIN_IXFR_BASE_BIT, + "maintain-ixfr-base", setflags1); + PRINT_AS_BOOLEAN(has_old_clients, HAS_OLD_CLIENTS_BIT, + "has-old-clients", setflags1); + PRINT_AS_BOOLEAN(auth_nx_domain, AUTH_NX_DOMAIN_BIT, + "auth-nxdomain", setflags1); + PRINT_AS_BOOLEAN(multiple_cnames, MULTIPLE_CNAMES_BIT, + "multiple-cnames", setflags1); + PRINT_AS_BOOLEAN(use_id_pool, USE_ID_POOL_BIT, + "use-id-pool", setflags1); + PRINT_AS_BOOLEAN(rfc2308_type1, RFC2308_TYPE1_BIT, + "rfc2308-type1", setflags1); + PRINT_AS_BOOLEAN(dialup, DIALUP_BIT, + "dialup", setflags1); + +#undef PRINT_INTEGER +#undef PRINT_AS_MINUTES +#undef PRINT_AS_BOOLEAN +#undef PRINT_AS_SIZE_CLAUSE +#undef PRINT_CHAR_P + + + if (DNS_C_CHECKBIT(OPTIONS_TRANSFER_FORMAT_BIT, &options->setflags1)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "transfer-format %s;\n", + dns_c_transformat2string(options->transfer_format, + ISC_TRUE)); + } + + + if (DNS_C_CHECKBIT(QUERY_SOURCE_PORT_BIT, &options->setflags1) || + DNS_C_CHECKBIT(QUERY_SOURCE_ADDR_BIT, &options->setflags1)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "query-source "); + + if (DNS_C_CHECKBIT(QUERY_SOURCE_ADDR_BIT, + &options->setflags1)) { + fprintf(fp, "address "); + dns_c_print_ipaddr(fp, &options->query_source_addr); + } + + if (DNS_C_CHECKBIT(QUERY_SOURCE_PORT_BIT, + &options->setflags1)) { + if (options->query_source_port == 0) { + fprintf(fp, " port *"); + } else { + fprintf(fp, " port %d", + options->query_source_port); + } + } + fprintf(fp, " ;\n"); + } + + + if (DNS_C_CHECKBIT(CHECKNAME_PRIM_BIT, &options->setflags1)) { + nameseverity = options->check_names[dns_trans_primary]; + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "check-names %s %s;\n", + dns_c_transport2string(dns_trans_primary, + ISC_TRUE), + dns_c_nameseverity2string(nameseverity, + ISC_TRUE)); + } + + if (DNS_C_CHECKBIT(CHECKNAME_SEC_BIT, &options->setflags1)) { + nameseverity = options->check_names[dns_trans_secondary]; + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "check-names %s %s;\n", + dns_c_transport2string(dns_trans_secondary, + ISC_TRUE), + dns_c_nameseverity2string(nameseverity, + ISC_TRUE)); + } + + if (DNS_C_CHECKBIT(CHECKNAME_RESP_BIT, &options->setflags1)) { + nameseverity = options->check_names[dns_trans_response]; + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "check-names %s %s;\n", + dns_c_transport2string(dns_trans_response, + ISC_TRUE), + dns_c_nameseverity2string(nameseverity, + ISC_TRUE)); + } + + fprintf(fp, "\n"); + + if (options->queryacl != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "allow-query "); + dns_c_ipmatchlist_print(fp, 2, options->queryacl); + fprintf(fp, ";\n"); + } + + if (options->transferacl != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "allow-transfer "); + dns_c_ipmatchlist_print(fp, 2, options->transferacl); + fprintf(fp, ";\n"); + } + + if (options->recursionacl != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "allow-recursion "); + dns_c_ipmatchlist_print(fp, 2, options->recursionacl); + fprintf(fp, ";\n"); + } + + if (options->blackhole != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "blackhole "); + dns_c_ipmatchlist_print(fp, 2, options->blackhole); + fprintf(fp, ";\n"); + } + + if (options->topology != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "topology "); + dns_c_ipmatchlist_print(fp, 2, options->topology); + fprintf(fp, ";\n"); + } + + if (options->sortlist != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "sortlist "); + dns_c_ipmatchlist_print(fp, 2, options->sortlist); + fprintf(fp, ";\n"); + } + + if (options->listens != NULL) { + dns_c_lstnlist_print(fp, indent + 1, + options->listens); + } + + dns_c_ctx_forwarderprint(fp, indent + 1, options); + + if (options->ordering != NULL) { + dns_c_rrsolist_print(fp, indent + 1, options->ordering); + } + + if (options->also_notify != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "also-notify ") ; + dns_c_iplist_print(fp, indent + 2, options->also_notify); + fprintf(fp, ";\n"); + } + + if (DNS_C_CHECKBIT(TRANSFER_SOURCE_BIT, &options->setflags1)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "transfer-source "); + dns_c_print_ipaddr(fp, &options->transfer_source); + fprintf(fp, ";\n"); + } + + + dns_c_printtabs(fp, indent); + fprintf(fp,"};\n"); +} + + +isc_boolean_t +dns_c_ctx_keydefinedp(dns_c_ctx_t *ctx, const char *keyname) +{ + dns_c_kdef_t *keyid; + isc_result_t res; + isc_boolean_t rval = ISC_FALSE; + + REQUIRE(DNS_C_CONFCTX_VALID(ctx)); + REQUIRE(keyname != NULL); + REQUIRE(strlen(keyname) > 0); + + if (ctx->keydefs != NULL) { + res = dns_c_kdeflist_find(ctx->keydefs, keyname, &keyid); + if (res == ISC_R_SUCCESS) { + rval = ISC_TRUE; + } + } + + return rval; +} + + +isc_result_t +dns_c_ctx_setalsonotify(dns_c_ctx_t *cfg, + dns_c_iplist_t *iml, + isc_boolean_t copy) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + REQUIRE(iml != NULL); + + res = cfg_set_iplist(cfg->options, &cfg->options->also_notify, + iml, copy); + + return (res); +} + + +isc_result_t +dns_c_ctx_getalsonotify(dns_c_ctx_t *cfg, dns_c_iplist_t **ret) +{ + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(ret != NULL); + + return (cfg_get_iplist(cfg->options, cfg->options->also_notify, ret)); +} + + +isc_result_t +dns_c_ctx_settransfersource(dns_c_ctx_t *cfg, isc_sockaddr_t newval) +{ + isc_boolean_t existed; + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + res = make_options(cfg); + if (res != ISC_R_SUCCESS) { + return (res); + } + + existed = DNS_C_CHECKBIT(TRANSFER_SOURCE_BIT, + &cfg->options->setflags1); + DNS_C_SETBIT(TRANSFER_SOURCE_BIT, &cfg->options->setflags1); + + cfg->options->transfer_source = newval; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ctx_gettransfersource(dns_c_ctx_t *cfg, isc_sockaddr_t *retval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + return (ISC_R_NOTFOUND); + } + + REQUIRE(retval != NULL); + + if (DNS_C_CHECKBIT(TRANSFER_SOURCE_BIT, &cfg->options->setflags1)) { + *retval = cfg->options->transfer_source; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + + + +/***************************************************************************/ + + +static isc_result_t +cfg_set_string(dns_c_options_t *options, char **field, const char *newval) +{ + char *p; + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + REQUIRE(field != NULL); + + p = *field; + *field = NULL; + + if (p != NULL) { + existed = ISC_TRUE; + } + + if (newval == NULL) { + if (p != NULL) { + isc_mem_free(options->mem, p); + } + p = NULL; + } else if (p == NULL) { + p = isc_mem_strdup(options->mem, newval); + if (p == NULL) { + return (ISC_R_NOMEMORY); + } + } else if (strlen(p) >= strlen(newval)) { + strcpy(p, newval); + } else { + isc_mem_free(options->mem, p); + p = isc_mem_strdup(options->mem, newval); + if (p == NULL) { + return (ISC_R_NOMEMORY); + } + } + + *field = p; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +static isc_result_t +cfg_set_iplist(dns_c_options_t *options, + dns_c_iplist_t **fieldaddr, + dns_c_iplist_t *newval, + isc_boolean_t copy) +{ + isc_result_t res; + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + REQUIRE(fieldaddr != NULL); + + if (*fieldaddr != NULL) { + existed = ISC_TRUE; + } + + if (newval == NULL) { + res = dns_c_iplist_new(options->mem, + newval->size, + fieldaddr); + } else if (copy) { + if (*fieldaddr != NULL) { + dns_c_iplist_detach(fieldaddr); + } + + res = dns_c_iplist_copy(options->mem, fieldaddr, + newval); + } else { + if (*fieldaddr != NULL) { + res = dns_c_iplist_detach(fieldaddr); + if (res != ISC_R_SUCCESS) { + return (res); + } + } + + res = ISC_R_SUCCESS; + + *fieldaddr = newval; + } + + if (res == ISC_R_SUCCESS && existed) { + res = ISC_R_EXISTS; + } + + return (res); +} + + +static isc_result_t +cfg_set_ipmatchlist(dns_c_options_t *options, + dns_c_ipmatchlist_t **fieldaddr, + dns_c_ipmatchlist_t *newval, + isc_boolean_t copy) +{ + isc_result_t res; + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + REQUIRE(fieldaddr != NULL); + + if (*fieldaddr != NULL) { + existed = ISC_TRUE; + } + + if (newval == NULL) { + res = dns_c_ipmatchlist_new(options->mem, fieldaddr); + } else if (copy) { + if (*fieldaddr != NULL) { + res = dns_c_ipmatchlist_empty(*fieldaddr); + if (res == ISC_R_SUCCESS && newval != NULL) { + res = dns_c_ipmatchlist_append(*fieldaddr, + newval, + ISC_FALSE); + } + } else { + res = dns_c_ipmatchlist_copy(options->mem, + fieldaddr, newval); + } + } else { + if (*fieldaddr != NULL) { + res = dns_c_ipmatchlist_detach(fieldaddr); + if (res != ISC_R_SUCCESS) { + return (res); + } + } + + res = ISC_R_SUCCESS; + + *fieldaddr = newval; + } + + if (res == ISC_R_SUCCESS && existed) { + res = ISC_R_EXISTS; + } + + return (res); +} + + + +static isc_result_t +cfg_set_boolean(dns_c_options_t *options, + isc_boolean_t *fieldaddr, + isc_boolean_t newval, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + REQUIRE(setfield != NULL); + REQUIRE(fieldaddr != NULL); + REQUIRE(bitnumber < DNS_C_SETBITS_SIZE); + + *fieldaddr = newval; + + existed = DNS_C_CHECKBIT(bitnumber, setfield); + DNS_C_SETBIT(bitnumber, setfield); + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +static isc_result_t +cfg_set_int32(dns_c_options_t *options, + isc_int32_t *fieldaddr, + isc_int32_t newval, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + REQUIRE(setfield != NULL); + REQUIRE(fieldaddr != NULL); + REQUIRE(bitnumber < DNS_C_SETBITS_SIZE); + + *fieldaddr = newval; + + existed = DNS_C_CHECKBIT(bitnumber, setfield); + DNS_C_SETBIT(bitnumber, setfield); + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +static isc_result_t +cfg_set_uint32(dns_c_options_t *options, + isc_uint32_t *fieldaddr, + isc_uint32_t newval, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + REQUIRE(setfield != NULL); + REQUIRE(fieldaddr != NULL); + REQUIRE(bitnumber < DNS_C_SETBITS_SIZE); + + *fieldaddr = newval; + + existed = DNS_C_CHECKBIT(bitnumber, setfield); + DNS_C_SETBIT(bitnumber, setfield); + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +static isc_result_t +cfg_get_ipmatchlist(dns_c_options_t *options, + dns_c_ipmatchlist_t *field, + dns_c_ipmatchlist_t **resval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + REQUIRE(resval != NULL); + + if (field != NULL && !ISC_LIST_EMPTY(field->elements)) { + dns_c_ipmatchlist_attach(field, resval); + res = ISC_R_SUCCESS; + } else { + *resval = NULL; + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +static isc_result_t +cfg_get_iplist(dns_c_options_t *options, + dns_c_iplist_t *field, + dns_c_iplist_t **resval) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + REQUIRE(resval != NULL); + + if (field != NULL && field->nextidx != 0) { + dns_c_iplist_attach(field, resval); + res = ISC_R_SUCCESS; + } else { + *resval = NULL; + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +static isc_result_t +cfg_get_boolean(dns_c_options_t *options, + isc_boolean_t *field, + isc_boolean_t *result, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + REQUIRE(result != NULL); + REQUIRE(field != NULL); + REQUIRE(setfield != NULL); + REQUIRE(bitnumber < DNS_C_SETBITS_SIZE); + + if (DNS_C_CHECKBIT(bitnumber,setfield)) { + *result = *field; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +static isc_result_t +cfg_get_int32(dns_c_options_t *options, + isc_int32_t *field, + isc_int32_t *result, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + REQUIRE(result != NULL); + REQUIRE(field != NULL); + REQUIRE(setfield != NULL); + REQUIRE(bitnumber < DNS_C_SETBITS_SIZE); + + if (DNS_C_CHECKBIT(bitnumber,setfield)) { + *result = *field; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +static isc_result_t +cfg_get_uint32(dns_c_options_t *options, + isc_uint32_t *field, + isc_uint32_t *result, + dns_c_setbits_t *setfield, + isc_uint32_t bitnumber) +{ + isc_result_t res; + + REQUIRE(DNS_C_CONFOPT_VALID(options)); + REQUIRE(result != NULL); + REQUIRE(field != NULL); + REQUIRE(setfield != NULL); + REQUIRE(bitnumber < DNS_C_SETBITS_SIZE); + + if (DNS_C_CHECKBIT(bitnumber,setfield)) { + *result = *field; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +static isc_result_t +acl_init(dns_c_ctx_t *cfg) +{ + dns_c_ipmatchelement_t *ime; + dns_c_ipmatchlist_t *iml; + isc_sockaddr_t addr; + dns_c_acl_t *acl; + isc_result_t r; + static struct in_addr zeroaddr; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + isc_sockaddr_fromin(&addr, &zeroaddr, 0); + + r = dns_c_acltable_new(cfg->mem, &cfg->acls); + if (r != ISC_R_SUCCESS) return (r); + + + /* + * The ANY acl. + */ + r = dns_c_acl_new(cfg->acls, "any", ISC_TRUE, &acl); + if (r != ISC_R_SUCCESS) return (r); + + r = dns_c_ipmatchpattern_new(cfg->mem, &ime, addr, 0); + if (r != ISC_R_SUCCESS) return (r); + + r = dns_c_ipmatchlist_new(cfg->mem, &iml); + if (r != ISC_R_SUCCESS) return (r); + + ISC_LIST_APPEND(iml->elements, ime, next); + + dns_c_acl_setipml(acl, iml, ISC_FALSE); + iml = NULL; + + + /* + * The NONE acl + */ + + r = dns_c_acl_new(cfg->acls, "none", ISC_TRUE, &acl); + if (r != ISC_R_SUCCESS) return (r); + + r = dns_c_ipmatchpattern_new(cfg->mem, &ime, addr, 0); + if (r != ISC_R_SUCCESS) return (r); + + dns_c_ipmatch_negate(ime); + + r = dns_c_ipmatchlist_new(cfg->mem, &iml); + if (r != ISC_R_SUCCESS) return (r); + + ISC_LIST_APPEND(iml->elements, ime, next); + + dns_c_acl_setipml(acl, iml, ISC_FALSE); + iml = NULL; + + + /* + * The LOCALHOST acl + */ + r = dns_c_acl_new(cfg->acls, "localhost", ISC_TRUE, &acl); + if (r != ISC_R_SUCCESS) return (r); + + r = dns_c_ipmatchlocalhost_new(cfg->mem, &ime); + if (r != ISC_R_SUCCESS) return (r); + + r = dns_c_ipmatchlist_new(cfg->mem, &iml); + if (r != ISC_R_SUCCESS) return (r); + + ISC_LIST_APPEND(iml->elements, ime, next); + + dns_c_acl_setipml(acl, iml, ISC_FALSE); + iml = NULL; + + + /* + * The LOCALNETS acl + */ + r = dns_c_acl_new(cfg->acls, "localnets", ISC_TRUE, &acl); + if (r != ISC_R_SUCCESS) return (r); + + r = dns_c_ipmatchlocalnets_new(cfg->mem, &ime); + if (r != ISC_R_SUCCESS) return (r); + + r = dns_c_ipmatchlist_new(cfg->mem, &iml); + if (r != ISC_R_SUCCESS) return (r); + + ISC_LIST_APPEND(iml->elements, ime, next); + + dns_c_acl_setipml(acl, iml, ISC_FALSE); + iml = NULL; + + return (ISC_R_SUCCESS); +} + + + +static isc_result_t +logging_init (dns_c_ctx_t *cfg) +{ + isc_result_t res; + dns_c_logcat_t *cat; + dns_c_logchan_t *chan; + + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + REQUIRE(cfg->logging == NULL); + + res = dns_c_logginglist_new(cfg->mem, &cfg->logging); + if (res != ISC_R_SUCCESS) { + return (res); + } + + /* default_syslog channel */ + chan = NULL; + res = dns_c_ctx_addsyslogchannel(cfg, DNS_C_DEFAULT_SYSLOG, + &chan); + if (res != ISC_R_SUCCESS) { + return (res); + } + dns_c_logchan_setpredef(chan, ISC_TRUE); + dns_c_logchan_setfacility(chan, LOG_DAEMON); + dns_c_logchan_setseverity(chan, dns_c_log_info); + + + /* default_debug channel */ + chan = NULL; + res = dns_c_ctx_addfile_channel(cfg, DNS_C_DEFAULT_DEBUG, &chan); + if (res != ISC_R_SUCCESS) { + return (res); + } + dns_c_logchan_setpredef(chan, ISC_TRUE); + dns_c_logchan_setpath(chan, DNS_C_DEFAULT_DEBUG_PATH); + dns_c_logchan_setseverity(chan, dns_c_log_dynamic); + + + /* null channel */ + chan = NULL; + res = dns_c_ctx_addnullchannel(cfg, DNS_C_NULL, &chan); + dns_c_logchan_setpredef(chan, ISC_TRUE); + + + /* default_stderr channel */ + chan = NULL; + res = dns_c_ctx_addfile_channel(cfg, DNS_C_DEFAULT_STDERR, + &chan); + if (res != ISC_R_SUCCESS) { + return (res); + } + dns_c_logchan_setpredef(chan, ISC_TRUE); + dns_c_logchan_setpath(chan, DNS_C_STDERR_PATH); + dns_c_logchan_setseverity(chan, dns_c_log_info); + + + /* default category */ + cat = NULL; + res = dns_c_ctx_addcategory(cfg, dns_c_cat_default, &cat); + if (res != ISC_R_SUCCESS) { + return (res); + } + dns_c_logcat_setpredef(cat, ISC_TRUE); + dns_c_logcat_addname(cat, DNS_C_DEFAULT_SYSLOG); + dns_c_logcat_addname(cat, DNS_C_DEFAULT_DEBUG); + + + /* panic category */ + cat = NULL; + res = dns_c_ctx_addcategory(cfg, dns_c_cat_panic, &cat); + if (res != ISC_R_SUCCESS) { + return (res); + } + dns_c_logcat_setpredef(cat, ISC_TRUE); + dns_c_logcat_addname(cat, DNS_C_DEFAULT_SYSLOG); + dns_c_logcat_addname(cat, DNS_C_DEFAULT_DEBUG); + + + /* eventlib category */ + cat = NULL; + res = dns_c_ctx_addcategory(cfg, dns_c_cat_eventlib, &cat); + if (res != ISC_R_SUCCESS) { + return (res); + } + dns_c_logcat_setpredef(cat, ISC_TRUE); + dns_c_logcat_addname(cat, DNS_C_DEFAULT_DEBUG); + + + /* packet category */ + cat = NULL; + res = dns_c_ctx_addcategory(cfg, dns_c_cat_packet, &cat); + if (res != ISC_R_SUCCESS) { + return (res); + } + dns_c_logcat_setpredef(cat, ISC_TRUE); + dns_c_logcat_addname(cat, DNS_C_DEFAULT_DEBUG); + + return (ISC_R_SUCCESS); +} + + + +static isc_result_t +make_options(dns_c_ctx_t *cfg) +{ + isc_result_t res = ISC_R_SUCCESS; + REQUIRE(DNS_C_CONFCTX_VALID(cfg)); + + if (cfg->options == NULL) { + res = dns_c_ctx_optionsnew(cfg->mem, &cfg->options); + if (res != ISC_R_SUCCESS) { + return (res); + } + } + + REQUIRE(DNS_C_CONFOPT_VALID(cfg->options)); + + return (res); +} + + diff --git a/lib/dns/config/confip.c b/lib/dns/config/confip.c new file mode 100644 index 00000000..55d86001 --- /dev/null +++ b/lib/dns/config/confip.c @@ -0,0 +1,1044 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <string.h> + +#include <isc/assertions.h> +#include <isc/error.h> +#include <isc/magic.h> + +#include <dns/confip.h> +#include <dns/confcommon.h> +#include <dns/log.h> + +/* Flag for dns_c_ipmatch_element */ +#define DNS_C_IPMATCH_NEGATE 0x01 /* match means deny access */ + + +static isc_result_t checkmask(isc_sockaddr_t *address, isc_uint32_t bits); +static isc_result_t bits2v6mask(struct in6_addr *addr, isc_uint32_t bits); + +isc_result_t +dns_c_ipmatchelement_new(isc_mem_t *mem, dns_c_ipmatchelement_t **result) +{ + dns_c_ipmatchelement_t *ime ; + + REQUIRE(result != NULL); + + *result = NULL; + + ime = isc_mem_get(mem, sizeof *ime); + if (ime == NULL) { + return (ISC_R_NOMEMORY); + } + + ime->magic = DNS_C_IPMELEM_MAGIC; + ime->type = dns_c_ipmatch_none; + ime->flags = 0; + memset(&ime->u, 0x0, sizeof ime->u); + + ISC_LINK_INIT(ime, next); + + *result = ime; + + return (ISC_R_SUCCESS); +} + + +isc_boolean_t +dns_c_ipmatchelement_isneg(dns_c_ipmatchelement_t *elem) +{ + + REQUIRE(DNS_C_IPMELEM_VALID(elem)); + + return (ISC_TF((elem->flags & DNS_C_IPMATCH_NEGATE) == + DNS_C_IPMATCH_NEGATE)); +} + + +isc_result_t +dns_c_ipmatchelement_delete(isc_mem_t *mem, dns_c_ipmatchelement_t **ipme) +{ + dns_c_ipmatchelement_t *elem; + + REQUIRE(mem != NULL); + REQUIRE(ipme != NULL); + REQUIRE(*ipme != NULL); + + elem = *ipme; + + REQUIRE(DNS_C_IPMELEM_VALID(elem)); + + switch (elem->type) { + case dns_c_ipmatch_localhost: + case dns_c_ipmatch_localnets: + case dns_c_ipmatch_pattern: + /* nothing */ + break; + + case dns_c_ipmatch_indirect: + INSIST(elem->u.indirect.list != NULL); + + if (elem->u.indirect.list != NULL) + dns_c_ipmatchlist_detach(&elem->u.indirect.list); + + if (elem->u.indirect.refname.base != NULL) { + isc_mem_put(mem, elem->u.indirect.refname.base, + elem->u.indirect.refname.length); + } + break; + + case dns_c_ipmatch_key: + isc_mem_free(mem, elem->u.key ); + break; + + case dns_c_ipmatch_acl: + isc_mem_free(mem, elem->u.aclname); + break; + + case dns_c_ipmatch_none: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "dns_ipmath_none element type"); + return (ISC_R_FAILURE); + } + + elem->magic = 0; + isc_mem_put(mem, elem, sizeof *elem); + + *ipme = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ipmatchelement_copy(isc_mem_t *mem, + dns_c_ipmatchelement_t **dest, + dns_c_ipmatchelement_t *src) +{ + isc_result_t result; + dns_c_ipmatchelement_t *newel; + + REQUIRE(mem != NULL); + REQUIRE(dest != NULL); + REQUIRE(DNS_C_IPMELEM_VALID(src)); + + result = dns_c_ipmatchelement_new(mem, &newel); + if (result != ISC_R_SUCCESS) { + return (result); + } + + newel->type = src->type; + newel->flags = src->flags; + + switch(src->type) { + case dns_c_ipmatch_pattern: + newel->u.direct.address = src->u.direct.address; + newel->u.direct.mask = src->u.direct.mask; + break; + + case dns_c_ipmatch_indirect: + result = dns_c_ipmatchlist_copy(mem, + &newel->u.indirect.list, + src->u.indirect.list); + break; + + case dns_c_ipmatch_localhost: + break; + + case dns_c_ipmatch_localnets: + break; + + case dns_c_ipmatch_key: + newel->u.key = isc_mem_strdup(mem, src->u.key); + break; + + case dns_c_ipmatch_acl: + newel->u.aclname = isc_mem_strdup(mem, src->u.aclname); + break; + + case dns_c_ipmatch_none: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "ipmatch 'none' element type"); + return (ISC_R_FAILURE); + } + + *dest = newel; + + return (ISC_R_SUCCESS); +} + + + +isc_boolean_t +dns_c_ipmatchelement_equal(dns_c_ipmatchelement_t *e1, + dns_c_ipmatchelement_t *e2) +{ + REQUIRE(DNS_C_IPMELEM_VALID(e1)); + REQUIRE(DNS_C_IPMELEM_VALID(e2)); + + if ((e1->type != e2->type) || (e1->flags != e2->flags)) + return (ISC_FALSE); + + switch (e1->type) { + case dns_c_ipmatch_pattern: + if (e1->u.direct.mask != e2->u.direct.mask) + return (ISC_FALSE); + return (isc_sockaddr_equal(&e1->u.direct.address, + &e2->u.direct.address)); + + case dns_c_ipmatch_indirect: + return (dns_c_ipmatchlist_equal(e1->u.indirect.list, + e2->u.indirect.list)); + + case dns_c_ipmatch_localhost: + break; + + case dns_c_ipmatch_localnets: + break; + + case dns_c_ipmatch_key: + return (ISC_TF(strcmp(e1->u.key, e2->u.key) == 0)); + + case dns_c_ipmatch_acl: + return (ISC_TF(strcmp(e1->u.aclname, e2->u.aclname) == 0)); + + case dns_c_ipmatch_none: + break; + } + return (ISC_TRUE); +} + +isc_result_t +dns_c_ipmatchlocalhost_new(isc_mem_t *mem, dns_c_ipmatchelement_t **result) +{ + dns_c_ipmatchelement_t *ime = NULL; + isc_result_t res; + + REQUIRE(mem != NULL); + REQUIRE(result != NULL); + + *result = NULL; + + res = dns_c_ipmatchelement_new(mem, &ime); + if (res == ISC_R_SUCCESS) { + ime->type = dns_c_ipmatch_localhost; + } + + *result = ime; + + return (res); +} + + +isc_result_t +dns_c_ipmatchlocalnets_new(isc_mem_t *mem, + dns_c_ipmatchelement_t **result) +{ + dns_c_ipmatchelement_t *ime = NULL; + isc_result_t res; + + REQUIRE(mem != NULL); + REQUIRE(result != NULL); + + *result = NULL; + + res = dns_c_ipmatchelement_new(mem, &ime); + if (res == ISC_R_SUCCESS) { + ime->type = dns_c_ipmatch_localnets; + } + + *result = ime; + + return (res); +} + + +isc_result_t +dns_c_ipmatchindirect_new(isc_mem_t *mem, + dns_c_ipmatchelement_t **result, + dns_c_ipmatchlist_t *iml, + const char *name) +{ + dns_c_ipmatchelement_t *ime; + dns_c_ipmatchlist_t *iml_copy; + isc_result_t res; + + REQUIRE(mem != NULL); + REQUIRE(result != NULL); + REQUIRE(DNS_C_IPMLIST_VALID(iml)); + + *result = NULL; + + res = dns_c_ipmatchlist_copy(mem, &iml_copy, iml); + if (res != ISC_R_SUCCESS) { + return (res); + } + + res = dns_c_ipmatchelement_new(mem, &ime); + if (res == ISC_R_SUCCESS) { + ime->type = dns_c_ipmatch_indirect; + ime->u.indirect.list = iml_copy; + if (name != NULL) { + ime->u.indirect.refname.length = strlen(name) + 1; + ime->u.indirect.refname.base = + isc_mem_get(mem, + ime->u.indirect.refname.length); + RUNTIME_CHECK(ime->u.indirect.refname.base != NULL); + strcpy(ime->u.indirect.refname.base, name); + } + } else { + dns_c_ipmatchlist_detach(&iml_copy); + } + + *result = ime; + + return (res); +} + + +isc_result_t +dns_c_ipmatchpattern_new(isc_mem_t *mem, + dns_c_ipmatchelement_t **result, + isc_sockaddr_t address, + isc_uint32_t maskbits) +{ + dns_c_ipmatchelement_t *ime ; + isc_result_t res; + + REQUIRE(result != NULL); + REQUIRE(mem != NULL); + + *result = NULL; + + res = checkmask(&address, maskbits); + + if (res != ISC_R_SUCCESS) { + return (res); + } + + res = dns_c_ipmatchelement_new(mem, &ime); + if (res != ISC_R_SUCCESS) { + return (res); + } + + ime->type = dns_c_ipmatch_pattern; + ime->u.direct.address = address; + ime->u.direct.mask = maskbits; + + *result = ime; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ipmatchkey_new(isc_mem_t *mem, + dns_c_ipmatchelement_t **result, + const char *key) +{ + dns_c_ipmatchelement_t *ipme; + isc_result_t res; + + REQUIRE(result != NULL); + REQUIRE(mem != NULL); + REQUIRE(key != NULL); + + *result = NULL; + + res = dns_c_ipmatchelement_new(mem, &ipme); + if (res != ISC_R_SUCCESS) { + return (res); + } + + ipme->type = dns_c_ipmatch_key; + ipme->u.key = isc_mem_strdup(mem, key); + + *result = ipme; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ipmatch_aclnew(isc_mem_t *mem, + dns_c_ipmatchelement_t **result, + const char *aclname) +{ + dns_c_ipmatchelement_t *ipme; + isc_result_t res; + + REQUIRE(result != NULL); + REQUIRE(mem != NULL); + REQUIRE(aclname != NULL); + REQUIRE(strlen(aclname) > 0); + + *result = NULL; + + res = dns_c_ipmatchelement_new(mem, &ipme); + if (res != ISC_R_SUCCESS) { + return (res); + } + + ipme->type = dns_c_ipmatch_acl; + ipme->u.aclname = isc_mem_strdup(mem, aclname); + + *result = ipme; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ipmatch_negate(dns_c_ipmatchelement_t *ipe) +{ + REQUIRE(DNS_C_IPMELEM_VALID(ipe)); + + if ((ipe->flags & DNS_C_IPMATCH_NEGATE) == DNS_C_IPMATCH_NEGATE) { + ipe->flags &= ~DNS_C_IPMATCH_NEGATE; + } else { + ipe->flags |= DNS_C_IPMATCH_NEGATE; + } + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ipmatchlist_new(isc_mem_t *mem, dns_c_ipmatchlist_t **ptr) +{ + dns_c_ipmatchlist_t *newlist; + + REQUIRE(ptr != NULL); + REQUIRE(mem != NULL); + + newlist = isc_mem_get(mem, sizeof *newlist); + if (newlist == NULL) { + return (ISC_R_NOMEMORY); + } + + newlist->magic = DNS_C_IPMLIST_MAGIC; + newlist->mem = mem; + newlist->refcount = 1; + + ISC_LIST_INIT(newlist->elements); + + *ptr = newlist; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ipmatchlist_detach(dns_c_ipmatchlist_t **ml) +{ + dns_c_ipmatchelement_t *ime; + dns_c_ipmatchelement_t *iptr; + dns_c_ipmatchlist_t *iml; + isc_mem_t *mem; + + REQUIRE(ml != NULL); + REQUIRE(*ml != NULL); + + iml = *ml; + *ml = NULL; + + REQUIRE(DNS_C_IPMLIST_VALID(iml)); + INSIST(iml->refcount > 0); + + iml->refcount--; + if (iml->refcount > 0) { + return (ISC_R_SUCCESS); + } + + mem = iml->mem; + INSIST(mem != NULL); + + ime = ISC_LIST_HEAD(iml->elements); + while (ime != NULL) { + iptr = ISC_LIST_NEXT(ime, next); + dns_c_ipmatchelement_delete(mem, &ime); + + ime = iptr; + } + + isc_mem_put(mem, iml, sizeof *iml); + + return (ISC_R_SUCCESS); +} + + +void +dns_c_ipmatchlist_attach(dns_c_ipmatchlist_t *source, + dns_c_ipmatchlist_t **target) +{ + + REQUIRE(DNS_C_IPMLIST_VALID(source)); + + INSIST(source->refcount > 0); + + source->refcount++; + *target = source; +} + + +isc_result_t +dns_c_ipmatchlist_empty(dns_c_ipmatchlist_t *ipml) +{ + dns_c_ipmatchelement_t *ime ; + dns_c_ipmatchelement_t *imptmp; + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(DNS_C_IPMLIST_VALID(ipml)); + + ime = ISC_LIST_HEAD(ipml->elements); + while (ime != NULL) { + imptmp = ISC_LIST_NEXT(ime, next); + res = dns_c_ipmatchelement_delete(ipml->mem, &ime); + if (res != ISC_R_SUCCESS) { + break; + } + ime = imptmp; + } + + return (res); +} + + +isc_result_t +dns_c_ipmatchlist_copy(isc_mem_t *mem, + dns_c_ipmatchlist_t **dest, dns_c_ipmatchlist_t *src) +{ + dns_c_ipmatchelement_t *ime; + dns_c_ipmatchelement_t *ptr; + dns_c_ipmatchlist_t *newlist; + isc_result_t result; + + REQUIRE(mem != NULL); + REQUIRE(dest != NULL); + REQUIRE(DNS_C_IPMLIST_VALID(src)); + + *dest = NULL; + + result = dns_c_ipmatchlist_new(mem, &newlist); + if (result != ISC_R_SUCCESS) { + return (result); + } + + ime = ISC_LIST_HEAD(src->elements); + while (ime != NULL) { + result = dns_c_ipmatchelement_copy(mem, &ptr, ime); + if (result != ISC_R_SUCCESS) { + dns_c_ipmatchlist_detach(&newlist); + return (result); + } + + ISC_LIST_APPEND(newlist->elements, ptr, next); + + ime = ISC_LIST_NEXT(ime, next); + } + + *dest = newlist; + + return (ISC_R_SUCCESS); +} + +isc_boolean_t +dns_c_ipmatchlist_equal(dns_c_ipmatchlist_t *l1, dns_c_ipmatchlist_t *l2) { + dns_c_ipmatchelement_t *e1, *e2; + + REQUIRE(l1 == NULL || DNS_C_IPMLIST_VALID(l1)); + REQUIRE(l2 == NULL || DNS_C_IPMLIST_VALID(l2)); + + if (l1 == NULL && l2 == NULL) + return (ISC_TRUE); + if (l1 != NULL || l2 != NULL) + return (ISC_FALSE); + + e1 = ISC_LIST_HEAD(l1->elements); + e2 = ISC_LIST_HEAD(l2->elements); + while (e1 != NULL && e2 != NULL) { + if (!dns_c_ipmatchelement_equal(e1, e2)) + return (ISC_FALSE); + e1 = ISC_LIST_NEXT(e1, next); + e2 = ISC_LIST_NEXT(e2, next); + } + + if (l1 != NULL || l2 != NULL) + return (ISC_FALSE); + return (ISC_TRUE); +} + + +isc_result_t +dns_c_ipmatchlist_append(dns_c_ipmatchlist_t *dest, + dns_c_ipmatchlist_t *src, + isc_boolean_t negate) +{ + dns_c_ipmatchelement_t *ime; + dns_c_ipmatchelement_t *ime_copy; + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(DNS_C_IPMLIST_VALID(dest)); + REQUIRE(DNS_C_IPMLIST_VALID(src)); + + ime = ISC_LIST_HEAD(src->elements); + while (ime != NULL) { + result = dns_c_ipmatchelement_copy(dest->mem, + &ime_copy, + ime); + if (result != ISC_R_SUCCESS) { + break; + } + + if (negate) { + dns_c_ipmatch_negate(ime_copy); + } + + ISC_LIST_APPEND(dest->elements, ime_copy, next); + + ime = ISC_LIST_NEXT(ime, next); + } + + return (result); +} + + +isc_result_t +dns_c_ipmatchelement_print(FILE *fp, int indent, + dns_c_ipmatchelement_t *ipme) +{ + int bits; + + REQUIRE(fp != NULL); + REQUIRE(DNS_C_IPMELEM_VALID(ipme)); + + if ((ipme->flags & DNS_C_IPMATCH_NEGATE) == DNS_C_IPMATCH_NEGATE) { + fputc('!', fp); + } else { + fputc(' ', fp); + } + + switch (ipme->type) { + case dns_c_ipmatch_pattern: + dns_c_print_ipaddr(fp, &ipme->u.direct.address); + + bits = ipme->u.direct.mask; + if (bits > 0) { + isc_uint32_t fam = + ipme->u.direct.address.type.sa.sa_family; + if ((fam == AF_INET && bits < 32) || + (fam == AF_INET6 && bits < 128)) { + fprintf(fp, "/%d", bits); + } + } + break; + + case dns_c_ipmatch_indirect: + if (ipme->u.indirect.refname.base != NULL) { + fprintf(fp, "%s", ipme->u.indirect.refname.base); + } else { + dns_c_ipmatchlist_print(fp, indent, + ipme->u.indirect.list); + } + + break; + + case dns_c_ipmatch_key: + fprintf(fp, "key %s", ipme->u.key); + break; + + case dns_c_ipmatch_localhost: + fprintf(fp, "localhost"); + break; + + case dns_c_ipmatch_localnets: + fprintf(fp, "localnets"); + break; + + case dns_c_ipmatch_none: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "dns_ipmatch_none element type"); + return (ISC_R_FAILURE); + + case dns_c_ipmatch_acl: + fprintf(fp, "%s", ipme->u.aclname); + break; + } + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_ipmatchlist_print(FILE *fp, int indent, dns_c_ipmatchlist_t *ml) +{ + dns_c_ipmatchelement_t *ipme ; + + REQUIRE(DNS_C_IPMLIST_VALID(ml)); + REQUIRE(fp != NULL); + + /* no indent on first line. */ + fprintf(fp, "{\n"); + ipme = ISC_LIST_HEAD(ml->elements); + if (ipme == NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, + "/* this list intentionally left blank */\n"); + } else { + while (ipme != NULL) { + dns_c_printtabs(fp, indent); + dns_c_ipmatchelement_print(fp, indent + 1, ipme); + fprintf(fp, ";\n"); + + ipme = ISC_LIST_NEXT(ipme, next); + } + } + + dns_c_printtabs(fp, indent - 1); + fprintf(fp, "}"); + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_iplist_new(isc_mem_t *mem, int length, dns_c_iplist_t **newlist) +{ + dns_c_iplist_t *list; + size_t bytes; + + REQUIRE(mem != NULL); + REQUIRE(length > 0); + REQUIRE(newlist != NULL); + + list = isc_mem_get(mem, sizeof *list); + if (list == NULL) { + return (ISC_R_NOMEMORY); + } + + bytes = sizeof (isc_sockaddr_t) * length; + list->ips = isc_mem_get(mem, bytes); + if (list->ips == NULL) { + isc_mem_put(mem, list, sizeof *list); + return (ISC_R_NOMEMORY); + } + + memset(list->ips, 0x0, bytes); + + list->magic = DNS_C_IPLIST_MAGIC; + list->size = length; + list->nextidx = 0; + list->mem = mem; + list->refcount = 1; + + *newlist = list; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_iplist_detach(dns_c_iplist_t **list) +{ + dns_c_iplist_t *l ; + + REQUIRE(list != NULL); + REQUIRE(*list != NULL); + + l = *list; + + REQUIRE(DNS_C_IPLIST_VALID(l)); + INSIST(l->refcount > 0); + + l->refcount--; + + if (l->refcount == 0) { + isc_mem_put(l->mem, l->ips, sizeof (isc_sockaddr_t) * l->size); + isc_mem_put(l->mem, l, sizeof *l); + } + + *list = NULL; + + return (ISC_R_SUCCESS); +} + + +void +dns_c_iplist_attach(dns_c_iplist_t *source, + dns_c_iplist_t **target) +{ + REQUIRE(DNS_C_IPLIST_VALID(source)); + INSIST(source->refcount > 0); + + source->refcount++; + *target = source; +} + + + +isc_result_t +dns_c_iplist_copy(isc_mem_t *mem, dns_c_iplist_t **dest, dns_c_iplist_t *src) +{ + dns_c_iplist_t *newl; + isc_result_t res; + isc_uint32_t i; + + REQUIRE(dest != NULL); + REQUIRE(DNS_C_IPLIST_VALID(src)); + + res = dns_c_iplist_new(mem, src->size, &newl); + if (res != ISC_R_SUCCESS) { + return (res); + } + + for (i = 0 ; i < src->nextidx ; i++) { + newl->ips[i] = src->ips[i]; + } + newl->nextidx = src->nextidx; + + *dest = newl; + + return (ISC_R_SUCCESS); +} + +isc_boolean_t +dns_c_iplist_equal(dns_c_iplist_t *list1, dns_c_iplist_t *list2) { + isc_uint32_t i; + + REQUIRE(DNS_C_IPLIST_VALID(list1)); + REQUIRE(DNS_C_IPLIST_VALID(list2)); + + if (list1->nextidx != list2->nextidx) + return (ISC_FALSE); + + for (i = 0 ; i < list1->nextidx ; i++) { + if (!isc_sockaddr_equal(&list1->ips[i], &list2->ips[i])) + return (ISC_FALSE); + } + + return (ISC_TRUE); +} + + +void +dns_c_iplist_print(FILE *fp, int indent, dns_c_iplist_t *list) +{ + isc_uint32_t i; + + REQUIRE(DNS_C_IPLIST_VALID(list)); + + fprintf(fp, "{\n"); + + if (list->nextidx == 0) { + dns_c_printtabs(fp, indent); + fprintf(fp, "/* no ip addresses defined */\n"); + } else { + for (i = 0 ; i < list->nextidx ; i++) { + dns_c_printtabs(fp, indent); + dns_c_print_ipaddr(fp, &list->ips[i]); + fprintf(fp, ";\n"); + } + } + + dns_c_printtabs(fp, indent - 1); + fprintf(fp, "}"); +} + + +isc_result_t +dns_c_iplist_append(dns_c_iplist_t *list, isc_sockaddr_t newaddr) +{ + isc_uint32_t i; + + REQUIRE(DNS_C_IPLIST_VALID(list)); + + for (i = 0 ; i < list->nextidx ; i++) { + if (memcmp(&list->ips[i], &newaddr, sizeof newaddr) == 0) { + break; + } + } + + if (i < list->nextidx) { + return (ISC_R_FAILURE); + } + + if (list->nextidx == list->size) { + isc_sockaddr_t *newlist; + size_t newbytes; + size_t oldbytes = list->size * sizeof (list->ips[0]); + size_t newsize = list->size + 10; + + newbytes = sizeof (list->ips[0]) * newsize; + newlist = isc_mem_get(list->mem, newbytes); + if (newlist == NULL) { + return (ISC_R_NOMEMORY); + } + + memset(newlist, 0x0, newbytes); + memcpy(newlist, list->ips, oldbytes); + + isc_mem_put(list->mem, list->ips, oldbytes); + list->ips = newlist; + list->size = newsize; + } + + list->ips[i] = newaddr; + list->nextidx++; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_iplist_remove(dns_c_iplist_t *list, isc_sockaddr_t newaddr) +{ + isc_uint32_t i; + + REQUIRE(DNS_C_IPLIST_VALID(list)); + + for (i = 0 ; i < list->nextidx ; i++) { + if (memcmp(&list->ips[0], &newaddr, sizeof newaddr) == 0) { + break; + } + } + + if (i == list->nextidx) { + return (ISC_R_FAILURE); + } + + list->nextidx--; + for ( /* nothing */ ; i < list->nextidx ; i++) { + list->ips[i] = list->ips[i + 1]; + } + + return (ISC_R_SUCCESS); +} + + + + +/* + * Check that the address given is a network address with the given number + * of high order bits. + */ +static isc_result_t +checkmask(isc_sockaddr_t *address, isc_uint32_t bits) +{ + if (bits > 0) { + if (address->type.sa.sa_family == AF_INET) { + isc_uint32_t mask; + + if (bits > 32) { + return (ISC_R_FAILURE); + } + + mask = ntohl(0xffffffffU << (32 - bits)); + + if ((mask & address->type.sin.sin_addr.s_addr) != + address->type.sin.sin_addr.s_addr) { + return (ISC_R_FAILURE); + } + } else if (address->type.sa.sa_family == AF_INET6) { + struct in6_addr iaddr; + unsigned char *maskp; + unsigned char *addrp; + int i; + + if (bits > 128) { + return (ISC_R_FAILURE); + } + + if (bits2v6mask(&iaddr, bits) != ISC_R_SUCCESS) { + return (ISC_R_FAILURE); + } + + addrp = (unsigned char *)&address->type.sin6.sin6_addr; + maskp = (unsigned char *)&iaddr; + for (i = 0 ; i < 16 ; i++) { + if ((addrp[i] & maskp[i]) != addrp[i]) { + return (ISC_R_FAILURE); + } + } + } + } + + return (ISC_R_SUCCESS); +} + + + +/* + * Create a 128 bits mask in network byte order in the the IPv6 address + * section of the sockaddr. The bits argument is the number of high bits + * that are to be set to 1. + */ +static isc_result_t +bits2v6mask(struct in6_addr *addr, isc_uint32_t bits) +{ + int i; + isc_uint32_t bitmask[4]; + char addrbuff [ sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1 ]; + + INSIST(bits <= 128); + + /* Break the 128 bits up into 32-bit sections */ + bitmask[0] = bitmask[1] = bitmask[2] = bitmask[3] = 0U; + + if (bits >= 32) { + bitmask[0] = 0xffffffffU; + } else if (bits > 0) { + bitmask[0] = 0xffffffffU << (32 - bits); + } + + if (bits >= 64) { + bitmask[1] = 0xffffffffU; + } else if (bits > 32) { + bitmask[1] = 0xffffffffU << (64 - bits); + } + + if (bits >= 96) { + bitmask[2] = 0xffffffffU; + bitmask[3] = 0xffffffffU << (128 - bits); + } else if (bits > 64) { + bitmask[2] = 0xffffffffU << (96 - bits); + } + + memset(addr, 0x0, sizeof *addr); + + sprintf(addrbuff, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + (((bitmask[0] & 0xffff0000U) >> 16) & 0xffffU), + (bitmask[0] & 0xffff), + (((bitmask[1] & 0xffff0000U) >> 16) & 0xffffU), + (bitmask[1] & 0xffff), + (((bitmask[2] & 0xffff0000U) >> 16) & 0xffffU), + (bitmask[2] & 0xffff), + (((bitmask[3] & 0xffff0000U) >> 16) & 0xffffU), + (bitmask[3] & 0xffff)); + + i = inet_pton(AF_INET6, addrbuff, addr); + + return (i == 1 ? ISC_R_SUCCESS : ISC_R_FAILURE); +} + + + diff --git a/lib/dns/config/confkeys.c b/lib/dns/config/confkeys.c new file mode 100644 index 00000000..b4064d19 --- /dev/null +++ b/lib/dns/config/confkeys.c @@ -0,0 +1,1177 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <string.h> + +#include <isc/assertions.h> +#include <isc/magic.h> + +#include <dns/result.h> +#include <dns/confkeys.h> +#include <dns/confcommon.h> + +static isc_result_t keyid_delete(dns_c_kid_t **ki); + + +isc_result_t +dns_c_kdeflist_new(isc_mem_t *mem, dns_c_kdeflist_t **list) +{ + dns_c_kdeflist_t *newlist; + + REQUIRE(mem != NULL); + REQUIRE(list != NULL); + + newlist = isc_mem_get(mem, sizeof *newlist); + if (newlist == NULL) { + return (ISC_R_NOMEMORY); + } + + newlist->mem = mem; + newlist->magic = DNS_C_KDEFLIST_MAGIC; + + ISC_LIST_INIT(newlist->keydefs); + + *list = newlist; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_kdeflist_delete(dns_c_kdeflist_t **list) +{ + dns_c_kdeflist_t *l; + dns_c_kdef_t *kd; + dns_c_kdef_t *tmpkd; + isc_result_t res; + + REQUIRE(list != NULL); + REQUIRE(DNS_C_KDEFLIST_VALID(*list)); + + l = *list; + + kd = ISC_LIST_HEAD(l->keydefs); + while (kd != NULL) { + tmpkd = ISC_LIST_NEXT(kd, next); + ISC_LIST_UNLINK(l->keydefs, kd, next); + res = dns_c_kdef_delete(&kd); + if (res != ISC_R_SUCCESS) { + return (res); + } + kd = tmpkd; + } + + l->magic = 0; + isc_mem_put(l->mem, l, sizeof *l); + + *list = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_kdeflist_copy(isc_mem_t *mem, dns_c_kdeflist_t **dest, + dns_c_kdeflist_t *src) +{ + dns_c_kdeflist_t *newlist; + dns_c_kdef_t *key; + isc_result_t res; + + REQUIRE(dest != NULL); + REQUIRE(DNS_C_KDEFLIST_VALID(src)); + + res = dns_c_kdeflist_new(mem, &newlist); + if (res != ISC_R_SUCCESS) { + return (res); + } + + key = ISC_LIST_HEAD(src->keydefs); + while (key != NULL) { + res = dns_c_kdeflist_append(newlist, key, ISC_TRUE); + if (res != ISC_R_SUCCESS) { + dns_c_kdeflist_delete(&newlist); + return (res); + } + + key = ISC_LIST_NEXT(key, next); + } + + *dest = newlist; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_kdeflist_append(dns_c_kdeflist_t *list, + dns_c_kdef_t *key, isc_boolean_t copy) +{ + dns_c_kdef_t *newe; + isc_result_t res; + + REQUIRE(DNS_C_KDEFLIST_VALID(list)); + REQUIRE(DNS_C_KDEF_VALID(key)); + + if (copy) { + res = dns_c_kdef_copy(list->mem, &newe, key); + if (res != ISC_R_SUCCESS) { + return (res); + } + } else { + newe = key; + } + + ISC_LIST_APPEND(list->keydefs, newe, next); + + return (ISC_R_SUCCESS); +} + + + +isc_result_t +dns_c_kdeflist_undef(dns_c_kdeflist_t *list, const char *keyid) +{ + dns_c_kdef_t *kd; + isc_result_t r; + + REQUIRE(DNS_C_KDEFLIST_VALID(list)); + REQUIRE(keyid != NULL); + REQUIRE(strlen(keyid) > 0); + + kd = ISC_LIST_HEAD(list->keydefs); + while (kd != NULL) { + if (strcmp(kd->keyid, keyid) == 0) { + break; + } + kd = ISC_LIST_NEXT(kd, next); + } + + if (kd != NULL) { + ISC_LIST_UNLINK(list->keydefs, kd, next); + (void)dns_c_kdef_delete(&kd); + r = ISC_R_SUCCESS; + } else { + r = ISC_R_NOTFOUND; + } + + return (r); +} + + +isc_result_t +dns_c_kdeflist_find(dns_c_kdeflist_t *list, const char *keyid, + dns_c_kdef_t **retval) +{ + dns_c_kdef_t *kd; + isc_result_t r; + + REQUIRE(DNS_C_KDEFLIST_VALID(list)); + REQUIRE(keyid != NULL); + REQUIRE(strlen(keyid) > 0); + + kd = ISC_LIST_HEAD(list->keydefs); + while (kd != NULL) { + if (strcmp(kd->keyid, keyid) == 0) { + break; + } + kd = ISC_LIST_NEXT(kd, next); + } + + if (kd != NULL) { + *retval = kd; + r = ISC_R_SUCCESS; + } else { + r = ISC_R_NOTFOUND; + } + + return (r); +} + + + +void +dns_c_kdeflist_print(FILE *fp, int indent, dns_c_kdeflist_t *list) +{ + dns_c_kdef_t *kd; + + REQUIRE(fp != NULL); + REQUIRE(indent >= 0); + REQUIRE(DNS_C_KDEFLIST_VALID(list)); + + if (list == NULL) { + return; + } + + kd = ISC_LIST_HEAD(list->keydefs); + while (kd != NULL) { + dns_c_kdef_print(fp, indent, kd); + fprintf(fp, "\n"); + kd = ISC_LIST_NEXT(kd, next); + } +} + + +isc_result_t +dns_c_kdef_new(dns_c_kdeflist_t *list, const char *name, + dns_c_kdef_t **keyid) +{ + dns_c_kdef_t *kd; + + REQUIRE(DNS_C_KDEFLIST_VALID(list)); + REQUIRE(keyid != NULL); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + + kd = isc_mem_get(list->mem, sizeof *kd); + if (kd == NULL) { + return (ISC_R_NOMEMORY); + } + + kd->keyid = isc_mem_strdup(list->mem, name); + if (kd->keyid == NULL) { + isc_mem_put(list->mem, kd, sizeof *kd); + } + + kd->magic = DNS_C_KDEF_MAGIC; + kd->mylist = list; + kd->algorithm = NULL; + kd->secret = NULL; + + ISC_LIST_APPEND(list->keydefs, kd, next); + + *keyid = kd; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_kdef_delete(dns_c_kdef_t **keydef) +{ + dns_c_kdef_t *kd; + isc_mem_t *mem; + + REQUIRE(keydef != NULL); + REQUIRE(DNS_C_KDEF_VALID(*keydef)); + + kd = *keydef; + + mem = kd->mylist->mem; + + isc_mem_free(mem, kd->keyid); + + if (kd->algorithm != NULL) { + isc_mem_free(mem, kd->algorithm); + } + + if (kd->secret != NULL) { + isc_mem_free(mem, kd->secret); + } + + kd->magic = 0; + kd->keyid = NULL; + kd->mylist = NULL; + kd->algorithm = NULL; + kd->secret = NULL; + + ISC_LINK_INIT(kd,next); + + isc_mem_put(mem, kd, sizeof *kd); + + *keydef = NULL; + + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_c_kdef_copy(isc_mem_t *mem, + dns_c_kdef_t **dest, dns_c_kdef_t *src) +{ + dns_c_kdef_t *newk; + + REQUIRE(dest != NULL); + REQUIRE(DNS_C_KDEF_VALID(src)); + + newk = isc_mem_get(mem, sizeof *newk); + if (newk == NULL) { + return (ISC_R_NOMEMORY); + } + newk->magic = DNS_C_KDEF_MAGIC; + newk->secret = newk->algorithm = newk->keyid = NULL; + + newk->keyid = isc_mem_strdup(mem, src->keyid); + if (newk->keyid == NULL) { + dns_c_kdef_delete(&newk); + return (ISC_R_NOMEMORY); + } + + newk->algorithm = isc_mem_strdup(mem, src->algorithm); + if (newk->algorithm == NULL) { + dns_c_kdef_delete(&newk); + return (ISC_R_NOMEMORY); + } + + newk->secret = isc_mem_strdup(mem, src->secret); + if (newk->secret == NULL) { + dns_c_kdef_delete(&newk); + return (ISC_R_NOMEMORY); + } + + *dest = newk; + + return (ISC_R_SUCCESS); +} + + + +void +dns_c_kdef_print(FILE *fp, int indent, dns_c_kdef_t *keydef) +{ + const char *quote = ""; + + REQUIRE(fp != NULL); + REQUIRE(DNS_C_KDEF_VALID(keydef)); + + if (dns_c_need_quote(keydef->keyid)) { + quote = "\""; + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "key %s%s%s {\n",quote, keydef->keyid, quote); + + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "algorithm \"%s\";\n",keydef->algorithm); + + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "secret \"%s\";\n",keydef->secret); + + dns_c_printtabs(fp, indent); + fprintf(fp, "};\n"); +} + + +isc_result_t +dns_c_kdef_setalgorithm(dns_c_kdef_t *keydef, const char *algorithm) +{ + REQUIRE(DNS_C_KDEF_VALID(keydef)); + REQUIRE(algorithm != NULL); + REQUIRE(strlen(algorithm) > 0); + + if (keydef->algorithm != NULL) { + isc_mem_free(keydef->mylist->mem, keydef->algorithm); + } + + keydef->algorithm = isc_mem_strdup(keydef->mylist->mem, + algorithm); + if (keydef->algorithm == NULL) { + return (ISC_R_NOMEMORY); + } + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_kdef_setsecret(dns_c_kdef_t *keydef, const char *secret) +{ + REQUIRE(DNS_C_KDEF_VALID(keydef)); + REQUIRE(secret != NULL); + REQUIRE(strlen(secret) > 0); + + if (keydef->secret != NULL) { + isc_mem_free(keydef->mylist->mem, keydef->secret); + } + + keydef->secret = isc_mem_strdup(keydef->mylist->mem, secret); + if (keydef->secret == NULL) { + return (ISC_R_NOMEMORY); + } + + return (ISC_R_SUCCESS); +} + + + +isc_result_t +dns_c_kidlist_new(isc_mem_t *mem, dns_c_kidlist_t **list) +{ + dns_c_kidlist_t *l; + + l = isc_mem_get(mem, sizeof *l); + if (l == NULL) { + return (ISC_R_NOMEMORY); + } + + l->magic = DNS_C_KEYIDLIST_MAGIC; + l->mem = mem; + *list = l; + + ISC_LIST_INIT(l->keyids); + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_kidlist_delete(dns_c_kidlist_t **list) +{ + dns_c_kidlist_t *l; + dns_c_kid_t *ki, *tmpki; + isc_result_t r; + + REQUIRE(list != NULL); + REQUIRE(DNS_C_KEYIDLIST_VALID(*list)); + + l = *list; + + ki = ISC_LIST_HEAD(l->keyids); + while (ki != NULL) { + tmpki = ISC_LIST_NEXT(ki, next); + ISC_LIST_UNLINK(l->keyids, ki, next); + r = keyid_delete(&ki); + if (r != ISC_R_SUCCESS) { + return (r); + } + ki = tmpki; + } + + l->magic = 0; + isc_mem_put(l->mem, l, sizeof *l); + + *list = NULL; + + return (ISC_R_SUCCESS); +} + + +static isc_result_t +keyid_delete(dns_c_kid_t **keyid) +{ + dns_c_kid_t *ki; + + REQUIRE(keyid != NULL); + REQUIRE(DNS_C_KEYID_VALID(*keyid)); + + ki = *keyid; + + isc_mem_free(ki->mylist->mem, ki->keyid); + + ki->magic = 0; + isc_mem_put(ki->mylist->mem, ki, sizeof *ki); + + *keyid = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_kidlist_undef(dns_c_kidlist_t *list, const char *keyid) +{ + dns_c_kid_t *ki; + isc_result_t r; + + REQUIRE(DNS_C_KEYIDLIST_VALID(list)); + REQUIRE(keyid != NULL); + REQUIRE(strlen(keyid) > 0); + + dns_c_kidlist_find(list, keyid, &ki); + + if (ki != NULL) { + ISC_LIST_UNLINK(list->keyids, ki, next); + r = keyid_delete(&ki); + } else { + r = ISC_R_SUCCESS; + } + + return (r); +} + + +isc_result_t +dns_c_kidlist_find(dns_c_kidlist_t *list, const char *keyid, + dns_c_kid_t **retval) +{ + dns_c_kid_t *iter; + + REQUIRE(DNS_C_KEYIDLIST_VALID(list)); + REQUIRE(keyid != NULL); + REQUIRE(strlen(keyid) > 0); + REQUIRE(retval != NULL); + + iter = ISC_LIST_HEAD(list->keyids); + while (iter != NULL) { + if (strcmp(keyid, iter->keyid) == 0) { + break; + } + + iter = ISC_LIST_NEXT(iter, next); + } + + *retval = iter; + + return (iter == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +void +dns_c_kidlist_print(FILE *fp, int indent, + dns_c_kidlist_t *list) +{ + dns_c_kid_t *iter; + const char *quote; + + REQUIRE(fp != NULL); + REQUIRE(DNS_C_KEYIDLIST_VALID(list)); + + if (ISC_LIST_EMPTY(list->keyids)) { + return; + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "keys {\n"); + iter = ISC_LIST_HEAD(list->keyids); + if (iter == NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "/* no keys defined */\n"); + } else { + while (iter != NULL) { + if (dns_c_need_quote(iter->keyid)) { + quote = "\""; + } else { + quote = ""; + } + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "%s%s%s;\n", quote, iter->keyid, quote); + iter = ISC_LIST_NEXT(iter, next); + } + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "};\n"); +} + + +isc_result_t +dns_c_kid_new(dns_c_kidlist_t *list, const char *name, dns_c_kid_t **keyid) +{ + dns_c_kid_t *ki; + + REQUIRE(DNS_C_KEYIDLIST_VALID(list)); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + REQUIRE(keyid != NULL); + + ki = isc_mem_get(list->mem, sizeof *ki); + if (ki == NULL) { + return (ISC_R_NOMEMORY); + } + + ki->magic = DNS_C_KEYID_MAGIC; + ki->mylist = list; + ki->keyid = isc_mem_strdup(list->mem, name); + + ISC_LINK_INIT(ki, next); + ISC_LIST_APPEND(list->keyids, ki, next); + + *keyid = ki; + + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_c_pklist_new(isc_mem_t *mem, dns_c_pklist_t **pklist) +{ + dns_c_pklist_t *newl; + + REQUIRE(pklist != NULL); + + newl = isc_mem_get(mem, sizeof *newl); + if (newl == NULL) { + return (ISC_R_NOMEMORY); + } + + newl->mem = mem; + newl->magic = DNS_C_PKLIST_MAGIC; + + ISC_LIST_INIT(newl->keylist); + + *pklist = newl; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_pklist_delete(dns_c_pklist_t **list) +{ + dns_c_pklist_t *l; + dns_c_pubkey_t *pk; + dns_c_pubkey_t *tmppk; + isc_result_t r; + + REQUIRE(list != NULL); + REQUIRE(DNS_C_PKLIST_VALID(*list)); + + l = *list; + + pk = ISC_LIST_HEAD(l->keylist); + while (pk != NULL) { + tmppk = ISC_LIST_NEXT(pk, next); + ISC_LIST_UNLINK(l->keylist, pk, next); + r = dns_c_pubkey_delete(&pk); + if (r != ISC_R_SUCCESS) { + return (r); + } + + pk = tmppk; + } + + l->magic = 0; + isc_mem_put(l->mem, l, sizeof *l); + + return (ISC_R_SUCCESS); +} + + + +void +dns_c_pklist_print(FILE *fp, int indent, dns_c_pklist_t *list) +{ + dns_c_pubkey_t *pk; + + REQUIRE(fp != NULL); + REQUIRE(indent >= 0); + + if (list == NULL) { + return; + } + + REQUIRE(DNS_C_PKLIST_VALID(list)); + + pk = ISC_LIST_HEAD(list->keylist); + while (pk != NULL) { + dns_c_pubkey_print(fp, indent, pk); + pk = ISC_LIST_NEXT(pk, next); + } + fprintf(fp, "\n"); +} + + + +isc_result_t +dns_c_pklist_addpubkey(dns_c_pklist_t *list, + dns_c_pubkey_t *pkey, + isc_boolean_t deepcopy) +{ + dns_c_pubkey_t *pk; + isc_result_t r; + + REQUIRE(DNS_C_PKLIST_VALID(list)); + REQUIRE(DNS_C_PUBKEY_VALID(pkey)); + + if (deepcopy) { + r = dns_c_pubkey_copy(list->mem, &pk, pkey); + if (r != ISC_R_SUCCESS) { + return (r); + } + } else { + pk = pkey; + } + + ISC_LIST_APPEND(list->keylist, pk, next); + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_pklist_findpubkey(dns_c_pklist_t *list, + dns_c_pubkey_t **pubkey, isc_int32_t flags, + isc_int32_t protocol, isc_int32_t algorithm, + const char *key) +{ + dns_c_pubkey_t *pk; + + REQUIRE(DNS_C_PKLIST_VALID(list)); + REQUIRE(pubkey != NULL); + + *pubkey = NULL; + pk = ISC_LIST_HEAD(list->keylist); + while (pk != NULL) { + if (pk->flags == flags && + pk->protocol == protocol && + pk->algorithm == algorithm && + strcmp(pk->key, key) == 0) { + *pubkey = pk; + pk = NULL; + } else { + pk = ISC_LIST_NEXT(pk, next); + } + } + + return (*pubkey == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + + +isc_result_t +dns_c_pklist_rmpubkey(dns_c_pklist_t *list, + isc_int32_t flags, + isc_int32_t protocol, isc_int32_t algorithm, + const char *key) +{ + dns_c_pubkey_t *pk; + isc_result_t r; + + REQUIRE(DNS_C_PKLIST_VALID(list)); + REQUIRE(key != NULL); + REQUIRE(strlen(key) > 0); + + r = dns_c_pklist_findpubkey(list, &pk, flags, protocol, + algorithm, key); + if (r == ISC_R_SUCCESS) { + ISC_LIST_UNLINK(list->keylist, pk, next); + r = dns_c_pubkey_delete(&pk); + } + + return (r); +} + + + +isc_result_t +dns_c_pubkey_new(isc_mem_t *mem, isc_int32_t flags, + isc_int32_t protocol, + isc_int32_t algorithm, + const char *key, dns_c_pubkey_t **pubkey) +{ + dns_c_pubkey_t *pkey; + + REQUIRE(pubkey != NULL); + REQUIRE(key != NULL); + REQUIRE(strlen(key) > 0); + + pkey = isc_mem_get(mem, sizeof *pkey); + if (pkey == NULL) { + return (ISC_R_NOMEMORY); + } + + pkey->magic = DNS_C_PUBKEY_MAGIC; + pkey->mem = mem; + pkey->flags = flags; + pkey->protocol = protocol; + pkey->algorithm = algorithm; + pkey->key = isc_mem_strdup(mem, key); + if (pkey->key == NULL) { + isc_mem_put(mem, pkey, sizeof *pkey); + return (ISC_R_NOMEMORY); + } + + *pubkey = pkey; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_pubkey_delete(dns_c_pubkey_t **pubkey) +{ + dns_c_pubkey_t *pkey; + + REQUIRE(pubkey != NULL); + REQUIRE(DNS_C_PUBKEY_VALID(*pubkey)); + + pkey = *pubkey; + + if (pkey->key != NULL) { + isc_mem_free(pkey->mem, pkey->key); + } + + pkey->magic = 0; + isc_mem_put(pkey->mem, pkey, sizeof *pkey); + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_pubkey_copy(isc_mem_t *mem, dns_c_pubkey_t **dest, dns_c_pubkey_t *src) +{ + dns_c_pubkey_t *k; + isc_result_t res; + + REQUIRE(DNS_C_PUBKEY_VALID(src)); + REQUIRE(dest != NULL); + + res = dns_c_pubkey_new(mem, src->flags, src->protocol, + src->algorithm, src->key, &k); + if (res != ISC_R_SUCCESS) { + return (res); + } + + *dest = k; + + return (ISC_R_SUCCESS); +} + +isc_boolean_t +dns_c_pubkey_equal(dns_c_pubkey_t *k1, dns_c_pubkey_t *k2) { + + REQUIRE(DNS_C_PUBKEY_VALID(k1)); + REQUIRE(DNS_C_PUBKEY_VALID(k2)); + + return (ISC_TF(k1->flags == k2->flags && + k1->protocol == k2->protocol && + k1->algorithm == k2->algorithm && + strcmp(k1->key, k2->key) == 0)); +} + +void +dns_c_pubkey_print(FILE *fp, int indent, dns_c_pubkey_t *pubkey) +{ + REQUIRE(fp != NULL); + REQUIRE(DNS_C_PUBKEY_VALID(pubkey)); + + dns_c_printtabs(fp, indent); + fprintf(fp, "pubkey %d %d %d \"%s\";\n", + pubkey->flags, pubkey->protocol, + pubkey->algorithm, pubkey->key); +} + + +isc_result_t +dns_c_tkeylist_new(isc_mem_t *mem, dns_c_tkeylist_t **newlist) +{ + dns_c_tkeylist_t *nl; + + REQUIRE(newlist != NULL); + + nl = isc_mem_get(mem, sizeof *nl); + if (nl == NULL) { + return (ISC_R_NOMEMORY); + } + + nl->magic = DNS_C_TKEYLIST_MAGIC; + nl->mem = mem; + ISC_LIST_INIT(nl->tkeylist); + + *newlist = nl; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_tkeylist_delete(dns_c_tkeylist_t **list) +{ + dns_c_tkeylist_t *l; + dns_c_tkey_t *tkey, *tmptkey; + isc_result_t res; + + REQUIRE(list != NULL); + REQUIRE(DNS_C_TKEYLIST_VALID(*list)); + + l = *list; + + tkey = ISC_LIST_HEAD(l->tkeylist); + while (tkey != NULL) { + tmptkey = ISC_LIST_NEXT(tkey, next); + ISC_LIST_UNLINK(l->tkeylist, tkey, next); + + res = dns_c_tkey_delete(&tkey); + if (res != ISC_R_SUCCESS) { + return (res); + } + + tkey = tmptkey; + } + + l->magic = 0; + isc_mem_put(l->mem, l, sizeof *l); + + *list = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_tkeylist_copy(isc_mem_t *mem, dns_c_tkeylist_t **dest, + dns_c_tkeylist_t *src) +{ + dns_c_tkeylist_t *newlist; + dns_c_tkey_t *tkey, *tmptkey; + isc_result_t res; + + REQUIRE(dest != NULL); + REQUIRE(DNS_C_TKEYLIST_VALID(src)); + + res = dns_c_tkeylist_new(mem, &newlist); + if (res != ISC_R_SUCCESS) { + return (res); + } + + tkey = ISC_LIST_HEAD(src->tkeylist); + while (tkey != NULL) { + res = dns_c_tkey_copy(mem, &tmptkey, tkey); + if (res != ISC_R_SUCCESS) { + dns_c_tkeylist_delete(&newlist); + return (res); + } + + res = dns_c_tkeylist_append(newlist, tmptkey, ISC_FALSE); + if (res != ISC_R_SUCCESS) { + dns_c_tkey_delete(&tmptkey); + dns_c_tkeylist_delete(&newlist); + return (res); + } + + tkey = ISC_LIST_NEXT(tkey, next); + } + + *dest = newlist; + + return (ISC_R_SUCCESS); +} + + +void +dns_c_tkeylist_print(FILE *fp, int indent, dns_c_tkeylist_t *list) +{ + dns_c_tkey_t *tkey; + + REQUIRE(fp != NULL); + REQUIRE(DNS_C_TKEYLIST_VALID(list)); + + dns_c_printtabs(fp, indent); + fprintf(fp, "trusted-keys {\n"); + tkey = ISC_LIST_HEAD(list->tkeylist); + if (tkey == NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "/* empty list */\n"); + } else { + while (tkey != NULL) { + dns_c_tkey_print(fp, indent + 1, tkey); + tkey = ISC_LIST_NEXT(tkey, next); + } + } + dns_c_printtabs(fp, indent); + fprintf(fp,"};\n"); +} + + +isc_result_t +dns_c_tkeylist_append(dns_c_tkeylist_t *list, dns_c_tkey_t *element, + isc_boolean_t copy) +{ + dns_c_tkey_t *newe; + isc_result_t res; + + REQUIRE(DNS_C_TKEYLIST_VALID(list)); + REQUIRE(DNS_C_TKEY_VALID(element)); + + if (copy) { + res = dns_c_tkey_copy(list->mem, &newe, element); + if (res != ISC_R_SUCCESS) { + return (res); + } + } else { + newe = element; + } + + ISC_LIST_APPEND(list->tkeylist, newe, next); + + return (ISC_R_SUCCESS); +} + + + +isc_result_t +dns_c_tkey_new(isc_mem_t *mem, const char *domain, isc_int32_t flags, + isc_int32_t protocol, isc_int32_t algorithm, + const char *key, dns_c_tkey_t **newkey) +{ + dns_c_tkey_t *newk; + dns_c_pubkey_t *pk; + isc_result_t res; + + REQUIRE(domain != NULL); + REQUIRE(strlen(domain) > 0); + REQUIRE(key != NULL); + REQUIRE(strlen(key) > 0); + REQUIRE(newkey != NULL); + + newk = isc_mem_get(mem, sizeof *newk); + if (newk == NULL) { + return (ISC_R_NOMEMORY); + } + + res = dns_c_pubkey_new(mem, flags, protocol, + algorithm, key, &pk); + if (res != ISC_R_SUCCESS) { + isc_mem_put(mem, newk, sizeof *newk); + return (res); + } + + newk->mem = mem; + newk->magic = DNS_C_TKEY_MAGIC; + + newk->domain = isc_mem_strdup(mem, domain); + if (newk->domain == NULL) { + dns_c_pubkey_delete(&pk); + isc_mem_put(mem, newk, sizeof *newk); + return (ISC_R_NOMEMORY); + } + + newk->pubkey = pk; + + ISC_LINK_INIT(newk, next); + + *newkey = newk; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_tkey_delete(dns_c_tkey_t **tkey) +{ + isc_result_t res; + dns_c_tkey_t *tk; + + REQUIRE(tkey != NULL); + REQUIRE(DNS_C_TKEY_VALID(*tkey)); + + tk = *tkey; + + isc_mem_free(tk->mem, tk->domain); + + res = dns_c_pubkey_delete(&tk->pubkey); + if (res != ISC_R_SUCCESS) { + return (res); + } + + tk->magic = 0; + isc_mem_put(tk->mem, tk, sizeof *tk); + + *tkey = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_tkey_copy(isc_mem_t *mem, dns_c_tkey_t **dest, dns_c_tkey_t *src) +{ + dns_c_tkey_t *newk; + dns_c_pubkey_t *newpk; + isc_result_t res; + + REQUIRE(dest != NULL); + REQUIRE(DNS_C_TKEY_VALID(src)); + + newk = isc_mem_get(mem, sizeof *newk); + if (newk == NULL) { + return (ISC_R_NOMEMORY); + } + + newk->magic = DNS_C_TKEY_MAGIC; + newk->domain = isc_mem_strdup(mem, src->domain); + if (newk->domain == NULL) { + isc_mem_put(mem, newk, sizeof *newk); + return (ISC_R_NOMEMORY); + } + + res = dns_c_pubkey_copy(mem, &newpk, src->pubkey); + if (res != ISC_R_SUCCESS) { + isc_mem_free(mem, newk->domain); + isc_mem_put(mem, newk, sizeof *newk); + return (res); + } + + newk->pubkey = newpk; + + *dest = newk; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_tkey_getflags(dns_c_tkey_t *tkey, isc_int32_t *flags) +{ + REQUIRE(DNS_C_TKEY_VALID(tkey)); + + *flags = tkey->pubkey->flags; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_tkey_getprotocol(dns_c_tkey_t *tkey, isc_int32_t *protocol) +{ + REQUIRE(DNS_C_TKEY_VALID(tkey)); + + *protocol = tkey->pubkey->protocol; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_tkey_getalgorithm(dns_c_tkey_t *tkey, isc_int32_t *algorithm) +{ + REQUIRE(DNS_C_TKEY_VALID(tkey)); + + *algorithm = tkey->pubkey->algorithm; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_tkey_getkey(dns_c_tkey_t *tkey, const char **key) +{ + REQUIRE(key != NULL); + REQUIRE(DNS_C_TKEY_VALID(tkey)); + + *key = tkey->pubkey->key; + + return (ISC_R_SUCCESS); +} + + +void +dns_c_tkey_print(FILE *fp, int indent, dns_c_tkey_t *tkey) +{ + REQUIRE(fp != NULL); + REQUIRE(DNS_C_TKEY_VALID(tkey)); + + dns_c_printtabs(fp, indent); + fprintf(fp, "\"%s\" %d %d %d \"%s\";\n", + tkey->domain, tkey->pubkey->flags, + tkey->pubkey->protocol, tkey->pubkey->algorithm, + tkey->pubkey->key); + + return; +} + diff --git a/lib/dns/config/conflog.c b/lib/dns/config/conflog.c new file mode 100644 index 00000000..fe83e239 --- /dev/null +++ b/lib/dns/config/conflog.c @@ -0,0 +1,1345 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <string.h> + +#include <isc/assertions.h> +#include <isc/magic.h> + +#include <dns/conflog.h> +#include <dns/confcommon.h> +#include <dns/log.h> + + +#include "confpvt.h" + + +#define UNLIM_VERSIONS (-1) /* XXX check this is right? */ + +/* + * Bit positions in the dns_c_logchan_t structure setflags field. + */ +#define CHAN_VERSIONS_BIT 0 +#define CHAN_SIZE_BIT 1 +#define CHAN_SEVERITY_BIT 2 +#define CHAN_DEBUG_LEVEL_BIT 3 +#define CHAN_PCAT_BIT 4 +#define CHAN_PSEV_BIT 5 +#define CHAN_PTIME_BIT 6 +#define CHAN_FACILITY_BIT 7 + + + +static void print_log_facility(FILE *fp, + int value); +static void print_log_severity(FILE *fp, + dns_c_logseverity_t severity); +static void print_log_category(FILE *fp, + dns_c_category_t category); +static isc_boolean_t logginglist_empty(dns_c_logginglist_t *ll); + + + +isc_result_t +dns_c_logginglist_new(isc_mem_t *mem, + dns_c_logginglist_t **list) +{ + dns_c_logginglist_t *newl; + + REQUIRE(list != NULL); + + newl = isc_mem_get(mem, sizeof *newl); + if (newl == NULL) { + return (ISC_R_NOMEMORY); + } + + newl->magic = DNS_C_LOGLIST_MAGIC; + newl->mem = mem; + ISC_LIST_INIT(newl->channels); + ISC_LIST_INIT(newl->categories); + + *list = newl; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logginglist_delete(dns_c_logginglist_t **list) +{ + dns_c_logginglist_t *l; + dns_c_logchan_t *chan, *tmpchan; + dns_c_logcat_t *cat, *tmpcat; + isc_result_t res; + + REQUIRE(list != NULL); + REQUIRE(DNS_C_LOGLIST_VALID(*list)); + + l = *list; + + chan = ISC_LIST_HEAD(l->channels); + while (chan != NULL) { + tmpchan = ISC_LIST_NEXT(chan, next); + ISC_LIST_UNLINK(l->channels, chan, next); + res = dns_c_logchan_delete(&chan); + if (res != ISC_R_SUCCESS) { + return (res); + } + + chan = tmpchan; + } + + cat = ISC_LIST_HEAD(l->categories); + while (cat != NULL) { + tmpcat = ISC_LIST_NEXT(cat, next); + ISC_LIST_UNLINK(l->categories, cat, next); + res = dns_c_logcat_delete(&cat); + if (res != ISC_R_SUCCESS) { + return (res); + } + + cat = tmpcat; + } + + l->magic = 0; + isc_mem_put(l->mem, l, sizeof *l); + + *list = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logginglist_copy(isc_mem_t *mem, + dns_c_logginglist_t **dest, + dns_c_logginglist_t *src) +{ + dns_c_logginglist_t *newl; + dns_c_logchan_t *logchan, *tmplogchan; + dns_c_logcat_t *logcat, *tmplogcat; + isc_result_t res; + + REQUIRE(dest != NULL); + REQUIRE(DNS_C_LOGLIST_VALID(src)); + + res = dns_c_logginglist_new(mem, &newl); + if (res != ISC_R_SUCCESS) { + return (res); + } + + logchan = ISC_LIST_HEAD(src->channels); + while (logchan != NULL) { + res = dns_c_logchan_copy(mem, &tmplogchan, logchan); + if (res != ISC_R_SUCCESS) { + dns_c_logginglist_delete(&newl); + return (res); + } + + ISC_LIST_APPEND(newl->channels, tmplogchan, next); + logchan = ISC_LIST_NEXT(logchan, next); + } + + + logcat = ISC_LIST_HEAD(src->categories); + while (logcat != NULL) { + res = dns_c_logcat_copy(mem, &tmplogcat, logcat); + if (res != ISC_R_SUCCESS) { + dns_c_logginglist_delete(&newl); + return (res); + } + + ISC_LIST_APPEND(newl->categories, tmplogcat, next); + logcat = ISC_LIST_NEXT(logcat, next); + } + + return (ISC_R_SUCCESS); +} + + +static isc_boolean_t +logginglist_empty(dns_c_logginglist_t *ll) +{ + dns_c_logchan_t *logchan; + dns_c_logcat_t *logcat; + + REQUIRE(DNS_C_LOGLIST_VALID(ll)); + + logchan = ISC_LIST_HEAD(ll->channels); + while (logchan != NULL) { + if (!logchan->predefined) { + return ISC_TRUE; + } + + logchan = ISC_LIST_NEXT(logchan, next); + } + + logcat = ISC_LIST_HEAD(ll->categories); + while (logcat != NULL) { + if (!logcat->predefined) { + return ISC_FALSE; + } + logcat = ISC_LIST_NEXT(logcat, next); + } + + return ISC_TRUE; +} + + +void +dns_c_logginglist_print(FILE *fp, int indent, dns_c_logginglist_t *ll, + isc_boolean_t if_predef_too) +{ + dns_c_logchan_t *logchan; + dns_c_logcat_t *logcat; + + REQUIRE(fp != NULL); + REQUIRE(DNS_C_LOGLIST_VALID(ll)); + + if (logginglist_empty(ll)) { + return; + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "logging {\n"); + + logchan = ISC_LIST_HEAD(ll->channels); + while (logchan != NULL) { + dns_c_logchan_print(fp, indent + 1, logchan, + if_predef_too); + logchan = ISC_LIST_NEXT(logchan, next); + } + + logcat = ISC_LIST_HEAD(ll->categories); + while (logcat != NULL) { + dns_c_logcat_print(fp, indent + 1, logcat, + if_predef_too); + logcat = ISC_LIST_NEXT(logcat, next); + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "};\n"); +} + + +isc_result_t +dns_c_logginglist_addchannel(dns_c_logginglist_t *list, + dns_c_logchan_t *newchan, + isc_boolean_t deepcopy) +{ + dns_c_logchan_t *newc, *tmpchan; + isc_result_t res; + isc_boolean_t existed = ISC_FALSE; + isc_boolean_t predefined = ISC_FALSE; + + REQUIRE(DNS_C_LOGLIST_VALID(list)); + REQUIRE(DNS_C_LOGCHAN_VALID(newchan)); + + if (deepcopy) { + res = dns_c_logchan_copy(list->mem, &newc, newchan); + if (res != ISC_R_SUCCESS) { + return (res); + } + } else { + newc = newchan; + } + + tmpchan = ISC_LIST_HEAD(list->channels); + while (tmpchan != NULL) { + if (strcmp(newchan->name, tmpchan->name) == 0) { + existed = ISC_TRUE; + predefined = tmpchan->predefined; + + ISC_LIST_UNLINK(list->channels, tmpchan, next); + res = dns_c_logchan_delete(&tmpchan); + if (res != ISC_R_SUCCESS) { + if (deepcopy) { + dns_c_logchan_delete(&newc); + } + return (res); + } + break; + } + + tmpchan = ISC_LIST_NEXT(tmpchan, next); + } + + ISC_LIST_APPEND(list->channels, newc, next); + + /* replacing a predefined channel is a plain success. */ + return (existed && !predefined ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logginglist_addcategory(dns_c_logginglist_t *list, + dns_c_logcat_t *newcat, + isc_boolean_t deepcopy) +{ + dns_c_logcat_t *newc, *tmpcat; + isc_result_t res; + isc_boolean_t existed = ISC_FALSE; + isc_boolean_t predefined = ISC_FALSE; + + REQUIRE(DNS_C_LOGLIST_VALID(list)); + REQUIRE(DNS_C_LOGCAT_VALID(newcat)); + + + if (deepcopy) { + res = dns_c_logcat_copy(list->mem, &newc, newcat); + if (res != ISC_R_SUCCESS) { + return (res); + } + } else { + newc = newcat; + } + + /* Remove old category defintion if there. */ + tmpcat = ISC_LIST_HEAD(list->categories); + while (tmpcat != NULL) { + if (newcat->category == tmpcat->category) { + existed = ISC_TRUE; + predefined = tmpcat->predefined; + + ISC_LIST_UNLINK(list->categories, tmpcat, next); + res = dns_c_logcat_delete(&tmpcat); + if (res != ISC_R_SUCCESS) { + if (deepcopy) { + dns_c_logcat_delete(&newc); + } + return (res); + } + break; + } + + tmpcat = ISC_LIST_NEXT(tmpcat, next); + } + + ISC_LIST_APPEND(list->categories, newc, next); + + /* replacing a predefined category is a simple success. */ + return (existed && !predefined ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logginglist_delchannel(dns_c_logginglist_t *list, + const char *name) +{ + dns_c_logchan_t *logc; + isc_result_t res; + + REQUIRE(DNS_C_LOGLIST_VALID(list)); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + + res = dns_c_logginglist_chanbyname(list, name, &logc); + if (res == ISC_R_SUCCESS) { + ISC_LIST_UNLINK(list->channels, logc, next); + + res = dns_c_logchan_delete(&logc); + } + + return (res); +} + + +isc_result_t +dns_c_logginglist_delcategory(dns_c_logginglist_t *list, + const char *name) +{ + dns_c_logcat_t *logc; + isc_result_t res; + + REQUIRE(DNS_C_LOGLIST_VALID(list)); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + + res = dns_c_logginglist_catbyname(list, name, &logc); + if (res == ISC_R_SUCCESS) { + ISC_LIST_UNLINK(list->categories, logc, next); + + res = dns_c_logcat_delete(&logc); + } + + return (res); +} + + +isc_result_t +dns_c_logginglist_chanbyname(dns_c_logginglist_t *list, + const char *name, + dns_c_logchan_t **chan) +{ + dns_c_logchan_t *logc; + + REQUIRE(DNS_C_LOGLIST_VALID(list)); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + REQUIRE(chan != NULL); + + logc = ISC_LIST_HEAD(list->channels); + while (logc != NULL) { + if (strcmp(logc->name, name) == 0) { + break; + } + + logc = ISC_LIST_NEXT(logc, next); + } + + if (logc == NULL) { + return (ISC_R_NOTFOUND); + } else { + *chan = logc; + return (ISC_R_SUCCESS); + } +} + + +isc_result_t +dns_c_logginglist_catbyname(dns_c_logginglist_t *list, + const char *name, + dns_c_logcat_t **cat) +{ + dns_c_category_t cattype; + isc_result_t res; + + REQUIRE(DNS_C_LOGLIST_VALID(list)); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + REQUIRE(cat != NULL); + + res = dns_c_string2category(name, &cattype); + if (res != ISC_R_SUCCESS) { + return (ISC_R_FAILURE); + } + + return (dns_c_logginglist_catbytype(list, cattype, cat)); +} + + +isc_result_t +dns_c_logginglist_catbytype(dns_c_logginglist_t *list, + dns_c_category_t cattype, + dns_c_logcat_t **cat) +{ + dns_c_logcat_t *logc; + + REQUIRE(DNS_C_LOGLIST_VALID(list)); + REQUIRE(cat != NULL); + + logc = ISC_LIST_HEAD(list->categories); + while (logc != NULL) { + if (logc->category == cattype) { + break; + } + + logc = ISC_LIST_NEXT(logc, next); + } + + if (logc == NULL) { + return (ISC_R_NOTFOUND); + } else { + *cat = logc; + return (ISC_R_SUCCESS); + } +} + + +/* ************************************************************************ */ +/* **************************** LOGGING CHANNELS ************************** */ +/* ************************************************************************ */ + +isc_result_t +dns_c_logchan_new(isc_mem_t *mem, const char *name, + dns_c_logchantype_t ctype, + dns_c_logchan_t **newchan) +{ + dns_c_logchan_t *newc; + + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + REQUIRE(newchan != NULL); + + newc = isc_mem_get(mem, sizeof *newc); + if (newc == NULL) { + return (ISC_R_NOMEMORY); + } + + newc->magic = DNS_C_LOGCHAN_MAGIC; + newc->mem = mem; + newc->ctype = ctype; + newc->severity = dns_c_log_info; + newc->debug_level = 0; + newc->print_category = ISC_FALSE; + newc->print_severity = ISC_FALSE; + newc->print_time = ISC_FALSE; + newc->predefined = ISC_FALSE; + + memset(&newc->setflags, 0x0, sizeof newc->setflags); + + ISC_LINK_INIT(newc, next); + + newc->name = isc_mem_strdup(mem, name); + if (newc->name == NULL) { + isc_mem_put(mem, newc, sizeof *newc); + return (ISC_R_NOMEMORY); + } + + switch (ctype) { + case dns_c_logchan_file: + newc->u.filec.path = NULL; + break; + + case dns_c_logchan_syslog: + case dns_c_logchan_null: + break; + } + + *newchan = newc; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logchan_delete(dns_c_logchan_t **channel) +{ + dns_c_logchan_t *logc; + + REQUIRE(channel != NULL); + REQUIRE(DNS_C_LOGCHAN_VALID(*channel)); + + logc = *channel; + + isc_mem_free(logc->mem, logc->name); + + switch (logc->ctype) { + case dns_c_logchan_file: + if (logc->u.filec.path != NULL) { + isc_mem_free(logc->mem, logc->u.filec.path); + } + break; + + case dns_c_logchan_syslog: + case dns_c_logchan_null: + break; + } + + *channel = NULL; + + logc->magic = 0; + isc_mem_put(logc->mem, logc, sizeof *logc); + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logchan_copy(isc_mem_t *mem, dns_c_logchan_t **dest, + dns_c_logchan_t *src) +{ + dns_c_logchan_t *logc; + isc_result_t res; + + REQUIRE(dest != NULL); + REQUIRE(DNS_C_LOGCHAN_VALID(src)); + + res = dns_c_logchan_new(mem, src->name, src->ctype, &logc); + if (res != ISC_R_SUCCESS) { + return (res); + } + + logc->severity = src->severity; + logc->debug_level = src->debug_level; + logc->print_category = src->print_category; + logc->print_severity = src->print_severity; + logc->print_time = src->print_time; + logc->setflags = src->setflags; + + switch (logc->ctype) { + case dns_c_logchan_file: + logc->u.filec.path = isc_mem_strdup(mem, src->u.filec.path); + logc->u.filec.versions = src->u.filec.versions; + logc->u.filec.size = src->u.filec.size; + break; + + case dns_c_logchan_syslog: + logc->u.syslogc.facility = src->u.syslogc.facility; + break; + + case dns_c_logchan_null: + break; + } + + *dest = logc; + + return (ISC_R_SUCCESS); +} + + +void +dns_c_logchan_print(FILE *fp, int indent, dns_c_logchan_t *logchan, + isc_boolean_t if_predef_too) +{ + REQUIRE(fp != NULL); + REQUIRE(DNS_C_LOGCHAN_VALID(logchan)); + + if (logchan->predefined && !if_predef_too) { + return; + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "channel %s {\n", logchan->name) ; + + dns_c_printtabs(fp, indent + 1) ; + switch (logchan->ctype) { + case dns_c_logchan_file: + fprintf(fp, "file \"%s\"", + (logchan->u.filec.path == NULL ? + "No path defined" : logchan->u.filec.path)); + + if (DNS_C_CHECKBIT(CHAN_VERSIONS_BIT, &logchan->setflags)) { + fprintf(fp, " versions "); + if (logchan->u.filec.versions == DNS_C_UNLIM_VERSIONS){ + fprintf(fp, "unlimited"); + } else { + fprintf(fp, "%u", logchan->u.filec.versions); + } + } + + if (DNS_C_CHECKBIT(CHAN_SIZE_BIT, &logchan->setflags)) { + fprintf(fp, " size "); + dns_c_printinunits(fp, logchan->u.filec.size); + } + break; + + case dns_c_logchan_syslog: + fprintf(fp, "syslog "); + print_log_facility(fp, logchan->u.syslogc.facility); + break; + + case dns_c_logchan_null: + fputs("null", fp); + break; + } + fprintf(fp, ";\n"); + + if (DNS_C_CHECKBIT(CHAN_SEVERITY_BIT, &logchan->setflags)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "severity "); + print_log_severity(fp, logchan->severity); + if (logchan->severity == dns_c_log_debug && + DNS_C_CHECKBIT(CHAN_DEBUG_LEVEL_BIT, &logchan->setflags)) { + fprintf(fp, " %d", logchan->debug_level); + } + fprintf(fp, ";\n"); + } + + if (DNS_C_CHECKBIT(CHAN_PSEV_BIT, &logchan->setflags)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "print-severity %s;\n", + (logchan->print_severity ? "true" : "false")); + } + + if (DNS_C_CHECKBIT(CHAN_PCAT_BIT, &logchan->setflags)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "print-category %s;\n", + (logchan->print_category ? "true" : "false")); + } + + if (DNS_C_CHECKBIT(CHAN_PTIME_BIT, &logchan->setflags)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "print-time %s;\n", + (logchan->print_time ? "true" : "false")); + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "};\n"); +} + + +isc_result_t +dns_c_logchan_setpath(dns_c_logchan_t *channel, const char *path) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + REQUIRE(path != NULL); + REQUIRE(strlen(path) > 0); + + if (channel->ctype != dns_c_logchan_file) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "This type of channel doesn't have a " + "path field"); + return (ISC_R_FAILURE); + } + + if (channel->u.filec.path != NULL) { + existed = ISC_TRUE; + isc_mem_free(channel->mem, channel->u.filec.path); + } + + channel->u.filec.path = isc_mem_strdup(channel->mem, path); + if (channel->u.filec.path == NULL) { + return (ISC_R_NOMEMORY); + } else { + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); + } +} + + +isc_result_t +dns_c_logchan_setversions(dns_c_logchan_t *channel, isc_uint32_t versions) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + + existed = DNS_C_CHECKBIT(CHAN_VERSIONS_BIT, &channel->setflags); + + if (channel->ctype != dns_c_logchan_file) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "This type of channel doesn't have a " + "version field"); + return (ISC_R_FAILURE); + } + + DNS_C_SETBIT(CHAN_VERSIONS_BIT, &channel->setflags); + channel->u.filec.versions = versions; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logchan_setsize(dns_c_logchan_t *channel, isc_uint32_t size) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + + if (channel->ctype != dns_c_logchan_file) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "This type of channel doesn't have a " + "size field"); + return (ISC_R_FAILURE); + } + + existed = DNS_C_CHECKBIT(CHAN_SIZE_BIT, &channel->setflags); + + DNS_C_SETBIT(CHAN_SIZE_BIT, &channel->setflags); + channel->u.filec.size = size; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logchan_setfacility(dns_c_logchan_t *channel, int facility) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + + if (channel->ctype != dns_c_logchan_syslog) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "This type of channel doesn't have a " + "facility field"); + return (ISC_R_FAILURE); + } + + + if (dns_c_facility2string(facility, ISC_FALSE) == NULL) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Not a legal facility for a syslog channel: %d", + facility); + return (ISC_R_FAILURE); + } + + + existed = DNS_C_CHECKBIT(CHAN_FACILITY_BIT, &channel->setflags); + + DNS_C_SETBIT(CHAN_FACILITY_BIT, &channel->setflags); + channel->u.syslogc.facility = facility; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logchan_setseverity(dns_c_logchan_t *channel, + dns_c_logseverity_t severity) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + + existed = DNS_C_CHECKBIT(CHAN_SEVERITY_BIT, &channel->setflags); + + DNS_C_SETBIT(CHAN_SEVERITY_BIT, &channel->setflags); + channel->severity = severity; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logchan_setdebuglevel(dns_c_logchan_t *channel, isc_int32_t level) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + + if (channel->severity == dns_c_log_debug) { + existed = DNS_C_CHECKBIT(CHAN_DEBUG_LEVEL_BIT, + &channel->setflags); + + DNS_C_SETBIT(CHAN_DEBUG_LEVEL_BIT, &channel->setflags); + channel->debug_level = level; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); + } else { + return (ISC_R_FAILURE); + } +} + + +isc_result_t +dns_c_logchan_setprintcat(dns_c_logchan_t *channel, isc_boolean_t newval) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + + existed = DNS_C_CHECKBIT(CHAN_PCAT_BIT, &channel->setflags); + + DNS_C_SETBIT(CHAN_PCAT_BIT, &channel->setflags); + channel->print_category = newval; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logchan_setprintsev(dns_c_logchan_t *channel, isc_boolean_t newval) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + + existed = DNS_C_CHECKBIT(CHAN_PSEV_BIT, &channel->setflags); + + DNS_C_SETBIT(CHAN_PSEV_BIT, &channel->setflags); + channel->print_severity = newval; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logchan_setprinttime(dns_c_logchan_t *channel, isc_boolean_t newval) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + + existed = DNS_C_CHECKBIT(CHAN_PTIME_BIT, &channel->setflags); + + DNS_C_SETBIT(CHAN_PTIME_BIT, &channel->setflags); + channel->print_time = newval; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + +isc_result_t +dns_c_logchan_setpredef(dns_c_logchan_t *channel, isc_boolean_t newval) +{ + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + + channel->predefined = newval; + + return (ISC_R_SUCCESS); +} + + + + + +isc_result_t +dns_c_logchan_getpath(dns_c_logchan_t *channel, const char **path) +{ + isc_result_t res; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + REQUIRE(path != NULL); + + if (channel->ctype == dns_c_logchan_file && + channel->u.filec.path != NULL) { + *path = channel->u.filec.path; + res = ISC_R_SUCCESS; + } else if (channel->ctype == dns_c_logchan_file) { + res = ISC_R_NOTFOUND; + } else { + res = ISC_R_FAILURE; + } + + return (res); +} + + +isc_result_t +dns_c_logchan_getversions(dns_c_logchan_t *channel, isc_uint32_t *retval) +{ + isc_result_t res; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + REQUIRE(retval != NULL); + + if (channel->ctype == dns_c_logchan_file && + DNS_C_CHECKBIT(CHAN_VERSIONS_BIT, &channel->setflags)) { + *retval = channel->u.filec.versions; + res = ISC_R_SUCCESS; + } else if (channel->ctype == dns_c_logchan_file) { + res = ISC_R_NOTFOUND; + } else { + res = ISC_R_FAILURE; + } + + return (res); +} + + +isc_result_t +dns_c_logchan_getsize(dns_c_logchan_t *channel, isc_uint32_t *retval) +{ + isc_result_t res; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + REQUIRE(retval != NULL); + + if (channel->ctype == dns_c_logchan_file && + DNS_C_CHECKBIT(CHAN_SIZE_BIT, &channel->setflags)) { + *retval = channel->u.filec.size; + res = ISC_R_SUCCESS; + } else if (channel->ctype == dns_c_logchan_file) { + res = ISC_R_NOTFOUND; + } else { + res = ISC_R_FAILURE; + } + + return (res); +} + + +isc_result_t +dns_c_logchan_getfacility(dns_c_logchan_t *channel, int *retval) +{ + isc_result_t res; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + REQUIRE(retval != NULL); + + if (channel->ctype == dns_c_logchan_syslog && + DNS_C_CHECKBIT(CHAN_FACILITY_BIT, &channel->setflags)) { + *retval = channel->u.syslogc.facility; + res = ISC_R_SUCCESS; + } else if (channel->ctype == dns_c_logchan_syslog) { + res = ISC_R_NOTFOUND; + } else { + res = ISC_R_FAILURE; + } + + return (res); + +} + + +isc_result_t +dns_c_logchan_getseverity(dns_c_logchan_t *channel, + dns_c_logseverity_t *retval) +{ + isc_result_t res; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + REQUIRE(retval != NULL); + + if (DNS_C_CHECKBIT(CHAN_SEVERITY_BIT, &channel->setflags)) { + *retval = channel->severity; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_logchan_getdebuglevel(dns_c_logchan_t *channel, isc_int32_t *retval) +{ + isc_result_t res; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + REQUIRE(retval != NULL); + + if (DNS_C_CHECKBIT(CHAN_DEBUG_LEVEL_BIT, &channel->setflags)) { + *retval = channel->debug_level; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_logchan_getprintcat(dns_c_logchan_t *channel, isc_boolean_t *retval) +{ + isc_result_t res; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + REQUIRE(retval != NULL); + + if (DNS_C_CHECKBIT(CHAN_PCAT_BIT, &channel->setflags)) { + *retval = channel->print_category; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_logchan_getprintsev(dns_c_logchan_t *channel, isc_boolean_t *retval) +{ + isc_result_t res; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + REQUIRE(retval != NULL); + + if (DNS_C_CHECKBIT(CHAN_PSEV_BIT, &channel->setflags)) { + *retval = channel->print_severity; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); + +} + + +isc_result_t +dns_c_logchan_getprinttime(dns_c_logchan_t *channel, isc_boolean_t *retval) +{ + isc_result_t res; + + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + REQUIRE(retval != NULL); + + if (DNS_C_CHECKBIT(CHAN_PTIME_BIT, &channel->setflags)) { + *retval = channel->print_time; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_logchan_getpredef(dns_c_logchan_t *channel, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_LOGCHAN_VALID(channel)); + REQUIRE(retval != NULL); + + *retval = channel->predefined; + + return (ISC_R_SUCCESS); +} + + +/* + * Logging category + */ +isc_result_t +dns_c_logcat_new(isc_mem_t *mem, dns_c_category_t cat, dns_c_logcat_t **newlc) +{ + dns_c_logcat_t *newc; + unsigned int i; + + REQUIRE(newlc != NULL); + + newc = isc_mem_get(mem, sizeof *newc); + if (newc == NULL) { + return (ISC_R_NOMEMORY); + } + + newc->magic = DNS_C_LOGCAT_MAGIC; + newc->mem = mem; + newc->category = cat; + newc->cnames_len = 2; + newc->nextcname = 0; + newc->predefined = ISC_FALSE; + newc->channel_names = isc_mem_get(mem, + sizeof (char *) * newc->cnames_len); + if (newc->channel_names == NULL) { + isc_mem_put(mem, newc, sizeof *newc); + return (ISC_R_NOMEMORY); + } + + for (i = 0 ; i < newc->cnames_len ; i++) { + newc->channel_names[i] = NULL; + } + + *newlc = newc; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logcat_delete(dns_c_logcat_t **logcat) +{ + dns_c_logcat_t *logc; + unsigned int i; + + REQUIRE(logcat != NULL); + REQUIRE(DNS_C_LOGCAT_VALID(*logcat)); + + logc = *logcat; + if (logc == NULL) { + return (ISC_R_SUCCESS); + } + + for (i = 0 ; i < logc->nextcname ; i++) { + REQUIRE(logc->channel_names[i] != NULL); + + isc_mem_free(logc->mem, logc->channel_names[i]); + } + + logc->magic = 0; + isc_mem_put(logc->mem, logc->channel_names, + sizeof (char *) * logc->cnames_len); + isc_mem_put(logc->mem, logc, sizeof *logc); + + *logcat = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logcat_copy(isc_mem_t *mem, dns_c_logcat_t **dest, dns_c_logcat_t *src) +{ + unsigned int i; + dns_c_logcat_t *newc; + isc_result_t res; + + REQUIRE(dest != NULL); + REQUIRE(DNS_C_LOGCAT_VALID(src)); + + res = dns_c_logcat_new(mem, src->category, &newc); + if (res != ISC_R_SUCCESS) { + return (res); + } + + for (i = 0 ; i < src->nextcname ; i++) { + res = dns_c_logcat_addname(newc, src->channel_names[i]); + if (res != ISC_R_SUCCESS) { + dns_c_logcat_delete(&newc); + return (res); + } + } + + return (ISC_R_SUCCESS); +} + + +void +dns_c_logcat_print(FILE *fp, int indent, dns_c_logcat_t *logcat, + isc_boolean_t if_predef_too) +{ + unsigned int i; + + REQUIRE(fp != NULL); + REQUIRE(DNS_C_LOGCAT_VALID(logcat)); + + if (logcat->predefined && !if_predef_too) { + return; + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "category "); + print_log_category(fp, logcat->category); + fprintf(fp, " {\n"); + + for (i = 0 ; i < logcat->nextcname ; i++) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "%s;\n", logcat->channel_names[i]); + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "};\n"); +} + + +isc_result_t +dns_c_logcat_addname(dns_c_logcat_t *logcat, const char *name) +{ + unsigned int i; + + REQUIRE(DNS_C_LOGCAT_VALID(logcat)); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + + if (logcat->cnames_len == logcat->nextcname) { + size_t newsize = logcat->cnames_len + 5; + char **newarr = isc_mem_get(logcat->mem, + newsize * sizeof (char *)); + + if (newarr == NULL) { + return (ISC_R_NOMEMORY); + } + + for (i = 0 ; i < newsize ; i++) { + if (i < logcat->cnames_len) { + newarr[i] = logcat->channel_names[i]; + } else { + newarr[i] = NULL; + } + } + + isc_mem_put(logcat->mem, logcat->channel_names, + sizeof (char *) * logcat->cnames_len); + + logcat->channel_names = newarr; + logcat->cnames_len = newsize; + } + + logcat->channel_names[logcat->nextcname] = + isc_mem_strdup(logcat->mem, name); + if (logcat->channel_names[logcat->nextcname] == NULL) { + return (ISC_R_NOMEMORY); + } + + logcat->nextcname++; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logcat_delname(dns_c_logcat_t *logcat, const char *name) +{ + unsigned int i ; + isc_result_t res; + + REQUIRE(DNS_C_LOGCAT_VALID(logcat)); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + + for (i = 0 ; i < logcat->nextcname ; i++) { + INSIST(logcat->channel_names[i] != NULL); + if (strcmp(logcat->channel_names[i], name) == 0) { + break; + } + } + + if (i < logcat->nextcname) { + res = ISC_R_SUCCESS; + isc_mem_free(logcat->mem, logcat->channel_names[i]); + while (i < (logcat->nextcname - 1)) { + logcat->channel_names[i] = logcat->channel_names[i+1]; + i++; + } + } else { + res = ISC_R_NOTFOUND; + } + + + return (res); +} + + + +isc_result_t +dns_c_logcat_setpredef(dns_c_logcat_t *logcat,isc_boolean_t newval) +{ + REQUIRE(DNS_C_LOGCAT_VALID(logcat)); + + logcat->predefined = newval; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_logcat_getpredef(dns_c_logcat_t *logcat, isc_boolean_t *retval) +{ + REQUIRE(DNS_C_LOGCAT_VALID(logcat)); + REQUIRE(retval != NULL); + + *retval = logcat->predefined; + + return (ISC_R_SUCCESS); +} + + + + +/***************************************************************************/ + + +static void +print_log_facility(FILE *fp, int value) +{ + REQUIRE(fp != NULL); + + fputs(dns_c_facility2string(value, ISC_TRUE), fp); +} + + +static void +print_log_severity(FILE *fp, dns_c_logseverity_t severity) +{ + REQUIRE(fp != NULL); + + fputs(dns_c_logseverity2string(severity, ISC_TRUE), fp); +} + + +static void +print_log_category(FILE *fp, dns_c_category_t category) +{ + REQUIRE(fp != NULL); + + fputs(dns_c_category2string(category, ISC_TRUE), fp); +} + diff --git a/lib/dns/config/conflsn.c b/lib/dns/config/conflsn.c new file mode 100644 index 00000000..35ef6a8d --- /dev/null +++ b/lib/dns/config/conflsn.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <isc/assertions.h> +#include <isc/magic.h> + +#include <dns/conflsn.h> +#include <dns/confcommon.h> + +#include "confpvt.h" + + +isc_result_t +dns_c_lstnon_new(isc_mem_t *mem, dns_c_lstnon_t **listen) +{ + dns_c_lstnon_t *ll; + isc_result_t result; + + REQUIRE(listen != NULL); + + *listen = NULL; + + ll = isc_mem_get(mem, sizeof *ll); + ll->mem = mem; + ll->port = 0; + ll->magic = DNS_C_LISTEN_MAGIC; + + result = dns_c_ipmatchlist_new(mem, &ll->iml); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mem, ll, sizeof *ll); + return (result); + } + + ISC_LINK_INIT(ll, next); + + *listen = ll; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_lstnon_delete(dns_c_lstnon_t **listen) +{ + dns_c_lstnon_t *lo; + isc_result_t r; + + REQUIRE(listen != NULL); + REQUIRE(DNS_C_LISTEN_VALID(*listen)); + + lo = *listen; + + if (lo->iml != NULL) { + r = dns_c_ipmatchlist_detach(&lo->iml); + } else { + r = ISC_R_SUCCESS; + } + + lo->magic = 0; + isc_mem_put(lo->mem, lo, sizeof *lo); + + *listen = NULL; + + return (r); +} + + +isc_result_t +dns_c_lstnon_setiml(dns_c_lstnon_t *listen, + dns_c_ipmatchlist_t *iml, isc_boolean_t deepcopy) +{ + isc_result_t result; + + REQUIRE(DNS_C_LISTEN_VALID(listen)); + REQUIRE(DNS_C_IPMLIST_VALID(iml)); + + if (listen->iml != NULL) { + result = dns_c_ipmatchlist_detach(&listen->iml); + if (result != ISC_R_SUCCESS) { + return (result); + } + } else { + result = ISC_R_SUCCESS; + } + + + if (deepcopy) { + result = dns_c_ipmatchlist_copy(listen->mem, + &listen->iml, iml); + } else { + listen->iml = iml; + } + + return (result); +} + + + + + + + +isc_result_t +dns_c_lstnlist_new(isc_mem_t *mem, dns_c_lstnlist_t **llist) +{ + dns_c_lstnlist_t *ll; + + REQUIRE(llist != NULL); + + *llist = NULL; + + ll = isc_mem_get(mem, sizeof *ll); + if (ll == NULL) { + /* XXXJAB logwrite */ + return (ISC_R_NOMEMORY); + } + + ll->mem = mem; + ll->magic = DNS_C_LLIST_MAGIC; + ISC_LIST_INIT(ll->elements); + + *llist = ll; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_lstnlist_delete(dns_c_lstnlist_t **llist) +{ + dns_c_lstnlist_t *ll; + dns_c_lstnon_t *lo, *lotmp; + isc_result_t r; + + REQUIRE(llist != NULL); + REQUIRE(DNS_C_LISTENLIST_VALID(*llist)); + + ll = *llist; + + lo = ISC_LIST_HEAD(ll->elements); + while (lo != NULL) { + lotmp = ISC_LIST_NEXT(lo, next); + ISC_LIST_UNLINK(ll->elements, lo, next); + r = dns_c_lstnon_delete(&lo); + if (r != ISC_R_SUCCESS) { + return (r); + } + + lo = lotmp; + } + + ll->magic = 0; + isc_mem_put(ll->mem, ll, sizeof *ll); + + *llist = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_lstnlist_print(FILE *fp, int indent, + dns_c_lstnlist_t *ll) +{ + dns_c_lstnon_t *lo; + + REQUIRE(DNS_C_LISTENLIST_VALID(ll)); + + lo = ISC_LIST_HEAD(ll->elements); + while (lo != NULL) { + dns_c_printtabs(fp, indent); + dns_c_lstnon_print(fp, indent, lo); + lo = ISC_LIST_NEXT(lo, next); + fprintf(fp, "\n"); + } + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_lstnon_print(FILE *fp, int indent, dns_c_lstnon_t *lo) +{ + REQUIRE(lo != NULL); + REQUIRE(DNS_C_LISTEN_VALID(lo)); + + fprintf(fp, "listen-on "); + if (lo->port != DNS_C_DEFAULTPORT) { + fprintf(fp, "port %d ", lo->port); + } + + dns_c_ipmatchlist_print(fp, indent + 1, lo->iml); + fprintf(fp, ";\n"); + + return (ISC_R_SUCCESS); +} + diff --git a/lib/dns/config/confparser.y b/lib/dns/config/confparser.y new file mode 100644 index 00000000..6bcf7f37 --- /dev/null +++ b/lib/dns/config/confparser.y @@ -0,0 +1,4508 @@ +%{ +/* + * Copyright (c) 1996-1999 by 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. + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: confparser.y,v 1.37 2000/02/02 00:38:11 halley Exp $"; +#endif /* not lint */ + +#include <config.h> + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <string.h> +#include <sys/types.h> + +#include <syslog.h> + +#include <isc/assertions.h> +#include <isc/error.h> +#include <isc/mutex.h> +#include <isc/lex.h> +#include <isc/symtab.h> +#include <isc/error.h> +#include <isc/once.h> +#include <isc/dir.h> +#include <isc/net.h> + +#include <dns/confparser.h> +#include <dns/confctx.h> +#include <dns/log.h> + +#include <dns/result.h> +#include <dns/rdatatype.h> +#include <dns/rdataclass.h> + +#include <dns/types.h> + +#include <dns/confcommon.h> + + +/* Type keys for symtab lookup */ +#define KEYWORD_SYM_TYPE 0x1 +#define CLASS_SYM_TYPE 0x2 +#define ACL_SYM_TYPE 0x3 + + +static isc_mutex_t yacc_mutex; + +/* All these statics are protected by the above yacc_mutex */ +static dns_c_ctx_t *currcfg; +static isc_mem_t *memctx; /* used for internal allocations */ +static isc_lex_t *mylexer; +static isc_symtab_t *keywords; +static dns_c_cbks_t *callbacks; +static isc_lexspecials_t specials; + +#define CONF_MAX_IDENT 1024 + +/* This should be sufficient to permit multiple parsers and lexers if needed */ +#define yyparse confyyparse +#define yylex confyylex + +#define YYDEBUG 1 + +static isc_result_t tmpres; +static int debug_lexer; + +static void parser_error(isc_boolean_t lasttoken, + const char *fmt, ...); +static void parser_warning(isc_boolean_t lasttoken, + const char *fmt, ...); +static void parser_complain(isc_boolean_t is_warning, + isc_boolean_t last_token, + const char *format, va_list args); +static isc_boolean_t unit_to_uint32(char *in, isc_uint32_t *out); +static void yyerror(const char *); + +/* returns true if (base * mult) would be too big.*/ +static isc_boolean_t int_too_big(isc_uint32_t base, isc_uint32_t mult); + +%} + +%union { + char *text; + int number; + isc_int32_t l_int; + isc_uint32_t ul_int; + isc_uint16_t port_int; + dns_c_zonetype_t ztype; + struct in_addr ip4_addr; + struct in6_addr ip6_addr; + isc_sockaddr_t ipaddress; + + isc_boolean_t boolean; + dns_rdataclass_t rrclass; + dns_severity_t severity; + dns_c_trans_t transport; + dns_transfer_format_t tformat; + dns_c_category_t logcat; + + dns_c_ipmatchelement_t *ime; + dns_c_ipmatchlist_t *iml; + + dns_c_forw_t forward; + dns_c_rrso_t *rrorder; + dns_c_rrsolist_t *rrolist; + dns_rdatatype_t ordertype; + dns_rdataclass_t orderclass; + dns_c_ordering_t ordering; + dns_c_iplist_t *iplist; +} + +/* Misc */ +%token <text> L_STRING +%token <text> L_QSTRING +%token <l_int> L_INTEGER +%token <ip4_addr> L_IP4ADDR +%token <ip6_addr> L_IP6ADDR + +%token L_LBRACE +%token L_RBRACE +%token L_EOS +%token L_SLASH +%token L_BANG +%token L_QUOTE + +%token L_MASTER +%token L_SLAVE +%token L_SORTLIST +%token L_HINT +%token L_STUB +%token L_FORWARD + +%token L_INCLUDE +%token L_END_INCLUDE + +%token L_OPTIONS +%token L_DIRECTORY +%token L_DIRECTORY +%token L_PIDFILE +%token L_NAMED_XFER +%token L_TKEY_DOMAIN +%token L_TKEY_DHKEY +%token L_DUMP_FILE +%token L_STATS_FILE +%token L_MEMSTATS_FILE +%token L_FAKE_IQUERY +%token L_RECURSION +%token L_FETCH_GLUE +%token L_QUERY_SOURCE +%token L_LISTEN_ON +%token L_PORT +%token L_ACL +%token L_ADDRESS +%token L_ALGID +%token L_ALLOW_QUERY +%token L_ALLOW_TRANSFER +%token L_ALLOW_UPDATE +%token L_ALLOW_RECURSION +%token L_ALSO_NOTIFY +%token L_BLACKHOLE +%token L_BOGUS +%token L_CATEGORY +%token L_CHANNEL +%token L_CHECK_NAMES +%token L_DEBUG +%token L_DIALUP +%token L_DYNAMIC +%token L_FAIL +%token L_FIRST +%token L_FORWARDERS +%token L_IF_NO_ANSWER +%token L_IF_NO_DOMAIN +%token L_IGNORE +%token L_FILE_IXFR +%token L_IXFR_TMP +%token L_SEC_KEY +%token L_KEYS +%token L_LOGGING +%token L_MASTERS +%token L_NULL_OUTPUT +%token L_ONLY +%token L_PRINT_CATEGORY +%token L_PRINT_SEVERITY +%token L_PRINT_TIME +%token L_PUBKEY +%token L_RESPONSE +%token L_SECRET +%token L_SERVER +%token L_SEVERITY +%token L_SIZE +%token L_SUPPORT_IXFR +%token L_SYSLOG +%token L_TOPOLOGY +%token L_TRANSFER_SOURCE +%token L_TRANSFERS +%token L_TRUSTED_KEYS +%token L_VERSIONS +%token L_WARN +%token L_RRSET_ORDER +%token L_ORDER +%token L_NAME +%token L_CLASS +%token L_CONTROLS +%token L_INET +%token L_UNIX +%token L_PERM +%token L_OWNER +%token L_GROUP +%token L_ALLOW +%token L_DATASIZE +%token L_STACKSIZE +%token L_CORESIZE +%token L_DEFAULT +%token L_UNLIMITED +%token L_FILES +%token L_VERSION +%token L_HOSTSTATS +%token L_DEALLOC_ON_EXIT +%token L_TRANSFERS_IN +%token L_TRANSFERS_OUT +%token L_TRANSFERS_PER_NS +%token L_TRANSFER_FORMAT +%token L_MAX_TRANSFER_TIME_IN +%token L_MAX_TRANSFER_TIME_OUT +%token L_MAX_TRANSFER_IDLE_IN +%token L_MAX_TRANSFER_IDLE_OUT +%token L_TCP_CLIENTS +%token L_RECURSIVE_CLIENTS +%token L_ONE_ANSWER +%token L_MANY_ANSWERS +%token L_NOTIFY +%token L_AUTH_NXDOMAIN +%token L_MULTIPLE_CNAMES +%token L_USE_IXFR +%token L_MAINTAIN_IXFR_BASE +%token L_CLEAN_INTERVAL +%token L_INTERFACE_INTERVAL +%token L_STATS_INTERVAL +%token L_MAX_LOG_SIZE_IXFR +%token L_HEARTBEAT +%token L_USE_ID_POOL +%token L_MAX_NCACHE_TTL +%token L_HAS_OLD_CLIENTS +%token L_EXPERT_MODE +%token L_ZONE +%token L_TYPE +%token L_FILE +%token L_YES +%token L_TRUE +%token L_NO +%token L_FALSE +%token L_VIEW +%token L_RFC2308_TYPE1 + +%type <boolean> yea_or_nay + +%type <forward> forward_opt +%type <forward> zone_forward_opt + +%type <ime> address_match_element +%type <ime> address_match_simple +%type <ime> address_name + +%type <iml> address_match_list + +%type <ipaddress> in_addr_elem +%type <ipaddress> ip4_address +%type <ipaddress> ip6_address +%type <ipaddress> ip_address +%type <ipaddress> maybe_wild_addr + +%type <iplist> in_addr_list +%type <iplist> master_in_addr_list +%type <iplist> master_in_addr_list +%type <iplist> master_in_addr_list +%type <iplist> notify_in_addr_list +%type <iplist> opt_in_addr_list +%type <iplist> opt_zone_forwarders_list + +%type <logcat> category_name + +%type <number> facility_name +%type <number> maybe_syslog_facility + +%type <orderclass> ordering_class + +%type <ordertype> ordering_type + +%type <port_int> in_port +%type <port_int> maybe_port +%type <port_int> maybe_wild_port +%type <port_int> maybe_zero_port + +%type <rrclass> class_name +%type <rrclass> optional_class + +%type <severity> check_names_opt; + +/* %type <text> optional_string */ +%type <text> algorithm_id +%type <text> any_string +%type <text> channel_name +%type <text> domain_name +%type <text> key_ref +%type <text> ordering_name +%type <text> secret + +%type <tformat> transfer_format + +%type <transport> check_names_type; + +%type <ul_int> size_spec + +%type <ztype> zone_type + +/* Miscellaneous items (used in several places): */ + +%% + +config_file: statement_list + ; + +statement_list: statement + | statement_list statement + ; + +statement: include_stmt L_EOS + | options_stmt L_EOS + | controls_stmt L_EOS + | logging_stmt L_EOS + | server_stmt L_EOS + | zone_stmt L_EOS + | trusted_keys_stmt L_EOS + | acl_stmt L_EOS + | key_stmt L_EOS + | view_stmt L_EOS + | L_END_INCLUDE + ; + + +include_stmt: L_INCLUDE L_QSTRING + { + if (isc_lex_openfile(mylexer, $2) != ISC_R_SUCCESS) { + parser_error(ISC_FALSE ,"Can't open file %s", $2); + YYABORT; + } + + isc_mem_free(memctx, $2); + } + ; + +options_stmt: L_OPTIONS + { + dns_c_options_t *options; + + tmpres = dns_c_ctx_getoptions(currcfg, &options); + if (tmpres == ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Cannot redefine options"); + + /* + * Clean out options so rest of config won't fail + * or issue extra error messages + */ + dns_c_ctx_optionsdelete(&currcfg->options); + } + + tmpres = dns_c_ctx_optionsnew(currcfg->mem, &currcfg->options); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create options structure: %s", + isc_result_totext(tmpres)); + YYABORT; + } + + } L_LBRACE options L_RBRACE { + if (callbacks != NULL && callbacks->optscbk != NULL) { + tmpres = callbacks->optscbk(currcfg, + callbacks->optscbkuap); + if (tmpres != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_ERROR, + "options configuration failed: %s", + isc_result_totext(tmpres)); + YYABORT; + } + } + } + ; + +options: option L_EOS + | options option L_EOS + ; + + +option: /* Empty */ + | L_VERSION L_QSTRING + { + tmpres = dns_c_ctx_setversion(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining version."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "set version error %s: %s", + isc_result_totext(tmpres), $2); + YYABORT; + } + + isc_mem_free(memctx, $2); + } + | L_DIRECTORY L_QSTRING + { + tmpres = dns_c_ctx_setdirectory(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining directory"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "error setting directory: %s: %s", + isc_result_totext(tmpres), $2); + YYABORT; + } + + isc_mem_free(memctx, $2); + } + | L_NAMED_XFER L_QSTRING + { + tmpres = dns_c_ctx_setnamedxfer(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining named-xfer"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "set named-xfer error: %s: %s", + isc_result_totext(tmpres), $2); + YYABORT; + } + + isc_mem_free(memctx, $2); + } + | L_TKEY_DOMAIN L_QSTRING + { + tmpres = dns_c_ctx_settkeydomain(currcfg, $2); + + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining tkey-domain"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "set tkey-domain error: %s: %s", + isc_result_totext(tmpres), $2); + YYABORT; + } + + isc_mem_free(memctx, $2); + } + | L_TKEY_DHKEY L_QSTRING L_INTEGER + { + tmpres = dns_c_ctx_settkeydhkey(currcfg, $2, $3); + + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining tkey-dhkey"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "set tkey-dhkey error: %s: %s", + isc_result_totext(tmpres), $2); + YYABORT; + } + + isc_mem_free(memctx, $2); + } + | L_PIDFILE L_QSTRING + { + tmpres = dns_c_ctx_setpidfilename(currcfg, $2); + + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining pid-file"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "set pidfile error %s: %s", + isc_result_totext(tmpres), $2); + YYABORT; + } + + isc_mem_free(memctx, $2); + } + | L_STATS_FILE L_QSTRING + { + tmpres = dns_c_ctx_setstatsfilename(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining statistics-file"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "set statsfile error %s: %s", + isc_result_totext(tmpres), $2); + YYABORT; + } + + isc_mem_free(memctx, $2); + } + | L_MEMSTATS_FILE L_QSTRING + { + tmpres = dns_c_ctx_setmemstatsfilename(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining memstatistics-file"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "set memstatsfile error %s: %s", + isc_result_totext(tmpres), $2); + YYABORT; + } + + isc_mem_free(memctx, $2); + } + | L_DUMP_FILE L_QSTRING + { + tmpres = dns_c_ctx_setdumpfilename(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining dump-file"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "set dumpfile error %s: %s", + isc_result_totext(tmpres), $2); + YYABORT; + } + + isc_mem_free(memctx, $2); + } + | L_EXPERT_MODE yea_or_nay + { + tmpres = dns_c_ctx_setexpertmode(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining expert-mode."); + } + } + | L_FAKE_IQUERY yea_or_nay + { + tmpres = dns_c_ctx_setfakeiquery(currcfg, ISC_FALSE); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining fake-iquery."); + } + } + | L_RECURSION yea_or_nay + { + tmpres = dns_c_ctx_setrecursion(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining recursion"); + } + } + | L_FETCH_GLUE yea_or_nay + { + tmpres = dns_c_ctx_setfetchglue(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining fetch-glue."); + } + } + | L_NOTIFY yea_or_nay + { + tmpres = dns_c_ctx_setnotify(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining notify."); + } + } + | L_HOSTSTATS yea_or_nay + { + tmpres = dns_c_ctx_sethoststatistics(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining host-statistics."); + } + } + | L_DEALLOC_ON_EXIT yea_or_nay + { + tmpres = dns_c_ctx_setdealloconexit(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining deallocate-on-exit."); + } + } + | L_USE_IXFR yea_or_nay + { + tmpres = dns_c_ctx_setuseixfr(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining use-ixfr."); + } + } + | L_MAINTAIN_IXFR_BASE yea_or_nay + { + tmpres = dns_c_ctx_setmaintainixfrbase(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining maintain-ixfr-base."); + } + } + | L_HAS_OLD_CLIENTS yea_or_nay + { + tmpres = dns_c_ctx_sethasoldclients(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining has-old-clients."); + } + } + | L_AUTH_NXDOMAIN yea_or_nay + { + tmpres = dns_c_ctx_setauthnxdomain(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining auth-nxdomain."); + } + } + | L_MULTIPLE_CNAMES yea_or_nay + { + tmpres = dns_c_ctx_setmultiplecnames(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining multiple-cnames."); + } + } + | L_CHECK_NAMES check_names_type check_names_opt + { + tmpres = dns_c_ctx_setchecknames(currcfg, $2, $3); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining check-names."); + } + } + | L_USE_ID_POOL yea_or_nay + { + tmpres = dns_c_ctx_setuseidpool(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining use-id-pool."); + } + } + | L_RFC2308_TYPE1 yea_or_nay + { + tmpres = dns_c_ctx_setrfc2308type1(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining rfc2308-type."); + } + } + | L_LISTEN_ON maybe_port L_LBRACE address_match_list L_RBRACE + { + if ($4 == NULL) { + parser_warning(ISC_FALSE, + "address-match-list empty. " + "listen statement ignored."); + } else { + tmpres = dns_c_ctx_addlisten_on(currcfg, $2, $4, + ISC_FALSE); + + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to add listen statement"); + YYABORT; + } + } + } + | L_FORWARD forward_opt + { + tmpres = dns_c_ctx_setforward(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining forward"); + } + } + | L_FORWARDERS { + dns_c_iplist_t *forwarders; + + tmpres = dns_c_ctx_getforwarders(currcfg, &forwarders); + if (tmpres != ISC_R_NOTFOUND) { + parser_error(ISC_FALSE, + "Redefining options forwarders"); + dns_c_iplist_detach(&forwarders); + } + + tmpres = dns_c_iplist_new(currcfg->mem, 5, &forwarders); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create " + "forwarders list"); + YYABORT; + } + + tmpres = dns_c_ctx_setforwarders(currcfg, ISC_FALSE, + forwarders); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set forwarders list."); + YYABORT; + } + } L_LBRACE opt_forwarders_list L_RBRACE + | L_QUERY_SOURCE query_source + | L_TRANSFER_SOURCE maybe_wild_addr + { + tmpres = dns_c_ctx_settransfersource(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining transfer-source"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set transfer-source"); + YYABORT; + } + } + | L_ALLOW_QUERY L_LBRACE address_match_list L_RBRACE + { + if ($3 == NULL) + YYABORT; + tmpres = dns_c_ctx_setqueryacl(currcfg, ISC_FALSE, $3); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining allow-query list"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Failed to set allow-query"); + YYABORT; + } + } + | L_ALLOW_TRANSFER L_LBRACE address_match_list L_RBRACE + { + tmpres = dns_c_ctx_settransferacl(currcfg, ISC_FALSE, $3); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining allow-transfer list"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set allow-transfer"); + YYABORT; + } + } + | L_ALLOW_RECURSION L_LBRACE address_match_list L_RBRACE + { + tmpres = dns_c_ctx_setrecursionacl(currcfg, ISC_FALSE, $3); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining allow-recursion list"); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set allow-recursion"); + YYABORT; + } + } + | L_SORTLIST L_LBRACE address_match_list L_RBRACE + { + tmpres = dns_c_ctx_setsortlist(currcfg, ISC_FALSE, $3); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining sortlist."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Failed to set sortlist"); + YYABORT; + } + } + | L_ALSO_NOTIFY L_LBRACE notify_in_addr_list L_RBRACE + { + tmpres = dns_c_ctx_setalsonotify(currcfg, $3, ISC_FALSE); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining also-notify."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Failed to set also-notify"); + YYABORT; + } + } + | L_BLACKHOLE L_LBRACE address_match_list L_RBRACE + { + tmpres = dns_c_ctx_setblackhole(currcfg, ISC_FALSE, $3); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining blackhole."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Failed to set blackhole"); + YYABORT; + } + } + | L_TOPOLOGY L_LBRACE address_match_list L_RBRACE + { + tmpres = dns_c_ctx_settopology(currcfg, ISC_FALSE, $3); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining topology."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Failed to set topology."); + YYABORT; + } + } + | size_clause + | transfer_clause + | L_TRANSFER_FORMAT transfer_format + { + tmpres = dns_c_ctx_settransferformat(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining transfer-format."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set transfer-format."); + YYABORT; + } + } + | L_MAX_TRANSFER_TIME_IN L_INTEGER + { + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_ctx_setmaxtransfertimein(currcfg, $2 * 60); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining max-transfer-time-in."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set max-transfer-time-in."); + YYABORT; + } + } + | L_MAX_TRANSFER_TIME_OUT L_INTEGER + { + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_ctx_setmaxtransfertimeout(currcfg, $2 * 60); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining max-transfer-time-out."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set max-transfer-time-out."); + YYABORT; + } + } + | L_MAX_TRANSFER_IDLE_IN L_INTEGER + { + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_ctx_setmaxtransferidlein(currcfg, $2 * 60); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining max-transfer-idle-in."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set max-transfer-idle-in."); + YYABORT; + } + } + | L_MAX_TRANSFER_IDLE_OUT L_INTEGER + { + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_ctx_setmaxtransferidleout(currcfg, $2 * 60); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining max-transfer-idle-out."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set max-transfer-idle-out."); + YYABORT; + } + } + | L_TCP_CLIENTS L_INTEGER + { + tmpres = dns_c_ctx_settcpclients(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining tcp-clients."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set tcp-clients."); + YYABORT; + } + } + | L_RECURSIVE_CLIENTS L_INTEGER + { + tmpres = dns_c_ctx_setrecursiveclients(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining recursive-clients."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set recursive-clients."); + YYABORT; + } + } + | L_CLEAN_INTERVAL L_INTEGER + { + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_ctx_setcleaninterval(currcfg, $2 * 60); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining cleaning-interval."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set cleaning-interval."); + YYABORT; + } + } + | L_INTERFACE_INTERVAL L_INTEGER + { + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_ctx_setinterfaceinterval(currcfg, $2 * 60); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining interface-interval."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set interface-interval."); + YYABORT; + } + } + | L_STATS_INTERVAL L_INTEGER + { + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_ctx_setstatsinterval(currcfg, $2 * 60); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining statistics-interval."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set statistics-interval."); + YYABORT; + } + } + | L_MAX_LOG_SIZE_IXFR L_INTEGER + { + tmpres = dns_c_ctx_setmaxlogsizeixfr(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining max-ixfr-log-size."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set max-ixfr-log-size."); + YYABORT; + } + } + | L_MAX_NCACHE_TTL L_INTEGER + { + tmpres = dns_c_ctx_setmaxncachettl(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining max-ncache-ttl."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set max-ncache-ttl."); + YYABORT; + } + } + | L_HEARTBEAT L_INTEGER + { + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_ctx_setheartbeat_interval(currcfg, $2 * 60); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining heartbeat-interval."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set heartbeat-interval."); + YYABORT; + } + } + | L_DIALUP yea_or_nay + { + tmpres = dns_c_ctx_setdialup(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining dialup."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Failed to set dialup."); + YYABORT; + } + } + | L_RRSET_ORDER + { + dns_c_rrsolist_t *ordering; + + tmpres = dns_c_ctx_getrrsetorderlist(currcfg, &ordering); + if (tmpres != ISC_R_NOTFOUND) { + parser_error(ISC_FALSE, + "Redefining rrset-order list"); + dns_c_rrsolist_clear(ordering); + } else { + tmpres = dns_c_rrsolist_new(currcfg->mem, &ordering); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create rrset-order " + "list"); + YYABORT; + } + tmpres = dns_c_ctx_setrrsetorderlist(currcfg, + ISC_FALSE, + ordering); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set rrset-order."); + YYABORT; + } + } + } L_LBRACE rrset_ordering_list L_RBRACE + ; + + +/* + * Controls. + */ +controls_stmt: L_CONTROLS + { + if (currcfg->controls != NULL) { + parser_error(ISC_FALSE, "Redefining controls"); + dns_c_ctrllist_delete(&currcfg->controls); + } + + tmpres = dns_c_ctrllist_new(currcfg->mem, + &currcfg->controls); + if (tmpres != ISC_R_SUCCESS) { + YYABORT; + } + } L_LBRACE controls L_RBRACE + ; + +controls: control L_EOS + | controls control L_EOS + ; + +control: /* Empty */ + | L_INET maybe_wild_addr L_PORT in_port + L_ALLOW L_LBRACE address_match_list L_RBRACE + { + dns_c_ctrl_t *control; + + tmpres = dns_c_ctrlinet_new(currcfg->mem, &control, + $2, $4, $7, ISC_FALSE); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to build inet control structure"); + YYABORT; + } + + ISC_LIST_APPEND(currcfg->controls->elements, control, next); + } + | L_UNIX L_QSTRING L_PERM L_INTEGER L_OWNER L_INTEGER L_GROUP L_INTEGER + { + dns_c_ctrl_t *control; + + tmpres = dns_c_ctrlunix_new(currcfg->mem, &control, + $2, $4, $6, $8); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to build unix control structure"); + YYABORT; + } + + ISC_LIST_APPEND(currcfg->controls->elements, control, next); + + isc_mem_free(memctx, $2); + } + ; + +rrset_ordering_list: rrset_ordering_element L_EOS + | rrset_ordering_list rrset_ordering_element L_EOS + ; + +ordering_class: /* nothing */ + { + $$ = dns_rdataclass_any; + } + | L_CLASS class_name + { + $$ = $2; + } + ; + +ordering_type: /* nothing */ + { + $$ = dns_rdatatype_any; + } + | L_TYPE any_string + { + isc_textregion_t reg; + dns_rdatatype_t ty; + + if (strcmp($2, "*") == 0) { + ty = dns_rdatatype_any; + } else { + reg.base = $2; + reg.length = strlen($2); + + tmpres = dns_rdatatype_fromtext(&ty, ®); + if (tmpres != DNS_R_SUCCESS) { + parser_warning(ISC_TRUE, + "Unknown type. Assuming ``*''"); + ty = dns_rdatatype_any; + } + } + + isc_mem_free(memctx, $2); + $$ = ty; + } + ; + + +ordering_name: /* nothing */ + { + $$ = isc_mem_strdup(memctx, "*"); + } + | L_NAME domain_name + { + $$ = $2; + } + + +rrset_ordering_element: ordering_class ordering_type ordering_name + L_ORDER L_STRING + { + dns_c_rrso_t *orderelem; + dns_c_ordering_t o; + + tmpres = dns_c_string2ordering($5, &o); + if (tmpres != ISC_R_SUCCESS) { + parser_warning(ISC_FALSE, + "Unknown ordering type ``%s''." + " Using default", $5); + o = DNS_DEFAULT_ORDERING; + } + + tmpres = dns_c_rrso_new(currcfg->mem, + &orderelem, $1, $2, $3, o); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create rrset-order element"); + YYABORT; + } + + ISC_LIST_APPEND(currcfg->options->ordering->elements, + orderelem, next); + + isc_mem_free(memctx, $5); + isc_mem_free(memctx, $3); + } + + +transfer_format: L_ONE_ANSWER + { + $$ = dns_one_answer; + } + | L_MANY_ANSWERS + { + $$ = dns_many_answers; + } + ; + + +maybe_wild_addr: ip_address + { + $$ = $1; + } + | L_STRING + { + struct in_addr any; + any.s_addr = htonl(INADDR_ANY); + isc_sockaddr_fromin(&$$, &any, 0); + + if (strcmp($1, "*") != 0) { + parser_error(ISC_TRUE, "Bad ip-address. Using ``*''"); + } + + isc_mem_free(memctx, $1); + } + ; + +maybe_wild_port: in_port + { + $$ = $1; + } + | L_STRING + { + $$ = 0; + + if (strcmp ($1, "*") != 0) { + parser_error(ISC_TRUE, + "Bad port specification. Using ``*''"); + } + + isc_mem_free(memctx, $1); + } + ; + +query_source_address: L_ADDRESS maybe_wild_addr + { + tmpres = dns_c_ctx_setquerysourceaddr(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining query-source address."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set query-source address."); + YYABORT; + } + } + ; + +query_source_port: L_PORT maybe_wild_port + { + tmpres = dns_c_ctx_setquerysourceport(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining query-source port."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set query-source port."); + YYABORT; + } + } + ; + +query_source: query_source_address + | query_source_port + | query_source_address query_source_port + | query_source_port query_source_address + ; + +maybe_port: /* nothing */ + { + $$ = DNS_C_DEFAULTPORT; + } + | L_PORT in_port + { + $$ = $2; + } + ; + +maybe_zero_port : /* nothing */ + { + $$ = 0; + } + | L_PORT in_port + { + $$ = $2; + } + ; + +yea_or_nay: L_YES + { + $$ = isc_boolean_true; + } + | L_TRUE + { + $$ = isc_boolean_true; + } + | L_NO + { + $$ = isc_boolean_false; + } + | L_FALSE + { + $$ = isc_boolean_false; + } + | L_INTEGER + { + if ($1 == 1) { + $$ = isc_boolean_true; + } else if ($1 == 0) { + $$ = isc_boolean_false; + } else { + parser_warning(ISC_TRUE, + "number should be 0 or 1; assuming 1"); + $$ = isc_boolean_true; + } + } + ; + +check_names_type: L_MASTER + { + $$ = dns_trans_primary; + } + | L_SLAVE + { + $$ = dns_trans_secondary; + } + | L_RESPONSE + { + $$ = dns_trans_response; + } + ; + +check_names_opt: L_WARN + { + $$ = dns_severity_warn; + } + | L_FAIL + { + $$ = dns_severity_fail; + } + | L_IGNORE + { + $$ = dns_severity_ignore; + } + ; + +forward_opt: L_ONLY + { + $$ = dns_c_forw_only; + } + | L_FIRST + { + $$ = dns_c_forw_first; + } + | L_IF_NO_ANSWER + { + $$ = dns_c_forw_noanswer; + } + | L_IF_NO_DOMAIN + { + $$ = dns_c_forw_nodomain; + } + ; + + + +size_clause: L_DATASIZE size_spec + { + tmpres = dns_c_ctx_setdatasize(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining datasize."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Failed to set datasize."); + YYABORT; + } + } + | L_STACKSIZE size_spec + { + tmpres = dns_c_ctx_setstacksize(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining stacksize."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Failed to set stacksize."); + YYABORT; + } + } + | L_CORESIZE size_spec + { + tmpres = dns_c_ctx_setcoresize(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining coresize."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Failed to set coresize."); + YYABORT; + } + } + | L_FILES size_spec + { + tmpres = dns_c_ctx_setfiles(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining files."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Failed to set files."); + YYABORT; + } + } + ; + + +size_spec: any_string + { + isc_uint32_t result; + + if (unit_to_uint32($1, &result)) { + $$ = result; + if ($$ == DNS_C_SIZE_SPEC_DEFAULT) { + isc_uint32_t newi = DNS_C_SIZE_SPEC_DEFAULT-1; + parser_warning(ISC_FALSE, + "value (%lu) too big. " + "Reducing to %lu", + (unsigned long)$$, + (unsigned long)newi); + $$ = newi; } + } else { + parser_warning(ISC_FALSE, + "invalid unit string '%s'. Using " + "default", $1); + $$ = DNS_C_SIZE_SPEC_DEFAULT; + } + isc_mem_free(memctx, $1); + } + | L_INTEGER + { + $$ = (isc_uint32_t)$1; + if ($$ == DNS_C_SIZE_SPEC_DEFAULT) { + isc_uint32_t newi = DNS_C_SIZE_SPEC_DEFAULT - 1; + parser_warning(ISC_FALSE, + "value (%lu) too big. Reducing to %lu", + (unsigned long) $$, + (unsigned long) newi); + $$ = newi; + } + } + | L_DEFAULT + { + $$ = DNS_C_SIZE_SPEC_DEFAULT; + } + | L_UNLIMITED + { + $$ = DNS_C_SIZE_SPEC_UNLIM; + } + ; + + + +transfer_clause: L_TRANSFERS_IN L_INTEGER + { + tmpres = dns_c_ctx_settransfersin(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, "Redefining transfers-in."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Failed to set transfers-in."); + YYABORT; + } + } + | L_TRANSFERS_OUT L_INTEGER + { + tmpres = dns_c_ctx_settransfersout(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining transfers-out."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set transfers-out."); + YYABORT; + } + } + | L_TRANSFERS_PER_NS L_INTEGER + { + tmpres = dns_c_ctx_settransfersperns(currcfg, $2); + if (tmpres == ISC_R_EXISTS) { + parser_error(ISC_FALSE, + "Redefining transfers-per-ns."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set transfers-per-ns."); + YYABORT; + } + } + ; + + +opt_forwarders_list: /* nothing */ { + } + | forwarders_in_addr_list + ; + +forwarders_in_addr_list: forwarders_in_addr L_EOS + | forwarders_in_addr_list forwarders_in_addr L_EOS + ; + +forwarders_in_addr: ip_address + { + tmpres = dns_c_iplist_append(currcfg->options->forwarders, $1); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to add forwarders " + "address element."); + YYABORT; + } + } + ; + + +/* + * Logging + */ + +logging_stmt: L_LOGGING + { + /* initialized in logging_init() */ + INSIST(currcfg->logging != NULL); + } + L_LBRACE logging_opts_list L_RBRACE + ; + +logging_opts_list: logging_opt L_EOS + | logging_opts_list logging_opt L_EOS + ; + +logging_opt: category_stmt + | channel_stmt + ; + + +channel_stmt: + L_CHANNEL channel_name L_LBRACE L_FILE L_QSTRING { + dns_c_logchan_t *newc; + + tmpres = dns_c_ctx_addfile_channel(currcfg, + $2, &newc); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, + "Redefing channel %s", $2); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to add new file channel."); + YYABORT; + } + + INSIST(newc != NULL); + + tmpres = dns_c_logchan_setpath(newc, $5); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to add file channel's path."); + YYABORT; + } + + isc_mem_free(memctx, $2); + isc_mem_free(memctx, $5); + } maybe_file_modifiers L_EOS optional_channel_opt_list L_RBRACE + | L_CHANNEL channel_name L_LBRACE L_SYSLOG maybe_syslog_facility { + dns_c_logchan_t *newc; + + tmpres = dns_c_ctx_addsyslogchannel(currcfg, + $2, &newc); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, "Redefining channel %s", $2); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to add new syslog channel."); + YYABORT; + } + + tmpres = dns_c_logchan_setfacility(newc, $5); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel facility."); + YYABORT; + } + isc_mem_free(memctx, $2); + } L_EOS optional_channel_opt_list L_RBRACE + | L_CHANNEL channel_name L_LBRACE L_NULL_OUTPUT { + dns_c_logchan_t *newc; + + tmpres = dns_c_ctx_addnullchannel(currcfg, + $2, &newc); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, "Redefining channel %s", $2); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to add new channel ``%s''", $2); + YYABORT; + } + + isc_mem_free(memctx, $2); + } L_EOS optional_channel_opt_list L_RBRACE + | L_CHANNEL channel_name L_LBRACE logging_non_type_keywords { + parser_error(ISC_FALSE, + "First statment inside a channel definition " + "must be ``file'' or ``syslog'' or ``null''."); + YYABORT; + } + ; + + +logging_non_type_keywords: L_SEVERITY | L_PRINT_TIME | L_PRINT_CATEGORY | + L_PRINT_SEVERITY + ; + + +optional_channel_opt_list: /* empty */ + | channel_opt_list + ; + +category_stmt: L_CATEGORY category_name { + dns_c_logcat_t *cat; + + tmpres = dns_c_ctx_addcategory(currcfg, $2, &cat); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, + "Redefining category ``%s''", $2); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to add new logging category."); + YYABORT; + } + } L_LBRACE channel_list L_RBRACE + ; + + +channel_severity: any_string + { + dns_c_logseverity_t severity; + dns_c_logchan_t *chan; + + tmpres = dns_c_string2logseverity($1, &severity); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Unknown severity ``%s''", $1); + YYABORT; + } + + tmpres = dns_c_ctx_currchannel(currcfg, &chan); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get current channel."); + YYABORT; + } + + tmpres = dns_c_logchan_setseverity(chan, severity); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, "Redefining severity."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel severity."); + YYABORT; + } + + isc_mem_free(memctx, $1); + } + | L_DEBUG + { + dns_c_logchan_t *chan; + + tmpres = dns_c_ctx_currchannel(currcfg, &chan); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get current channel."); + YYABORT; + } + + tmpres = dns_c_logchan_setseverity(chan, + dns_c_log_debug); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, "Redefining severity."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel severity(debug)."); + YYABORT; + } + } + | L_DEBUG L_INTEGER + { + dns_c_logchan_t *chan; + + tmpres = dns_c_ctx_currchannel(currcfg, &chan); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get current channel."); + YYABORT; + } + + tmpres = dns_c_logchan_setseverity(chan, + dns_c_log_debug); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, "Redefining severity."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel " + "severity (debug)."); + YYABORT; + } + + tmpres = dns_c_logchan_setdebuglevel(chan, $2); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel " + "severity debug level."); + YYABORT; + } + } + | L_DYNAMIC + { + dns_c_logchan_t *chan; + + tmpres = dns_c_ctx_currchannel(currcfg, &chan); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get current channel."); + YYABORT; + } + + tmpres = dns_c_logchan_setseverity(chan, + dns_c_log_dynamic); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, "Redefining severity."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel " + "severity (dynamic)."); + YYABORT; + } + } + ; + +version_modifier: L_VERSIONS L_INTEGER + { + dns_c_logchan_t *chan; + + tmpres = dns_c_ctx_currchannel(currcfg, &chan); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get current channel."); + YYABORT; + } + + tmpres = dns_c_logchan_setversions(chan, $2); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, "Redefining versions."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel versions."); + YYABORT; + } + } + | L_VERSIONS L_UNLIMITED + { + dns_c_logchan_t *chan; + + tmpres = dns_c_ctx_currchannel(currcfg, &chan); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get current channel."); + YYABORT; + } + + tmpres = dns_c_logchan_setversions(chan, -1); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, "Redefining versions."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel " + "versions (unlimited)."); + YYABORT; + } + } + ; + +size_modifier: L_SIZE size_spec + { + dns_c_logchan_t *chan; + + tmpres = dns_c_ctx_currchannel(currcfg, &chan); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get current channel."); + YYABORT; + } + + tmpres = dns_c_logchan_setsize(chan, $2); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, "Redefining size."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel size."); + YYABORT; + } + } + ; + +maybe_file_modifiers: /* nothing */ + | version_modifier + | size_modifier + | version_modifier size_modifier + | size_modifier version_modifier + ; + +facility_name: any_string + { + tmpres = dns_c_string2facility($1, &$$); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_TRUE, "Unknown syslog facility."); + $$ = LOG_DAEMON; + } + + isc_mem_free(memctx, $1); + } + | L_SYSLOG + { + $$ = LOG_SYSLOG; + } + ; + +maybe_syslog_facility: /* nothing */ + { + $$ = LOG_DAEMON; + } + | facility_name + { + $$ = $1; + } + ; + + +channel_opt_list: channel_opt L_EOS + | channel_opt_list channel_opt L_EOS + ; + + +channel_opt: L_SEVERITY channel_severity { /* nothing to do */ } + | L_PRINT_TIME yea_or_nay + { + dns_c_logchan_t *chan; + + tmpres = dns_c_ctx_currchannel(currcfg, &chan); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Can't get current channel."); + YYABORT; + } + + tmpres = dns_c_logchan_setprinttime(chan, $2); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, "Redefining print-time."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel print-time."); + YYABORT; + } + } + | L_PRINT_CATEGORY yea_or_nay + { + dns_c_logchan_t *chan; + + tmpres = dns_c_ctx_currchannel(currcfg, &chan); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Can't get current channel."); + YYABORT; + } + + tmpres = dns_c_logchan_setprintcat(chan, $2); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, + "Redefining print-category."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel print-category."); + YYABORT; + } + } + | L_PRINT_SEVERITY yea_or_nay + { + dns_c_logchan_t *chan; + + tmpres = dns_c_ctx_currchannel(currcfg, &chan); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Can't get current channel."); + YYABORT; + } + + tmpres = dns_c_logchan_setprintsev(chan, $2); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, + "Redefining print-severity."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't get set channel print-severity."); + YYABORT; + } + } + ; + + +channel_name: any_string + | L_NULL_OUTPUT + { + $$ = isc_mem_strdup(memctx, "null"); + } + ; + + +channel: channel_name + { + dns_c_logcat_t *cat; + + /* + * XXX validate the channel name refers to a previously + * defined channel + */ + tmpres = dns_c_ctx_currcategory(currcfg, &cat); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Can't get current category."); + YYABORT; + } + + tmpres = dns_c_logcat_addname(cat, $1); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Can't add new name to category."); + } + + isc_mem_free(memctx, $1); + } + ; + + +channel_list: channel L_EOS + | channel_list channel L_EOS + ; + + +category_name: any_string + { + dns_c_category_t cat; + + tmpres = dns_c_string2category($1, &cat); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Unknown category ``%s''", $1); + YYABORT; + } + + isc_mem_free(memctx, $1); + + $$ = cat; + } + | L_DEFAULT + { + $$ = dns_c_cat_default; + } + | L_NOTIFY + { + $$ = dns_c_cat_notify; + } + ; + +/* + * Server Information + */ + +server_stmt: L_SERVER ip_address + { + dns_c_srv_t *server; + dns_c_srv_t *tmpserver; + dns_c_srvlist_t *servers = currcfg->servers; + + if (servers == NULL) { + tmpres = dns_c_srvlist_new(currcfg->mem, + &currcfg->servers); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create server list"); + YYABORT; + } + servers = currcfg->servers; + } + + /* + * Check that this IP hasn't already bee used and if it has + * remove the old definition. + */ + server = ISC_LIST_HEAD(servers->elements); + while (server != NULL) { + tmpserver = ISC_LIST_NEXT(server, next); + if (memcmp(&server->address, &$2, + sizeof(isc_sockaddr_t)) == 0) { + parser_error(ISC_TRUE, "Redefining server"); + ISC_LIST_UNLINK(servers->elements, + server, next); + dns_c_srv_delete(&server); + break; + } + server = tmpserver; + } + + tmpres = dns_c_srv_new(currcfg->mem, $2, &server); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create server structure"); + YYABORT; + } + + ISC_LIST_APPEND(currcfg->servers->elements, server, next); + } + L_LBRACE server_info_list L_RBRACE + ; + +server_info_list: server_info L_EOS + | server_info_list server_info L_EOS + ; + +server_info: L_BOGUS yea_or_nay + { + dns_c_srv_t *server; + isc_boolean_t tv; + + INSIST(currcfg->servers != NULL); + server = ISC_LIST_TAIL(currcfg->servers->elements); + + INSIST(server != NULL); + + tmpres = dns_c_srv_getbogus(server, &tv); + if (tmpres != ISC_R_NOTFOUND) { + parser_warning(ISC_FALSE, + "Redefining server bogus value"); + } + + dns_c_srv_setbogus(server, $2); + } + | L_SUPPORT_IXFR yea_or_nay + { + dns_c_srv_t *server; + isc_boolean_t tv; + + INSIST(currcfg->servers != NULL); + server = ISC_LIST_TAIL(currcfg->servers->elements); + + INSIST(server != NULL); + + tmpres = dns_c_srv_getsupportixfr(server, &tv); + if(tmpres != ISC_R_NOTFOUND) { + parser_warning(ISC_FALSE, + "Redefining server support-ixfr value"); + } + + dns_c_srv_setsupportixfr(server, $2); + } + | L_TRANSFERS L_INTEGER + { + dns_c_srv_t *server; + isc_int32_t tv; + + INSIST(currcfg->servers != NULL); + server = ISC_LIST_TAIL(currcfg->servers->elements); + + INSIST(server != NULL); + + tmpres = dns_c_srv_gettransfers(server, &tv); + if (tmpres != ISC_R_NOTFOUND) { + parser_warning(ISC_FALSE, + "Redefining server transfers value"); + } + + dns_c_srv_settransfers(server, $2); + } + | L_TRANSFER_FORMAT transfer_format + { + dns_c_srv_t *server; + dns_transfer_format_t tv; + + INSIST(currcfg->servers != NULL); + server = ISC_LIST_TAIL(currcfg->servers->elements); + + INSIST(server != NULL); + + tmpres = dns_c_srv_gettransferformat(server, &tv); + if (tmpres != ISC_R_NOTFOUND) { + parser_warning(ISC_FALSE, + "Redefining server transfer-format " + "value"); + } + + + dns_c_srv_settransferformat(server, $2); + } + | L_KEYS L_LBRACE { + dns_c_srv_t *server; + + INSIST(currcfg->servers != NULL); + server = ISC_LIST_TAIL(currcfg->servers->elements); + INSIST(server != NULL); + + if (server->keys == NULL) { + tmpres = dns_c_kidlist_new(currcfg->mem, + &server->keys); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create keyid_list"); + YYABORT; + } + } + } key_list L_RBRACE + ; + +/* + * Address Matching + */ + +address_match_list: address_match_element L_EOS + { + dns_c_ipmatchlist_t *ml = 0; + + if ($1 != NULL) { + tmpres = dns_c_ipmatchlist_new(currcfg->mem, &ml); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Insufficient memory"); + dns_c_ipmatchelement_delete(currcfg->mem, + &$1); + YYABORT; + } + + ISC_LIST_APPEND(ml->elements, $1, next); + } + + $$ = ml; + } + | address_match_list address_match_element L_EOS + { + dns_c_ipmatchlist_t *ml = $1; + + if (ml == NULL && $2 != NULL) { + tmpres = dns_c_ipmatchlist_new(currcfg->mem, &ml); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, "Insufficient memory"); + dns_c_ipmatchelement_delete(currcfg->mem, + &$2); + YYABORT; + } + } + + if ($2 != NULL) { + ISC_LIST_APPEND(ml->elements, $2, next); + } + + $$ = ml; + } + ; + +address_match_element: address_match_simple + | L_BANG address_match_simple + { + if ($2 != NULL) { + dns_c_ipmatch_negate($2); + } + $$ = $2; + } + | L_SEC_KEY L_STRING + { + dns_c_ipmatchelement_t *ime = NULL; + + if (!dns_c_ctx_keydefinedp(currcfg, $2)) { + parser_error(ISC_FALSE, + "Address match key element (%s) " + "referenced before defined", $2); + YYABORT; + } else { + tmpres = dns_c_ipmatchkey_new(currcfg->mem, &ime, $2); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_TRUE, + "Failed to create address match " + "key element for %s", $2); + YYABORT; + } + } + + isc_mem_free(memctx, $2); + $$ = ime; + } + ; + +address_match_simple: ip_address + { + dns_c_ipmatchelement_t *ime = NULL; + unsigned int prefixlen = 0; + + switch ($1.type.sa.sa_family) { + case AF_INET: + prefixlen = 32; + break; + case AF_INET6: + prefixlen = 128; + break; + default: + INSIST(0); + break; + } + tmpres = dns_c_ipmatchpattern_new(currcfg->mem, &ime, $1, + prefixlen); + switch (tmpres) { + case ISC_R_FAILURE: + parser_error(ISC_FALSE, "bad address match element."); + YYABORT; + break; + + case ISC_R_NOMEMORY: + parser_error(ISC_FALSE, + "Insufficient memory available."); + YYABORT; + break; + + case ISC_R_SUCCESS: + break; + } + + $$ = ime; + } + | ip_address L_SLASH L_INTEGER + { + dns_c_ipmatchelement_t *ime = NULL; + + if ($3 < 0 || + ($1.type.sa.sa_family == AF_INET && $3 > 32) || + ($1.type.sa.sa_family == AF_INET6 && $3 > 128)) { + parser_warning(ISC_FALSE, + "mask bits (%d) out of range: " + "skipping", (int)$3); + $$ = NULL; + } else { + tmpres = dns_c_ipmatchpattern_new(currcfg->mem, &ime, + $1, $3); + switch (tmpres) { + case ISC_R_FAILURE: + parser_error(ISC_FALSE, + "bad address match element."); + YYABORT; + break; + + case ISC_R_NOMEMORY: + parser_error(ISC_FALSE, + "Insufficient memory " + "available."); + YYABORT; + break; + + case ISC_R_SUCCESS: + break; + } + } + + $$ = ime; + } + | L_INTEGER L_SLASH L_INTEGER + { + struct in_addr ia; + dns_c_ipmatchelement_t *ime = NULL; + isc_sockaddr_t address; + + if ($1 > 255) { + parser_error(ISC_FALSE, + "address out of range; skipping"); + YYABORT; + } else { + if ($3 < 0 || $3 > 32) { + parser_warning(ISC_FALSE, + "mask bits out of range; " + "skipping"); + $$ = NULL; + } else { + ia.s_addr = htonl(($1 & 0xff) << 24); + isc_sockaddr_fromin(&address, &ia, 0); + + tmpres = + dns_c_ipmatchpattern_new(currcfg->mem, + &ime, + address, + $3); + switch (tmpres) { + case ISC_R_FAILURE: + parser_error(ISC_FALSE, + "bad address match " + "element."); + YYABORT; + break; + + case ISC_R_NOMEMORY: + parser_error(ISC_FALSE, + "Insufficient memory " + "available."); + YYABORT; + break; + + case ISC_R_SUCCESS: + break; + } + } + } + + $$ = ime; + } + | address_name + | L_LBRACE address_match_list L_RBRACE + { + dns_c_ipmatchelement_t *ime = NULL; + + if ($2 != NULL) { + tmpres = dns_c_ipmatchindirect_new(currcfg->mem, &ime, + $2, NULL); + switch (tmpres) { + case ISC_R_SUCCESS: + break; + + case ISC_R_NOMEMORY: + parser_error(ISC_FALSE, + "Insufficient memory " + "available."); + YYABORT; + break; + } + } + + dns_c_ipmatchlist_detach(&$2); + + $$ = ime; + } + ; + +address_name: any_string + { + dns_c_ipmatchelement_t *elem; + dns_c_acl_t *acl; + + tmpres = dns_c_acltable_getacl(currcfg->acls, + $1, &acl); + if (tmpres == ISC_R_NOTFOUND) { + parser_warning(ISC_FALSE, + "Undefined acl ``%s'' referenced", + $1); + elem = NULL; + } else { + tmpres = dns_c_ipmatch_aclnew(currcfg->mem, &elem, $1); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create IPE-ACL"); + YYABORT; + } + } + + isc_mem_free(memctx, $1); + $$ = elem; + } + ; + +/* + * Keys + */ + +key_ref: any_string + ; + +key_list_element: key_ref + { + dns_c_srv_t *currserver; + dns_c_kid_t *keyid; + + INSIST(currcfg->servers != NULL); + currserver = ISC_LIST_TAIL(currcfg->servers->elements); + INSIST(currserver != NULL); + + INSIST(currserver->keys != NULL); + + if (!dns_c_ctx_keydefinedp(currcfg, $1)) { + parser_error(ISC_FALSE, + "Server keys key_id (%s) " + "referenced before defined", $1); + YYABORT; + } else { + tmpres = dns_c_kid_new(currserver->keys, $1, &keyid); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create keyid"); + YYABORT; + } + } + + isc_mem_free(memctx, $1); + } + ; + + +/* + * The grammer in the man page implies a semicolon is not required before + * key_list_elements. We'll support either way. + */ +maybe_eos: | L_EOS + ; + +key_list: key_list_element maybe_eos + | key_list key_list_element maybe_eos + ; + +key_stmt: L_SEC_KEY any_string + { + dns_c_kdef_t *keydef; + + if (currcfg->keydefs == NULL) { + tmpres = dns_c_kdeflist_new(currcfg->mem, + &currcfg->keydefs); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create keylist"); + YYABORT; + } + } + + tmpres = dns_c_kdef_new(currcfg->keydefs, + $2, &keydef); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create key definition"); + YYABORT; + } + + isc_mem_free(memctx, $2); + } + L_LBRACE key_definition L_RBRACE + ; + +key_definition: algorithm_id secret + { + dns_c_kdef_t *keydef; + + INSIST(currcfg->keydefs != NULL); + + keydef = ISC_LIST_TAIL(currcfg->keydefs->keydefs); + INSIST(keydef != NULL); + + dns_c_kdef_setalgorithm(keydef, $1); + dns_c_kdef_setsecret(keydef, $2); + + isc_mem_free(memctx, $1); + isc_mem_free(memctx, $2); + } + | secret algorithm_id + { + dns_c_kdef_t *keydef; + + INSIST(currcfg->keydefs != NULL); + + keydef = ISC_LIST_TAIL(currcfg->keydefs->keydefs); + INSIST(keydef != NULL); + + dns_c_kdef_setsecret(keydef, $1); + dns_c_kdef_setalgorithm(keydef, $2); + + isc_mem_free(memctx, $1); + isc_mem_free(memctx, $2); + } + ; + +algorithm_id: L_ALGID any_string L_EOS + { + $$ = $2; + } + ; + +secret: L_SECRET any_string L_EOS + { + $$ = $2; + } + ; + + +/* + * Views + */ + + +view_stmt: L_VIEW any_string L_LBRACE + { + dns_c_view_t *view; + + if (currcfg->views == NULL) { + tmpres = dns_c_viewtable_new(currcfg->mem, + &currcfg->views); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create viewtable"); + YYABORT; + } + } + + tmpres = dns_c_view_new(currcfg->mem, $2, &view); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create view %s", $2); + YYABORT; + } + + dns_c_viewtable_addview(currcfg->views, view); + dns_c_ctx_setcurrview(currcfg, view); + + isc_mem_free(memctx, $2); + } optional_view_options_list L_RBRACE { + dns_c_ctx_setcurrview(currcfg, NULL); + }; + +optional_view_options_list: + | view_options_list + ; + +view_options_list: view_option L_EOS + | view_options_list view_option L_EOS; + + +view_option: L_ALLOW_QUERY L_LBRACE address_match_list L_RBRACE + { + dns_c_view_t *view = dns_c_ctx_getcurrview(currcfg); + + INSIST(view != NULL); + + tmpres = dns_c_view_setallowquery(view, $3, + ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining view allow-query."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set view allow-query."); + break; + } + } + | L_ALLOW_TRANSFER L_LBRACE address_match_list L_RBRACE + { + dns_c_view_t *view = dns_c_ctx_getcurrview(currcfg); + + INSIST(view != NULL); + + tmpres = dns_c_view_setallowtransfer(view, + $3, ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining view allow-transfer."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set view allow-transfer."); + break; + } + } + | L_ALLOW_RECURSION L_LBRACE address_match_list L_RBRACE + { + dns_c_view_t *view = dns_c_ctx_getcurrview(currcfg); + + INSIST(view != NULL); + + tmpres = dns_c_view_setallowrecursion(view, + $3, ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining view allow-recursion."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set view allow-recursion."); + break; + } + } + | L_BLACKHOLE L_LBRACE address_match_list L_RBRACE + { + dns_c_view_t *view = dns_c_ctx_getcurrview(currcfg); + + INSIST(view != NULL); + + tmpres = dns_c_view_setblackhole(view, + $3, ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining view blackhole."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set view blackhole."); + break; + } + } + | L_FORWARDERS L_LBRACE opt_in_addr_list L_RBRACE + { + dns_c_view_t *view = dns_c_ctx_getcurrview(currcfg); + + INSIST(view != NULL); + + tmpres = dns_c_view_setforwarders(view, + $3, ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining view forwarders."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set view forwarders."); + break; + } + } + | L_SORTLIST L_LBRACE address_match_list L_RBRACE + { + dns_c_view_t *view = dns_c_ctx_getcurrview(currcfg); + + INSIST(view != NULL); + + tmpres = dns_c_view_setsortlist(view, + $3, ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining view sortlist."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set view sortlist."); + break; + } + } + | L_TOPOLOGY L_LBRACE address_match_list L_RBRACE + { + dns_c_view_t *view = dns_c_ctx_getcurrview(currcfg); + + INSIST(view != NULL); + + tmpres = dns_c_view_settopology(view, + $3, ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining view topology."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set view topology."); + break; + } + } + | L_LISTEN_ON maybe_port L_LBRACE address_match_list L_RBRACE + { + dns_c_view_t *view = dns_c_ctx_getcurrview(currcfg); + + INSIST(view != NULL); + + if ($4 == NULL) { + parser_warning(ISC_FALSE, + "address-match-list empty. " + "listen statement ignored."); + } else { + tmpres = dns_c_view_addlisten_on(view, $2, $4, + ISC_FALSE); + + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to add listen statement"); + YYABORT; + } + } + } +/* XXX not implemented yet + | L_RRSET_ORDER L_LBRACE rrset_ordering_list L_RBRACE + | L_CHECK_NAMES + | L_TRANSFER_FORMAT +*/ + | zone_stmt; + ; + +/* XXX other view statements need to go in here???. */ + + +/* + key + trusted-keys + server + options { + forwarders + blackhole + lame-ttl + max-ncache-ttl + min-roots + cleaning-interval + } +*/ + +/* + * ACLs + */ + +acl_stmt: L_ACL any_string L_LBRACE address_match_list L_RBRACE + { + dns_c_acl_t *acl; + + INSIST(currcfg->acls != NULL); + + tmpres = dns_c_acl_new(currcfg->acls, + $2, ISC_FALSE, &acl); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to create acl %s", $2); + YYABORT; + } + + dns_c_acl_setipml(acl, $4, ISC_FALSE); + + isc_mem_free(memctx, $2); + } + ; + + +/* + * Zones + */ + +domain_name: L_QSTRING + { + $$ = $1; + } + ; + +/* + * ``type'' is no longer optional and must be the first statement in the + * zone block. + */ +zone_stmt: L_ZONE domain_name optional_class L_LBRACE L_TYPE zone_type L_EOS + { + dns_c_zone_t *zone; + + if (currcfg->zlist == NULL) { + tmpres = dns_c_zonelist_new(currcfg->mem, + &currcfg->zlist); + if (tmpres != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_ERROR, + "Failed to create zone list"); + YYABORT; + } + } + + /* XXX internal name support needed! */ + tmpres = dns_c_zone_new(currcfg->mem, + $6, $3, $2, $2, &zone); + if (tmpres != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_ERROR, + "Error creating new zone."); + YYABORT; + } + + if (currcfg->options != NULL) { + zone->afteropts = ISC_TRUE; + } + + tmpres = dns_c_zonelist_addzone(currcfg->zlist, zone); + if (tmpres != ISC_R_SUCCESS) { + dns_c_zone_detach(&zone); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_ERROR, + "Error adding new zone to list."); + YYABORT; + } + + dns_c_ctx_setcurrzone(currcfg, zone); + + isc_mem_free(memctx, $2); + } optional_zone_options_list L_RBRACE { + dns_c_zone_t *zone; + dns_c_view_t *view; + + zone = dns_c_ctx_getcurrzone(currcfg); + view = dns_c_ctx_getcurrview(currcfg); + + zone->view = view; + + if (view != NULL) { + dns_c_view_addzone(view, zone); + } + + dns_c_ctx_setcurrzone(currcfg, NULL); + + if (callbacks != NULL && callbacks->zonecbk != NULL) { + tmpres = callbacks->zonecbk(currcfg, + zone, + view, + callbacks->zonecbkuap); + if (tmpres != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_ERROR, + "zone configuration for '%s' failed: %s", + zone->name, + isc_result_totext(tmpres)); + YYABORT; + } + + dns_c_zonelist_rmzone(currcfg->zlist, zone); + } + } + | L_ZONE domain_name optional_class L_LBRACE zone_non_type_keywords + { + parser_error(ISC_FALSE, + "First statement in a zone definition must " + "be ``type''"); + YYABORT; + } + | L_ZONE domain_name + { + parser_warning(ISC_FALSE, + "References to zones not implemented yet."); + } + ; + +optional_zone_options_list: /* Empty */ + | zone_option_list + ; + +class_name: any_string + { + isc_textregion_t reg; + dns_rdataclass_t cl; + + if (strcmp($1, "*") == 0) { + cl = dns_rdataclass_any; + } else { + reg.base = $1; + reg.length = strlen($1); + + tmpres = dns_rdataclass_fromtext(&cl, ®); + if (tmpres != DNS_R_SUCCESS) { + parser_error(ISC_TRUE, + "Unknown class assuming ``*''."); + cl = dns_rdataclass_any; + } + } + + isc_mem_free(memctx, $1); + $$ = cl; + } + +optional_class: /* Empty */ + { + $$ = dns_rdataclass_in; + } + | class_name + ; + +zone_type: L_MASTER + { + $$ = dns_c_zone_master; + } + | L_SLAVE + { + $$ = dns_c_zone_slave; + } + | L_HINT + { + $$ = dns_c_zone_hint; + } + | L_STUB + { + $$ = dns_c_zone_stub; + } + | L_FORWARD + { + $$ = dns_c_zone_forward; + } + ; + + + +zone_option_list: zone_option L_EOS + | zone_option_list zone_option L_EOS + ; + + +zone_non_type_keywords: L_FILE | L_FILE_IXFR | L_IXFR_TMP | L_MASTERS | + L_TRANSFER_SOURCE | L_CHECK_NAMES | L_ALLOW_UPDATE | L_ALLOW_QUERY | + L_ALLOW_TRANSFER | L_FORWARD | L_FORWARDERS | L_MAX_TRANSFER_TIME_IN | + L_TCP_CLIENTS | L_RECURSIVE_CLIENTS | + L_MAX_TRANSFER_TIME_OUT | L_MAX_TRANSFER_IDLE_IN | + L_MAX_TRANSFER_IDLE_OUT | L_MAX_LOG_SIZE_IXFR | L_NOTIFY | + L_MAINTAIN_IXFR_BASE | L_PUBKEY | L_ALSO_NOTIFY | L_DIALUP + ; + + +zone_option: L_FILE L_QSTRING + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setfile(zone, $2); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, + "redefining zone filename."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set zone file name"); + } + isc_mem_free(memctx, $2); + } + | L_FILE_IXFR L_QSTRING + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setixfrbase(zone, $2); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, + "Redefining ixfr-base."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set zone ixfr_base."); + } + isc_mem_free(memctx, $2); + } + | L_IXFR_TMP L_QSTRING + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setixfrtmp(zone, $2); + if (tmpres == ISC_R_EXISTS) { + parser_warning(ISC_FALSE, + "Redefining ixfr-tmp-file."); + } else if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_FALSE, + "Failed to set zone ixfr_tmp-file."); + } + isc_mem_free(memctx, $2); + } + | L_MASTERS maybe_zero_port L_LBRACE master_in_addr_list L_RBRACE + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setmasterport(zone, $2); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone master's port."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone master port."); + break; + } + + tmpres = dns_c_zone_setmasterips(zone, + $4, ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone masters ips."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone masters ips."); + break; + } + } + | L_TRANSFER_SOURCE maybe_wild_addr + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_settransfersource(zone, $2); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone transfer-source."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone transfer-source."); + break; + } + } + | L_CHECK_NAMES check_names_opt + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setchecknames(zone, $2); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone check-names."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone check-names."); + break; + } + } + | L_ALLOW_UPDATE L_LBRACE address_match_list L_RBRACE + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setallowupd(zone, + $3, ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone allow-update."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone allow-update."); + break; + } + } + | L_ALLOW_QUERY L_LBRACE address_match_list L_RBRACE + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setallowquery(zone, + $3, ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone allow-query."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone allow-query."); + break; + } + } + | L_ALLOW_TRANSFER L_LBRACE address_match_list L_RBRACE + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setallowtransfer(zone, + $3, ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone allow-transfer."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone allow-transfer."); + break; + } + } + | L_FORWARD zone_forward_opt + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setforward(zone, $2); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone forward."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone forward."); + break; + } + } + | L_FORWARDERS L_LBRACE opt_zone_forwarders_list L_RBRACE + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + dns_c_iplist_t *iplist; + + INSIST(zone != NULL); + + if ($3 == NULL) { /* user defined empty list */ + tmpres = dns_c_iplist_new(currcfg->mem, + 5, &iplist); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_TRUE, + "Failed to create new zone " + "iplist"); + YYABORT; + } + } else { + iplist = $3; + } + + tmpres = dns_c_zone_setforwarders(zone, + iplist, ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone forwarders."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone forwarders."); + dns_c_iplist_detach(&$3); + break; + } + } + | L_MAX_TRANSFER_TIME_IN L_INTEGER + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_zone_setmaxtranstimein(zone, $2 * 60); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone " + "max-transfer-time-in."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone " + "max-transfer-time-in."); + break; + } + } + | L_MAX_TRANSFER_TIME_OUT L_INTEGER + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_zone_setmaxtranstimeout(zone, $2 * 60); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone " + "max-transfer-time-out."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone " + "max-transfer-time-out."); + break; + } + } + | L_MAX_TRANSFER_IDLE_IN L_INTEGER + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_zone_setmaxtransidlein(zone, $2 * 60); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone " + "max-transfer-idle-in."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone " + "max-transfer-idle-in."); + break; + } + } + | L_MAX_TRANSFER_IDLE_OUT L_INTEGER + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + if ( int_too_big($2, 60) ) { + parser_error(ISC_FALSE, + "integer value too big: %u", $2); + YYABORT; + } + + tmpres = dns_c_zone_setmaxtransidleout(zone, $2 * 60); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone " + "max-transfer-idle-out."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone " + "max-transfer-idle-out."); + break; + } + } + | L_MAX_LOG_SIZE_IXFR L_INTEGER + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setmaxixfrlog(zone, $2); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone max-ixfr-log-size."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone max-ixfr-log-size."); + break; + } + } + | L_NOTIFY yea_or_nay + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setnotify(zone, $2); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone notify."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone notify."); + break; + } + } + | L_MAINTAIN_IXFR_BASE yea_or_nay + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setmaintixfrbase(zone, $2); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone maintain-ixfr-base."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone maintain-ixfr-base."); + break; + } + } + | L_PUBKEY L_INTEGER L_INTEGER L_INTEGER L_QSTRING + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + dns_c_pubkey_t *pubkey; + + INSIST(zone != NULL); + + tmpres = dns_c_pubkey_new(currcfg->mem, $2, + $3, $4, $5, &pubkey); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_TRUE, + "Failed to create a zone pubkey"); + YYABORT; + } + + tmpres = dns_c_zone_addpubkey(zone, pubkey, + ISC_FALSE); + switch (tmpres) { + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + dns_c_pubkey_delete(&pubkey); + parser_error(ISC_FALSE, + "Failed to add a zone pubkey."); + break; + } + + isc_mem_free(memctx, $5); + } + | L_ALSO_NOTIFY L_LBRACE notify_in_addr_list L_RBRACE + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setalsonotify(zone, $3, + ISC_FALSE); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone also-notify."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone also-notify."); + break; + } + } + | L_DIALUP yea_or_nay + { + dns_c_zone_t *zone = dns_c_ctx_getcurrzone(currcfg); + + INSIST(zone != NULL); + + tmpres = dns_c_zone_setdialup(zone, $2); + switch (tmpres) { + case ISC_R_EXISTS: + parser_warning(ISC_FALSE, + "Redefining zone dialup."); + break; + + case ISC_R_SUCCESS: + /* nothing */ + break; + + default: + parser_error(ISC_FALSE, + "Failed to set zone dialup."); + break; + } + } + ; + + +master_in_addr_list: in_addr_list + ; + +notify_in_addr_list: opt_in_addr_list + ; + +ip4_address: L_IP4ADDR + { + isc_sockaddr_fromin(&$$, &$1, 0); + } + ; + +ip6_address: L_IP6ADDR + { + isc_sockaddr_fromin6(&$$, &$1, 0); + } + + +ip_address: ip4_address | ip6_address + ; + +in_addr_elem: ip_address + ; + +opt_in_addr_list: /* nothing */ + { + dns_c_iplist_t *list; + + tmpres = dns_c_iplist_new(currcfg->mem, 5, &list); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_TRUE, + "Failed to create new iplist"); + YYABORT; + } + + $$ = list; + } + | in_addr_list + ; + +in_addr_list: in_addr_elem L_EOS + { + dns_c_iplist_t *list; + + tmpres = dns_c_iplist_new(currcfg->mem, 5, &list); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_TRUE, + "Failed to create new iplist"); + YYABORT; + } + + tmpres = dns_c_iplist_append(list, $1); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_TRUE, + "Failed to append master address"); + YYABORT; + } + + $$ = list; + } + | in_addr_list in_addr_elem L_EOS + { + tmpres = dns_c_iplist_append($1, $2); + if (tmpres != ISC_R_SUCCESS) { + parser_error(ISC_TRUE, + "Failed to append master address"); + YYABORT; + } + + $$ = $1; + } + ; + +zone_forward_opt: L_ONLY + { + $$ = dns_c_forw_only; + } + | L_FIRST + { + $$ = dns_c_forw_first; + } + ; + +opt_zone_forwarders_list: opt_in_addr_list + ; + +/* + * Trusted Key statement + */ + +trusted_keys_stmt: L_TRUSTED_KEYS + { + dns_c_tkeylist_t *newlist; + + tmpres = dns_c_ctx_gettrustedkeys(currcfg, + &newlist); + if (tmpres == ISC_R_NOTFOUND) { + tmpres = dns_c_tkeylist_new(currcfg->mem, &newlist); + if (tmpres != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_ERROR, + "Failed to create trusted key" + " list."); + YYABORT; + } + + tmpres = dns_c_ctx_settrustedkeys(currcfg, + newlist, + ISC_FALSE); + if (tmpres != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_ERROR, + "Failed to set trusted keys"); + YYABORT; + } + } + } L_LBRACE trusted_keys_list L_RBRACE + ; + +trusted_keys_list: trusted_key L_EOS + | trusted_keys_list trusted_key L_EOS + ; + + +trusted_key: domain_name L_INTEGER L_INTEGER L_INTEGER L_QSTRING + { + dns_c_tkey_t *tkey; + dns_c_tkeylist_t *list; + + tmpres = dns_c_ctx_gettrustedkeys(currcfg, &list); + if (tmpres != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_ERROR, + "No trusted key list defined!"); + YYABORT; + } + + tmpres = dns_c_tkey_new(currcfg->mem, $1, $2, $3, + $4, $5, &tkey); + if (tmpres != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_ERROR, + "Failed to create trusted key"); + YYABORT; + } + + tmpres = dns_c_tkeylist_append(list, + tkey, ISC_FALSE); + if (tmpres != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_ERROR, + "Failed to append trusted key."); + YYABORT; + } + + isc_mem_free(memctx, $1); + isc_mem_free(memctx, $5); + } + ; + + + +/* + * Misc. + */ + +in_port: L_INTEGER + { + if ($1 < 0 || $1 > 65535) { + parser_warning(ISC_TRUE, + "invalid IP port number '%d'; setting port to 0", + (int)$1); + $1 = 0; + } else { + $$ = $1; + } + } + ; + + +any_string: L_STRING + | L_QSTRING + ; + +%% + +static int intuit_token(const char *string); + +static isc_boolean_t is_ip4addr(const char *string, struct in_addr *addr); +static isc_boolean_t is_ip6addr(const char *string, struct in6_addr *addr); +static isc_result_t keyword_init(void); +static char * token_to_text(int token, YYSTYPE lval); +static int token_value(isc_token_t *token, + isc_symtab_t *symtable); +static void init_action(void); + +static int yylex(void); +int yyparse(void); + +static YYSTYPE lastyylval; +static int lasttoken; + + +/* + * Definition of all unique keyword tokens to be recognised by the + * lexer. All the ``L_'' tokens defined in parser.y must be defined here too. + */ +struct token +{ + char *token; + int yaccval; +}; + +static struct token keyword_tokens [] = { + { "{", L_LBRACE }, + { "}", L_RBRACE }, + { ";", L_EOS }, + { "/", L_SLASH }, + { "!", L_BANG }, + + { "acl", L_ACL }, + { "address", L_ADDRESS }, + { "algorithm", L_ALGID }, + { "allow", L_ALLOW }, + { "allow-query", L_ALLOW_QUERY }, + { "allow-transfer", L_ALLOW_TRANSFER }, + { "allow-recursion", L_ALLOW_RECURSION }, + { "allow-update", L_ALLOW_UPDATE }, + { "also-notify", L_ALSO_NOTIFY }, + { "auth-nxdomain", L_AUTH_NXDOMAIN }, + { "blackhole", L_BLACKHOLE }, + { "bogus", L_BOGUS }, + { "category", L_CATEGORY }, + { "class", L_CLASS }, + { "channel", L_CHANNEL }, + { "check-names", L_CHECK_NAMES }, + { "cleaning-interval", L_CLEAN_INTERVAL }, + { "controls", L_CONTROLS }, + { "coresize", L_CORESIZE }, + { "datasize", L_DATASIZE }, + { "deallocate-on-exit", L_DEALLOC_ON_EXIT }, + { "debug", L_DEBUG }, + { "default", L_DEFAULT }, + { "dialup", L_DIALUP }, + { "directory", L_DIRECTORY }, + { "dump-file", L_DUMP_FILE }, + { "dynamic", L_DYNAMIC }, + { "expert-mode", L_EXPERT_MODE }, + { "fail", L_FAIL }, + { "fake-iquery", L_FAKE_IQUERY }, + { "false", L_FALSE }, + { "fetch-glue", L_FETCH_GLUE }, + { "file", L_FILE }, + { "files", L_FILES }, + { "first", L_FIRST }, + { "forward", L_FORWARD }, + { "forwarders", L_FORWARDERS }, + { "group", L_GROUP }, + { "has-old-clients", L_HAS_OLD_CLIENTS }, + { "heartbeat-interval", L_HEARTBEAT }, + { "hint", L_HINT }, + { "host-statistics", L_HOSTSTATS }, + { "if-no-answer", L_IF_NO_ANSWER }, + { "if-no-domain", L_IF_NO_DOMAIN }, + { "ignore", L_IGNORE }, + { "include", L_INCLUDE }, + { "inet", L_INET }, + { "interface-interval", L_INTERFACE_INTERVAL }, + { "ixfr-base", L_FILE_IXFR }, + { "ixfr-tmp-file", L_IXFR_TMP }, + { "key", L_SEC_KEY }, + { "keys", L_KEYS }, + { "listen-on", L_LISTEN_ON }, + { "logging", L_LOGGING }, + { "maintain-ixfr-base", L_MAINTAIN_IXFR_BASE }, + { "many-answers", L_MANY_ANSWERS }, + { "master", L_MASTER }, + { "masters", L_MASTERS }, + { "max-ixfr-log-size", L_MAX_LOG_SIZE_IXFR }, + { "max-ncache-ttl", L_MAX_NCACHE_TTL }, + { "max-transfer-time-in", L_MAX_TRANSFER_TIME_IN }, + { "max-transfer-time-out", L_MAX_TRANSFER_TIME_OUT }, + { "max-transfer-idle-in", L_MAX_TRANSFER_IDLE_IN }, + { "max-transfer-idle-out", L_MAX_TRANSFER_IDLE_OUT }, + { "memstatistics-file", L_MEMSTATS_FILE }, + { "multiple-cnames", L_MULTIPLE_CNAMES }, + { "name", L_NAME }, + { "named-xfer", L_NAMED_XFER }, + { "no", L_NO }, + { "notify", L_NOTIFY }, + { "null", L_NULL_OUTPUT }, + { "one-answer", L_ONE_ANSWER }, + { "only", L_ONLY }, + { "order", L_ORDER }, + { "options", L_OPTIONS }, + { "owner", L_OWNER }, + { "perm", L_PERM }, + { "pid-file", L_PIDFILE }, + { "port", L_PORT }, + { "print-category", L_PRINT_CATEGORY }, + { "print-severity", L_PRINT_SEVERITY }, + { "print-time", L_PRINT_TIME }, + { "pubkey", L_PUBKEY }, + { "query-source", L_QUERY_SOURCE }, + { "rfc2308-type1", L_RFC2308_TYPE1 }, + { "rrset-order", L_RRSET_ORDER }, + { "recursion", L_RECURSION }, + { "recursive-clients", L_RECURSIVE_CLIENTS }, + { "response", L_RESPONSE }, + { "secret", L_SECRET }, + { "server", L_SERVER }, + { "severity", L_SEVERITY }, + { "size", L_SIZE }, + { "slave", L_SLAVE }, + { "sortlist", L_SORTLIST }, + { "stacksize", L_STACKSIZE }, + { "statistics-file", L_STATS_FILE }, + { "statistics-interval", L_STATS_INTERVAL }, + { "stub", L_STUB }, + { "support-ixfr", L_SUPPORT_IXFR }, + { "syslog", L_SYSLOG }, + { "tcp-clients", L_TCP_CLIENTS }, + { "tkey-domain", L_TKEY_DOMAIN }, + { "tkey-dhkey", L_TKEY_DHKEY }, + { "topology", L_TOPOLOGY }, + { "transfer-format", L_TRANSFER_FORMAT }, + { "transfer-source", L_TRANSFER_SOURCE }, + { "transfers", L_TRANSFERS }, + { "transfers-in", L_TRANSFERS_IN }, + { "transfers-out", L_TRANSFERS_OUT }, + { "transfers-per-ns", L_TRANSFERS_PER_NS }, + { "true", L_TRUE }, + { "trusted-keys", L_TRUSTED_KEYS }, + { "type", L_TYPE }, + { "unix", L_UNIX }, + { "unlimited", L_UNLIMITED }, + { "use-id-pool", L_USE_ID_POOL }, + { "use-ixfr", L_USE_IXFR }, + { "version", L_VERSION }, + { "versions", L_VERSIONS }, + { "view", L_VIEW }, + { "warn", L_WARN }, + { "yes", L_YES }, + { "zone", L_ZONE }, + + { NULL, 0 } +}; + + +static struct token class_symbol_tokens[] = { + { "IN", dns_rdataclass_in }, +#if 0 /* XXX expand */ + { "CHAOS", dns_rdataclass_chaos }, + { "HS", dns_rdataclass_hs }, + { "HESIOD", dns_rdataclass_hs }, +#endif + { "ANY", dns_rdataclass_any }, + { "NONE", dns_rdataclass_none }, + { NULL, 0 } +}; + + +static isc_once_t once = ISC_ONCE_INIT; + + +static void +init_action(void) +{ + isc_mutex_init(&yacc_mutex); +} + + +/* + * XXX Need a parameter to specify where error messages should go (syslog, + * FILE, /dev/null etc.) Also some way to tell the function to obey logging + * statments as appropriate. + */ + +isc_result_t +dns_c_parse_namedconf(const char *filename, isc_mem_t *mem, + dns_c_ctx_t **configctx, dns_c_cbks_t *cbks) +{ + isc_result_t res; + const char *funcname = "dns_parse_namedconf"; + + RUNTIME_CHECK(isc_once_do(&once, init_action) == ISC_R_SUCCESS); + + /* Lock down whole parser. */ + if (isc_mutex_lock(&yacc_mutex) != ISC_R_SUCCESS) { + return (ISC_R_UNEXPECTED); + } + + REQUIRE(currcfg == NULL); + REQUIRE(filename != NULL); + REQUIRE(strlen(filename) > 0); + REQUIRE(configctx != NULL); + INSIST(mylexer == NULL); + INSIST(memctx == NULL); + INSIST(keywords == NULL); + INSIST(callbacks == NULL); + +#if 0 + if (getenv("DEBUG_LEXER") != NULL) { /* XXX debug */ + debug_lexer++; + } +#endif + + specials['{'] = 1; + specials['}'] = 1; + specials[';'] = 1; + specials['/'] = 1; + specials['"'] = 1; + specials['!'] = 1; +#if 0 + specials['*'] = 1; +#endif + + + /* + * This memory context is only used by the lexer routines (and must + * stay that way). Any memory that must live past the return of + * yyparse() must be allocated via the 'mem' parameter to this + * function. + */ + res = isc_mem_create(0, 0, &memctx); + if (res != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_ERROR, + "%s: Error creating mem context.", + funcname); + goto done; + } + + res = keyword_init(); + if (res != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_ERROR, + "%s: Error initializing keywords.", + funcname); + goto done; + } + + res = dns_c_ctx_new(mem, &currcfg); + if (res != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_ERROR, + "%s: Error creating config context.", + funcname); + goto done; + } + + res = isc_lex_create(memctx, CONF_MAX_IDENT, &mylexer); + if (res != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_ERROR, + "%s: Error creating lexer", + funcname); + goto done; + } + + isc_lex_setspecials(mylexer, specials); + isc_lex_setcomments(mylexer, (ISC_LEXCOMMENT_C | + ISC_LEXCOMMENT_CPLUSPLUS | + ISC_LEXCOMMENT_SHELL)); + + res = isc_lex_openfile(mylexer, (char *)filename) ; /* remove const */ + if (res != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_ERROR, + "%s: Error opening file %s.", + funcname, filename); + goto done; + } + + callbacks = cbks; + + if (yyparse() != 0) { + res = ISC_R_FAILURE; + + /* Syntax errors in the config file make it very difficult + * to clean up memory properly (which causes assertion + * failure when the memory manager is destroyed). + */ + isc_mem_destroy_check(memctx, ISC_FALSE); + + dns_c_ctx_delete(&currcfg); + currcfg = NULL; + } else { + res = ISC_R_SUCCESS; + } + + + done: + if (mylexer != NULL) + isc_lex_destroy(&mylexer); + + isc_symtab_destroy(&keywords); + + isc_mem_destroy(&memctx); + + if (res == ISC_R_SUCCESS) { + res = dns_c_checkconfig(currcfg); + if (res != ISC_R_SUCCESS) { + dns_c_ctx_delete(&currcfg); + } + } + + *configctx = currcfg; + + callbacks = NULL; + currcfg = NULL; + memctx = NULL; + mylexer = NULL; + + RUNTIME_CHECK(isc_mutex_unlock(&yacc_mutex) == ISC_R_SUCCESS); + + return (res); +} + + + +/*** + *** PRIVATE + ***/ + +static isc_result_t +keyword_init(void) +{ + struct token *tok; + isc_symvalue_t symval; + + RUNTIME_CHECK(isc_symtab_create(memctx, 97 /* prime < 100 */, + NULL, NULL, ISC_FALSE, + &keywords) == ISC_R_SUCCESS); + + + /* Stick all the keywords into the main symbol table. */ + for (tok = &keyword_tokens[0] ; tok->token != NULL ; tok++) { + symval.as_integer = tok->yaccval; + RUNTIME_CHECK(isc_symtab_define(keywords, tok->token, + KEYWORD_SYM_TYPE, symval, + isc_symexists_reject) == + ISC_R_SUCCESS); + } + + /* Now the class names */ + for (tok = &class_symbol_tokens[0] ; tok->token != NULL ; tok++) { + symval.as_integer = tok->yaccval; + RUNTIME_CHECK(isc_symtab_define(keywords, tok->token, + CLASS_SYM_TYPE, symval, + isc_symexists_reject) == + ISC_R_SUCCESS); + } + + return (ISC_R_SUCCESS); +} + + + +static int +yylex(void) +{ + isc_token_t token; + isc_result_t res; + int options = (ISC_LEXOPT_EOF | + ISC_LEXOPT_NUMBER | + ISC_LEXOPT_QSTRING | + ISC_LEXOPT_NOMORE); + + INSIST(mylexer != NULL); + + res = isc_lex_gettoken(mylexer, options, &token); + + switch(res) { + case ISC_R_SUCCESS: + res = token_value(&token, keywords); /* modifies yylval */ + break; + + case ISC_R_EOF: + res = 0; + break; + + case ISC_R_UNBALANCED: + parser_error(ISC_TRUE, + "%s: %d: unbalanced parentheses", + isc_lex_getsourcename(mylexer), + (int)isc_lex_getsourceline(mylexer)); + res = -1; + break; + + case ISC_R_NOSPACE: + parser_error(ISC_TRUE, + "%s: %d: token too big.", + isc_lex_getsourcename(mylexer), + (int)isc_lex_getsourceline(mylexer)); + res = -1; + break; + + case ISC_R_UNEXPECTEDEND: + parser_error(ISC_TRUE, + "%s: %d: unexpected EOF", + isc_lex_getsourcename(mylexer), + (int)isc_lex_getsourceline(mylexer)); + res = -1; + break; + + default: + parser_error(ISC_TRUE, + "%s: %d unknown lexer error (%d)", + isc_lex_getsourcename(mylexer), + (int)isc_lex_getsourceline(mylexer), + (int)res); + res = -1; + break; + } + + + lastyylval = yylval; + lasttoken = res; + + return (res); +} + + + +static char * +token_to_text(int token, YYSTYPE lval) { + static char buffer[1024]; + int i; + + /* Yacc keeps token numbers above 128, it seems. */ + if (token < 128) { + if (token == 0) + strncpy(buffer, "<end of file>", sizeof buffer); + else + if ((unsigned int) sprintf(buffer, "'%c'", token) + >= sizeof buffer) { + abort(); + } + } else { + switch (token) { + case L_STRING: + if ((unsigned int) sprintf(buffer, "'%s'", + lval.text) >= + sizeof buffer) { + abort(); + } + break; + case L_QSTRING: + if ((unsigned int) sprintf(buffer, "\"%s\"", + lval.text) >= + sizeof buffer) { + abort(); + } + break; + case L_IP6ADDR: + strcpy(buffer, "UNAVAILABLE-IPV6-ADDRESS"); + inet_ntop(AF_INET6, lval.ip6_addr.s6_addr, + buffer, sizeof buffer); + break; + case L_IP4ADDR: + strcpy(buffer, "UNAVAILABLE-IPV4-ADDRESS"); + inet_ntop(AF_INET, &lval.ip4_addr.s_addr, + buffer, sizeof buffer); + break; + case L_INTEGER: + sprintf(buffer, "%lu", (unsigned long)lval.ul_int); + break; + case L_END_INCLUDE: + strcpy (buffer, "<end of include>"); + break; + default: + for (i = 0 ; keyword_tokens[i].token != NULL ; i++) { + if (keyword_tokens[i].yaccval == token) + break; + } + + if (keyword_tokens[i].token == NULL) { + sprintf(buffer, "UNKNOWN-TOKEN-TYPE (%d)", + (int)token); + } else { + strncpy(buffer, keyword_tokens[i].token, + sizeof buffer - 1); + buffer[sizeof buffer - 1] = '\0'; + } + break; + } + } + + return (buffer); +} + + +static void +parser_complain(isc_boolean_t is_warning, isc_boolean_t print_last_token, + const char *format, va_list args) +{ + static char where[ISC_DIR_PATHMAX + 100]; + static char message[2048]; + int level = ISC_LOG_ERROR; + const char *filename = isc_lex_getsourcename(mylexer); + int lineno = isc_lex_getsourceline(mylexer); + + /* + * We can't get a trace of the include files we may be nested in + * (lex.c has the structures hidden). So we only report the current + * file. + */ + if (filename == NULL) { + filename = "(none)"; + } + + if (is_warning) { + level = ISC_LOG_WARNING; + } + + sprintf(where, "%s:%d: ", filename, lineno); + if ((unsigned int)vsprintf(message, format, args) >= sizeof message) + FATAL_ERROR(__FILE__, __LINE__, + "error message would overflow"); + + if (print_last_token) { + if (dns_lctx != NULL) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, level, + "%s%s near `%s'", where, message, + token_to_text(lasttoken, lastyylval)); + } else { + fprintf(stderr, "%s%s near `%s'\n", where, message, + token_to_text(lasttoken, lastyylval)); + } + } else { + if (dns_lctx != NULL) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, level, + "%s%s", where, message); + } else { + fprintf(stderr, "%s%s\n", where, message); + } + } +} + + + + +/* + * For reporting items that are semantic, but not syntactic errors + */ +static void +parser_error(isc_boolean_t lasttoken, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + parser_complain(ISC_TRUE, lasttoken, fmt, args); + va_end(args); + + currcfg->errors++; +} + + +static void +parser_warning(isc_boolean_t lasttoken, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + parser_complain(ISC_FALSE, lasttoken, fmt, args); + va_end(args); + + currcfg->warnings++; +} + + +static isc_boolean_t +int_too_big(isc_uint32_t base, isc_uint32_t mult) { + isc_uint32_t max = UINT_MAX; + + if ((max / mult) < base) { + return ISC_TRUE; + } else { + return ISC_FALSE; + } +} + + +static void +yyerror(const char *string) +{ + parser_error(ISC_TRUE, string); +} + + + +static int +token_value(isc_token_t *token, isc_symtab_t *symtable) +{ + int res = -1; + const char *tokstring; + char tmpident [2]; + isc_symvalue_t keywordtok; + + switch (token->type) { + case isc_tokentype_unknown: + if (debug_lexer) { + fprintf(stderr, "unknown lexer token\n"); + } + + res = -1; + break; + + case isc_tokentype_special: + case isc_tokentype_string: + if (token->type == isc_tokentype_special) { + tmpident[0] = token->value.as_char; + tmpident[1] = '\0'; + tokstring = tmpident; + } else { + tokstring = token->value.as_textregion.base; + } + + if (debug_lexer) { + fprintf(stderr, "lexer token: %s : %s\n", + (token->type == isc_tokentype_special ? + "special" : "string"), tokstring); + } + + res = isc_symtab_lookup(symtable, tokstring, + KEYWORD_SYM_TYPE, &keywordtok); + + if (res != ISC_R_SUCCESS) { + res = intuit_token(tokstring); + } else { + res = keywordtok.as_integer; + } + break; + + case isc_tokentype_number: + yylval.ul_int = (isc_uint32_t)token->value.as_ulong; + res = L_INTEGER; + + if(debug_lexer) { + fprintf(stderr, "lexer token: number : %lu\n", + (unsigned long)yylval.ul_int); + } + + break; + + case isc_tokentype_qstring: + yylval.text = isc_mem_strdup(memctx, + token->value.as_textregion.base); + if (yylval.text == NULL) { + res = -1; + } else { + res = L_QSTRING; + } + + if (debug_lexer) { + fprintf(stderr, "lexer token: qstring : \"%s\"\n", + yylval.text); + } + + break; + + case isc_tokentype_eof: + res = isc_lex_close(mylexer); + INSIST(res == ISC_R_NOMORE || res == ISC_R_SUCCESS); + + if (isc_lex_getsourcename(mylexer) == NULL) { + /* the only way to tell that we + * closed the main file and not an included file + */ + if (debug_lexer) { + fprintf(stderr, "lexer token: EOF\n"); + } + res = 0; + } else { + if (debug_lexer) { + fprintf(stderr, "lexer token: EOF (main)\n"); + } + res = L_END_INCLUDE; + } + break; + + case isc_tokentype_initialws: + if (debug_lexer) { + fprintf(stderr, "lexer token: initial ws\n"); + } + res = -1; + break; + + case isc_tokentype_eol: + if (debug_lexer) { + fprintf(stderr, "lexer token: eol\n"); + } + res = -1; + break; + + case isc_tokentype_nomore: + if (debug_lexer) { + fprintf(stderr, "lexer token: nomore\n"); + } + res = -1; + break; + } + + return (res); +} + + + + +static int +intuit_token(const char *string) +{ + int resval; + + if (is_ip4addr(string, &yylval.ip4_addr)) { + resval = L_IP4ADDR; + } else if (is_ip6addr(string, &yylval.ip6_addr)) { + resval = L_IP6ADDR; + } else { + yylval.text = isc_mem_strdup(memctx, string); + if (yylval.text == NULL) { + resval = -1; + } else { + resval = L_STRING; + } + } + + return (resval); +} + + +/* + * Conversion Routines + */ + +static isc_boolean_t +unit_to_uint32(char *in, isc_uint32_t *out) { + int c, units_done = 0; + isc_uint32_t result = 0L; + + INSIST(in != NULL); + + for (; (c = *in) != '\0'; in++) { + if (units_done) + return (ISC_FALSE); + if (isdigit(c)) { + result *= 10; + result += (c - '0'); + } else { + switch (c) { + case 'k': + case 'K': + result *= 1024; + units_done = 1; + break; + case 'm': + case 'M': + result *= (1024*1024); + units_done = 1; + break; + case 'g': + case 'G': + result *= (1024*1024*1024); + units_done = 1; + break; + default: + return (ISC_FALSE); + } + } + } + + *out = result; + return (ISC_TRUE); +} + + +static isc_boolean_t +is_ip6addr(const char *string, struct in6_addr *addr) +{ + if (inet_pton(AF_INET6, string, addr) != 1) { + return ISC_FALSE; + } + return ISC_TRUE; +} + + + +static isc_boolean_t +is_ip4addr(const char *string, struct in_addr *addr) +{ + char addrbuf[sizeof "xxx.xxx.xxx.xxx" + 1]; + const char *p = string; + int dots = 0; + char dot = '.'; + + while (*p) { + if (!isdigit(*p & 0xff) && *p != dot) { + return (ISC_FALSE); + } else if (!isdigit(*p & 0xff)) { + dots++; + } + p++; + } + + if (dots > 3) { + return (ISC_FALSE); + } else if (dots < 3) { + if (dots == 1) { + if (strlen(string) + 5 <= sizeof (addrbuf)) { + strcpy(addrbuf, string); + strcat(addrbuf, ".0.0"); + } else { + return (ISC_FALSE); + } + } else if (dots == 2) { + if (strlen(string) + 3 <= sizeof (addrbuf)) { + strcpy(addrbuf, string); + strcat(addrbuf, ".0"); + } else { + return (ISC_FALSE); + } + } + } else if (strlen(string) < sizeof addrbuf) { + strcpy (addrbuf, string); + } else { + return (ISC_FALSE); + } + + if (inet_pton(AF_INET, addrbuf, addr) != 1) { + return ISC_FALSE; + } + return ISC_TRUE; +} diff --git a/lib/dns/config/confpvt.h b/lib/dns/config/confpvt.h new file mode 100644 index 00000000..402054d2 --- /dev/null +++ b/lib/dns/config/confpvt.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#ifndef DNS_CONFIG_CONFPVT_H +#define DNS_CONFIG_CONFPVT_H 1 + +/***** + ***** Module Info + *****/ + +/* + * Some private definitions for config module internal use. + */ + +/* + * Various structures keep track of whether fields have been assigned + * to. They do this with a bit field. + */ +#define DNS_C_SETBITS_SIZE (sizeof(dns_c_setbits_t) * 8) +#define DNS_C_SETBIT(bit, flags) \ + (*(flags) |= ((dns_c_setbits_t)1 << (bit))) +#define DNS_C_CLEARBIT(bit, flags) \ + (*(flags) &= ~((dns_c_setbits_t)1 << (bit))) +#define DNS_C_CHECKBIT(bit,flags) \ + ISC_TF((*(flags) & ((dns_c_setbits_t)1 << (bit))) == ((dns_c_setbits_t)1 << (bit))) + +#endif diff --git a/lib/dns/config/confresolv.c b/lib/dns/config/confresolv.c new file mode 100644 index 00000000..fff0609d --- /dev/null +++ b/lib/dns/config/confresolv.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <dns/confresolv.h> +#include <dns/result.h> + + +#include "confpvt.h" + +isc_result_t +dns_c_resolv_new(isc_mem_t *mem, dns_c_resolv_t **cfgres) +{ + (void) mem; (void) cfgres; + + /* XXX nothing yet */ + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_resolv_delete(dns_c_resolv_t **cfgres) +{ + (void) cfgres; + /* XXX nothin yet */ + + return (ISC_R_SUCCESS); +} + + + diff --git a/lib/dns/config/confrrset.c b/lib/dns/config/confrrset.c new file mode 100644 index 00000000..3291c08b --- /dev/null +++ b/lib/dns/config/confrrset.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <isc/assertions.h> +#include <isc/magic.h> + +#include <dns/confrrset.h> +#include <dns/confcommon.h> + + +isc_result_t +dns_c_rrsolist_clear(dns_c_rrsolist_t *olist) +{ + dns_c_rrso_t *elem; + + REQUIRE(DNS_C_RRSOLIST_VALID(olist)); + + elem = ISC_LIST_HEAD(olist->elements); + while (elem != NULL) { + ISC_LIST_UNLINK(olist->elements, elem, next); + dns_c_rrso_delete(&elem); + elem = ISC_LIST_HEAD(olist->elements); + } + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_rrsolist_append(dns_c_rrsolist_t *dest, + dns_c_rrsolist_t *src) +{ + dns_c_rrso_t *oldelem; + dns_c_rrso_t *newelem; + isc_result_t res; + + REQUIRE(DNS_C_RRSOLIST_VALID(dest)); + REQUIRE(DNS_C_RRSOLIST_VALID(src)); + + oldelem = ISC_LIST_HEAD(src->elements); + while (oldelem != NULL) { + res = dns_c_rrso_copy(dest->mem, &newelem, oldelem); + if (res != ISC_R_SUCCESS) { + return (res); + } + + ISC_LIST_APPEND(dest->elements, newelem, next); + oldelem = ISC_LIST_NEXT(oldelem, next); + } + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_rrsolist_new(isc_mem_t *mem, dns_c_rrsolist_t **rval) +{ + dns_c_rrsolist_t *ro; + + ro = isc_mem_get(mem, sizeof *ro); + if (ro == NULL) { + return (ISC_R_NOMEMORY); + } + + ISC_LIST_INIT(ro->elements); + ro->mem = mem; + ro->magic = DNS_C_RRSOLIST_MAGIC; + + *rval = ro; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_rrso_new(isc_mem_t *mem, dns_c_rrso_t **res, + dns_rdataclass_t oclass, + dns_rdatatype_t otype, char *name, dns_c_ordering_t ordering) +{ + dns_c_rrso_t *newo; + + REQUIRE(mem != NULL); + REQUIRE(res != NULL); + + if (name == NULL) { + name = "*"; + } + + newo = isc_mem_get(mem, sizeof *newo); + if (newo == NULL) { + return (ISC_R_NOMEMORY); + } + + newo->magic = DNS_C_RRSO_MAGIC; + newo->mem = mem; + newo->otype = otype; + newo->oclass = oclass; + newo->ordering = ordering; + ISC_LINK_INIT(newo, next); + + newo->name = isc_mem_strdup(mem, name); + if (newo->name == NULL) { + newo->magic = 0; + isc_mem_put(mem, newo, sizeof *newo); + return (ISC_R_NOMEMORY); + } + + *res = newo; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_rrsolist_delete(dns_c_rrsolist_t **list) +{ + dns_c_rrso_t *elem, *q; + dns_c_rrsolist_t *l; + isc_result_t r; + + REQUIRE(list != NULL); + REQUIRE(DNS_C_RRSOLIST_VALID(*list)); + + l = *list; + + elem = ISC_LIST_HEAD(l->elements); + while (elem != NULL) { + q = ISC_LIST_NEXT(elem, next); + ISC_LIST_UNLINK(l->elements, elem, next); + r = dns_c_rrso_delete(&elem); + if (r != ISC_R_SUCCESS) { + return (r); + } + + elem = q; + } + + l->magic = 0; + isc_mem_put(l->mem, l, sizeof *l); + + *list = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_rrso_delete(dns_c_rrso_t **order) +{ + dns_c_rrso_t *oldo; + + REQUIRE(order != NULL); + REQUIRE(DNS_C_RRSO_VALID(*order)); + + oldo = *order; + + REQUIRE(oldo->name != NULL); + isc_mem_free(oldo->mem, oldo->name); + + oldo->magic = 0; + isc_mem_put(oldo->mem, oldo, sizeof *oldo); + + *order = NULL; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_rrso_copy(isc_mem_t *mem, dns_c_rrso_t **dest, + dns_c_rrso_t *source) +{ + dns_c_rrso_t *newo; + isc_result_t res; + + REQUIRE(DNS_C_RRSO_VALID(*dest)); + REQUIRE(DNS_C_RRSO_VALID(source)); + + res = dns_c_rrso_new(mem, &newo, source->oclass, + source->otype, source->name, + source->ordering); + if (res == ISC_R_SUCCESS) { + *dest = newo; + } else { + *dest = NULL; + } + + return (res); +} + + +isc_result_t +dns_c_rrsolist_copy(isc_mem_t *mem, dns_c_rrsolist_t **dest, + dns_c_rrsolist_t *source) + +{ + dns_c_rrsolist_t *nlist; + dns_c_rrso_t *elem; + dns_c_rrso_t *newe; + isc_result_t res; + + REQUIRE(DNS_C_RRSOLIST_VALID(source)); + REQUIRE(dest != NULL); + + res = dns_c_rrsolist_new(mem, &nlist); + if (res != DNS_R_SUCCESS) { + return (res); + } + + elem = ISC_LIST_HEAD(source->elements); + while (elem != NULL) { + res = dns_c_rrso_copy(mem, &newe, elem); + if (res != DNS_R_SUCCESS) { + dns_c_rrsolist_delete(&nlist); + return (res); + } + + ISC_LIST_APPEND(nlist->elements, newe, next); + + elem = ISC_LIST_NEXT(elem, next); + } + + *dest = nlist; + + return (ISC_R_SUCCESS); +} + + +void +dns_c_rrsolist_print(FILE *fp, int indent, + dns_c_rrsolist_t *rrlist) +{ + dns_c_rrso_t *or; + + REQUIRE(DNS_C_RRSOLIST_VALID(rrlist)); + + if (ISC_LIST_EMPTY(rrlist->elements)) { + return; + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "rrset-order {\n"); + + or = ISC_LIST_HEAD(rrlist->elements); + while (or != NULL) { + dns_c_rrso_print(fp, indent + 1, or); + or = ISC_LIST_NEXT(or, next); + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "};\n"); + +} + + +void +dns_c_rrso_print(FILE *fp, int indent, dns_c_rrso_t *order) +{ + REQUIRE(DNS_C_RRSO_VALID(order)); + + dns_c_printtabs(fp, indent); + + fputs("class ", fp); + if (order->oclass == dns_rdataclass_any) { + fputc('*', fp); + } else { + dns_c_dataclass_tostream(fp, order->oclass); + } + + + fputs(" type ", fp); + if (order->otype == dns_rdatatype_any) { + fputc('*', fp); + } else { + dns_c_datatype_tostream(fp, order->otype); + } + + fprintf(fp, " name %s", order->name); + + fprintf(fp, " order %s", + dns_c_ordering2string(order->ordering, ISC_TRUE)); + + fputs(";\n", fp); +} diff --git a/lib/dns/config/confserv.c b/lib/dns/config/confserv.c new file mode 100644 index 00000000..5181ffa6 --- /dev/null +++ b/lib/dns/config/confserv.c @@ -0,0 +1,414 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <sys/types.h> /* XXXRTH */ + +#include <string.h> + +#include <isc/assertions.h> +#include <isc/magic.h> +#include <isc/net.h> + +#include <dns/confserv.h> +#include <dns/confcommon.h> +#include "confpvt.h" + + +/* + * Bit positions in the dns_c_srv_t structure flags field + */ +#define BOGUS_BIT 0 +#define SERVER_TRANSFER_FORMAT_BIT 1 +#define TRANSFERS_BIT 2 +#define SUPPORT_IXFR_BIT 3 + +isc_result_t +dns_c_srvlist_new(isc_mem_t *mem, dns_c_srvlist_t **list) +{ + dns_c_srvlist_t *l; + + REQUIRE(list != NULL); + + l = isc_mem_get(mem, sizeof *l); + if (l == NULL) { + return (ISC_R_NOMEMORY); + } + + ISC_LIST_INIT(l->elements); + l->mem = mem; + l->magic = DNS_C_SRVLIST_MAGIC; + + *list = l; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_srvlist_delete(dns_c_srvlist_t **list) +{ + dns_c_srvlist_t *l; + dns_c_srv_t *server, *stmp; + isc_result_t r; + + REQUIRE(list != NULL); + REQUIRE(DNS_C_SRVLIST_VALID(*list)); + + l = *list; + + server = ISC_LIST_HEAD(l->elements); + while (server != NULL) { + stmp = ISC_LIST_NEXT(server, next); + ISC_LIST_UNLINK(l->elements, server, next); + r = dns_c_srv_delete(&server); + if (r != ISC_R_SUCCESS) { + return (r); + } + + server = stmp; + } + + l->magic = 0; + isc_mem_put(l->mem, l, sizeof *l); + + *list = NULL; + + return (ISC_R_SUCCESS); +} + + +void +dns_c_srvlist_print(FILE *fp, int indent, + dns_c_srvlist_t *servers) +{ + dns_c_srv_t *server; + + REQUIRE(fp != NULL); + REQUIRE(DNS_C_SRVLIST_VALID(servers)); + + server = ISC_LIST_HEAD(servers->elements); + while (server != NULL) { + dns_c_srv_print(fp, indent, server); + server = ISC_LIST_NEXT(server, next); + if (server != NULL) { + fprintf(fp, "\n"); + } + } + + return; +} + + +isc_result_t +dns_c_srvlist_servbyaddr(dns_c_srvlist_t *servers, + isc_sockaddr_t addr, dns_c_srv_t **retval) +{ + dns_c_srv_t *server; + isc_result_t res; + + REQUIRE(retval != NULL); + REQUIRE(DNS_C_SRVLIST_VALID(servers)); + + server = ISC_LIST_HEAD(servers->elements); + while (server != NULL) { + if (isc_sockaddr_eqaddr(&addr, &server->address)) { + break; + } + + server = ISC_LIST_NEXT(server, next); + } + + if (server != NULL) { + *retval = server; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + + + +isc_result_t +dns_c_srv_new(isc_mem_t *mem, isc_sockaddr_t addr, + dns_c_srv_t **server) +{ + dns_c_srv_t *serv; + + REQUIRE(server != NULL); + + serv = isc_mem_get(mem, sizeof *serv); + if (serv == NULL) { + return (ISC_R_NOMEMORY); + } + + serv->magic = DNS_C_SRV_MAGIC; + serv->address = addr; + serv->mem = mem; + serv->bogus = ISC_FALSE; + serv->transfer_format = dns_one_answer; + serv->transfers = 0; + serv->support_ixfr = ISC_FALSE; + serv->keys = NULL; + + memset(&serv->bitflags, 0x0, sizeof serv->bitflags); + + ISC_LINK_INIT(serv, next); + + *server = serv; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_srv_delete(dns_c_srv_t **server) +{ + dns_c_srv_t *serv; + isc_mem_t *mem; + + REQUIRE(server != NULL); + REQUIRE(DNS_C_SRV_VALID(*server)); + + serv = *server; + + mem = serv->mem; + serv->mem = NULL; + serv->magic = 0; + + if (serv->keys != NULL) + dns_c_kidlist_delete(&serv->keys); + + isc_mem_put(mem, serv, sizeof *serv); + + *server = NULL; + + return (ISC_R_SUCCESS); +} + + +void +dns_c_srv_print(FILE *fp, int indent, dns_c_srv_t *server) +{ + REQUIRE(DNS_C_SRV_VALID(server)); + REQUIRE(fp != NULL); + + dns_c_printtabs(fp, indent); + fprintf(fp, "server "); + dns_c_print_ipaddr(fp, &server->address); + fprintf(fp, " {\n"); + + if (DNS_C_CHECKBIT(BOGUS_BIT, &server->bitflags)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "bogus %s;\n", + (server->bogus ? "true" : "false")); + } + + if (DNS_C_CHECKBIT(SERVER_TRANSFER_FORMAT_BIT, &server->bitflags)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "transfer-format %s;\n", + dns_c_transformat2string(server->transfer_format, + ISC_TRUE)); + } + + if (DNS_C_CHECKBIT(TRANSFERS_BIT, &server->bitflags)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "transfers %d;\n", server->transfers); + } + + if (DNS_C_CHECKBIT(SUPPORT_IXFR_BIT,&server->bitflags)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "support-ixfr %s;\n", + (server->support_ixfr ? "true" : "false")); + } + + if (server->keys != NULL) { + dns_c_kidlist_print(fp, indent + 1, server->keys); + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "};\n"); +} + + +isc_result_t +dns_c_srv_setbogus(dns_c_srv_t *server, isc_boolean_t newval) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_SRV_VALID(server)); + + existed = DNS_C_CHECKBIT(BOGUS_BIT, &server->bitflags); + + server->bogus = newval; + DNS_C_SETBIT(BOGUS_BIT, &server->bitflags); + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_srv_getbogus(dns_c_srv_t *server, + isc_boolean_t *retval) +{ + REQUIRE(DNS_C_SRV_VALID(server)); + REQUIRE(retval != NULL); + + if (DNS_C_CHECKBIT(BOGUS_BIT, &server->bitflags)) { + *retval = server->bogus; + return (ISC_R_SUCCESS); + } else { + return (ISC_R_NOTFOUND); + } +} + + +isc_result_t +dns_c_srv_setsupportixfr(dns_c_srv_t *server, + isc_boolean_t newval) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_SRV_VALID(server)); + + existed = DNS_C_CHECKBIT(SUPPORT_IXFR_BIT, &server->bitflags); + + server->support_ixfr = newval; + DNS_C_SETBIT(SUPPORT_IXFR_BIT, &server->bitflags); + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_srv_getsupportixfr(dns_c_srv_t *server, + isc_boolean_t *retval) +{ + REQUIRE(DNS_C_SRV_VALID(server)); + REQUIRE(retval != NULL); + + if (DNS_C_CHECKBIT(SUPPORT_IXFR_BIT, &server->bitflags)) { + *retval = server->support_ixfr; + return (ISC_R_SUCCESS); + } else { + return (ISC_R_NOTFOUND); + } +} + + +isc_result_t +dns_c_srv_settransfers(dns_c_srv_t *server, + isc_int32_t newval) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_SRV_VALID(server)); + + existed = DNS_C_CHECKBIT(TRANSFERS_BIT, &server->bitflags); + + server->transfers = newval; + DNS_C_SETBIT(TRANSFERS_BIT, &server->bitflags); + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_srv_gettransfers(dns_c_srv_t *server, + isc_int32_t *retval) +{ + REQUIRE(DNS_C_SRV_VALID(server)); + REQUIRE(retval != NULL); + + if (DNS_C_CHECKBIT(TRANSFERS_BIT, &server->bitflags)) { + *retval = server->transfers; + return (ISC_R_SUCCESS); + } else { + return (ISC_R_NOTFOUND); + } +} + + +isc_result_t +dns_c_srv_settransferformat(dns_c_srv_t *server, + dns_transfer_format_t newval) +{ + isc_boolean_t existed; + + REQUIRE(DNS_C_SRV_VALID(server)); + + existed = DNS_C_CHECKBIT(SERVER_TRANSFER_FORMAT_BIT, + &server->bitflags); + + server->transfer_format = newval; + DNS_C_SETBIT(SERVER_TRANSFER_FORMAT_BIT, &server->bitflags); + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_srv_gettransferformat(dns_c_srv_t *server, + dns_transfer_format_t *retval) +{ + REQUIRE(DNS_C_SRV_VALID(server)); + REQUIRE(retval != NULL); + + if (DNS_C_CHECKBIT(SERVER_TRANSFER_FORMAT_BIT, &server->bitflags)) { + *retval = server->transfer_format; + return (ISC_R_SUCCESS); + } else { + return (ISC_R_NOTFOUND); + } +} + + +isc_result_t +dns_c_srv_getkeys(dns_c_srv_t *server, dns_c_kidlist_t **retval) +{ + REQUIRE(DNS_C_SRV_VALID(server)); + REQUIRE(retval != NULL); + + *retval = server->keys; + + return (server->keys == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_srv_setkeys(dns_c_srv_t *server, dns_c_kidlist_t *newval) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_SRV_VALID(server)); + REQUIRE(DNS_C_KEYIDLIST_VALID(newval)); + + if (server->keys != NULL) { + dns_c_kidlist_delete(&server->keys); + existed = ISC_TRUE; + } + + server->keys = newval; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + diff --git a/lib/dns/config/confview.c b/lib/dns/config/confview.c new file mode 100644 index 00000000..1afdf671 --- /dev/null +++ b/lib/dns/config/confview.c @@ -0,0 +1,1056 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <sys/types.h> + +#include <isc/assertions.h> +#include <isc/magic.h> +#include <isc/net.h> + +#include <dns/confacl.h> +#include <dns/confzone.h> +#include <dns/confcommon.h> +#include <dns/confview.h> +#include <dns/confzone.h> +#include <dns/log.h> + +#include "confpvt.h" + +#define CHECKNAME_PRIM_BIT 1 +#define CHECKNAME_SEC_BIT 2 +#define CHECKNAME_RESP_BIT 3 +#define MULTIPLE_CNAMES_BIT 4 +#define DIALUP_BIT 5 +#define FETCH_GLUE_BIT 6 +#define HAS_OLD_CLIENTS_BIT 7 +#define HOST_STATISTICS_BIT 8 +#define MAINTAIN_IXFR_BASE_BIT 9 +#define NOTIFY_BIT 11 +#define RECURSION_BIT 12 +#define RFC2308_TYPE1_BIT 13 +#define USE_ID_POOL_BIT 14 +#define FAKE_IQUERY_BIT 15 +#define USE_IXFR_BIT 16 +#define TCP_CLIENTS_BIT 17 +#define RECURSIVE_CLIENTS_BIT 18 +#define CLEAN_INTERVAL_BIT 19 +#define MAX_LOG_SIZE_IXFR_BIT 20 +#define MAX_NCACHE_TTL_BIT 21 +#define MAX_TRANSFER_TIME_IN_BIT 22 +#define MAX_TRANSFER_TIME_OUT_BIT 23 +#define MAX_TRANSFER_IDLE_IN_BIT 24 +#define MAX_TRANSFER_IDLE_OUT_BIT 25 +#define STATS_INTERVAL_BIT 26 +#define TRANSFERS_IN_BIT 27 +#define TRANSFERS_OUT_BIT 28 +#define TRANSFERS_PER_NS_BIT 29 +#define TRANSFER_FORMAT_BIT 30 + +isc_result_t +dns_c_viewtable_new(isc_mem_t *mem, dns_c_viewtable_t **viewtable) +{ + dns_c_viewtable_t *table; + + REQUIRE(viewtable != NULL); + + table = isc_mem_get(mem, sizeof *table); + if (table == NULL) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Out of memory"); + return (ISC_R_NOMEMORY); + } + + table->magic = DNS_C_VIEWTABLE_MAGIC; + table->mem = mem; + + ISC_LIST_INIT(table->views); + + *viewtable = table; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_viewtable_delete(dns_c_viewtable_t **viewtable) +{ + dns_c_viewtable_t *table; + + REQUIRE(viewtable != NULL); + REQUIRE(DNS_C_VIEWTABLE_VALID(*viewtable)); + + table = *viewtable; + *viewtable = NULL; + + dns_c_viewtable_clear(table); + + table->magic = 0; + isc_mem_put(table->mem, table, sizeof *table); + + return (ISC_R_SUCCESS); +} + + +void +dns_c_viewtable_addview(dns_c_viewtable_t *viewtable, dns_c_view_t *view) +{ + REQUIRE(DNS_C_VIEWTABLE_VALID(viewtable)); + REQUIRE(DNS_C_VIEW_VALID(view)); + + ISC_LIST_APPEND(viewtable->views, view, next); +} + + + +void +dns_c_viewtable_rmview(dns_c_viewtable_t *viewtable, dns_c_view_t *view) +{ + REQUIRE(DNS_C_VIEWTABLE_VALID(viewtable)); + REQUIRE(DNS_C_VIEW_VALID(view)); + + ISC_LIST_UNLINK(viewtable->views, view, next); +} + + + +isc_result_t +dns_c_viewtable_clear(dns_c_viewtable_t *table) +{ + dns_c_view_t *elem; + dns_c_view_t *tmpelem; + isc_result_t r; + + REQUIRE(DNS_C_VIEWTABLE_VALID(table)); + + elem = ISC_LIST_HEAD(table->views); + while (elem != NULL) { + tmpelem = ISC_LIST_NEXT(elem, next); + ISC_LIST_UNLINK(table->views, elem, next); + + r = dns_c_view_delete(&elem); + if (r != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, + ISC_LOG_CRITICAL, + "Failed to delete view.\n"); + return (r); + } + + elem = tmpelem; + } + + return (ISC_R_SUCCESS); +} + + + +isc_result_t +dns_c_viewtable_viewbyname(dns_c_viewtable_t *viewtable, + const char *viewname, + dns_c_view_t **retval) +{ + dns_c_view_t *elem; + + REQUIRE(DNS_C_VIEWTABLE_VALID(viewtable)); + REQUIRE(retval != NULL); + REQUIRE(viewname != NULL); + REQUIRE(strlen(viewname) > 0); + + elem = ISC_LIST_HEAD(viewtable->views); + while (elem != NULL) { + if (strcmp(viewname, elem->name) == 0) { + break; + } + + elem = ISC_LIST_NEXT(elem, next); + } + + if (elem != NULL) { + *retval = elem; + } + + return (elem == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + + +isc_result_t +dns_c_viewtable_rmviewbyname(dns_c_viewtable_t *viewtable, + const char *name) +{ + dns_c_view_t *view; + isc_result_t res; + + REQUIRE(DNS_C_VIEWTABLE_VALID(viewtable)); + + res = dns_c_viewtable_viewbyname(viewtable, name, &view); + if (res == ISC_R_SUCCESS) { + ISC_LIST_UNLINK(viewtable->views, view, next); + dns_c_view_delete(&view); + } + + return (res); +} + + + +isc_result_t +dns_c_view_new(isc_mem_t *mem, const char *name, dns_c_view_t **newview) +{ + dns_c_view_t *view; + int i; + + + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + REQUIRE(newview != NULL); + + view = isc_mem_get(mem, sizeof *view); + if (view == NULL) { + return (ISC_R_NOMEMORY); + } + + /* XXXJAB not portable -- should set each field */ + memset(view, 0x0, sizeof *view); + + memset(&view->setflags, 0x0, sizeof (view->setflags)); + + view->magic = DNS_C_VIEW_MAGIC; + view->mem = mem; + + view->allowquery = NULL; + view->transferacl = NULL; + view->recursionacl = NULL; + view->blackhole = NULL; + view->sortlist = NULL; + view->topology = NULL; + view->forwarders = NULL; + view->listens = NULL; + view->ordering = NULL; + + for (i = 0 ; i < DNS_C_TRANSCOUNT ; i++) { + view->check_names[i] = dns_severity_fail; + } + + view->transfer_format = dns_one_answer; + + view->auth_nx_domain = ISC_FALSE; + view->dialup = ISC_FALSE; + view->fetch_glue = ISC_FALSE; + view->has_old_clients = ISC_FALSE; + view->host_statistics = ISC_FALSE; + view->maintain_ixfr_base = ISC_FALSE; + view->multiple_cnames = ISC_FALSE; + view->notify = ISC_FALSE; + view->recursion = ISC_FALSE; + view->rfc2308_type1 = ISC_FALSE; + view->use_id_pool = ISC_FALSE; + view->fake_iquery = ISC_FALSE; + view->use_ixfr = ISC_FALSE; + + view->clean_interval = 0; + view->lamettl = 0; /* XXX not implemented */ + view->max_log_size_ixfr = 0; + view->max_ncache_ttl = 0; + view->max_transfer_time_in = 0; + view->max_transfer_time_out = 0; + view->max_transfer_idle_in = 0; + view->max_transfer_idle_out = 0; + view->stats_interval = 0; + view->transfers_in = 0; + view->transfers_out = 0; + view->transfers_per_ns = 0; + + view->zonelist = NULL; + view->name = isc_mem_strdup(mem, name); + if (view->name == NULL) { + isc_mem_put(mem, view, sizeof *view); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Insufficient memory"); + } + + *newview = view; + + return (ISC_R_SUCCESS); +} + + +void +dns_c_viewtable_print(FILE *fp, int indent, + dns_c_viewtable_t *table) +{ + dns_c_view_t *view; + + REQUIRE(fp != NULL); + REQUIRE(indent >= 0); + REQUIRE(DNS_C_VIEWTABLE_VALID(table)); + + view = ISC_LIST_HEAD(table->views); + while (view != NULL) { + dns_c_view_print(fp, indent, view); + fprintf(fp, "\n"); + + view = ISC_LIST_NEXT(view, next); + } +} + +void +dns_c_view_print(FILE *fp, int indent, dns_c_view_t *view) +{ + dns_severity_t nameseverity; + + REQUIRE(DNS_C_VIEW_VALID(view)); + + dns_c_printtabs(fp, indent); + fprintf(fp, "view \"%s\" {\n", view->name); + + if (view->allowquery != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "allow-query "); + dns_c_ipmatchlist_print(fp, indent + 2, + view->allowquery); + fprintf(fp, ";\n"); + } + + if (view->transferacl != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "allow-transfer "); + dns_c_ipmatchlist_print(fp, indent + 2, + view->transferacl); + fprintf(fp, ";\n"); + } + + if (view->recursionacl != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "allow-recursion "); + dns_c_ipmatchlist_print(fp, indent + 2, + view->recursionacl); + fprintf(fp, ";\n"); + } + + if (view->blackhole != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "blackhole "); + dns_c_ipmatchlist_print(fp, indent + 2, + view->blackhole); + fprintf(fp, ";\n"); + } + + if (view->forwarders != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "forwarders "); + dns_c_iplist_print(fp, indent + 2, + view->forwarders); + fprintf(fp, ";\n"); + } + + if (view->sortlist != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "sortlist "); + dns_c_ipmatchlist_print(fp, indent + 2, + view->sortlist); + fprintf(fp, ";\n"); + } + + if (view->topology != NULL) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "topology "); + dns_c_ipmatchlist_print(fp, indent + 2, + view->topology); + fprintf(fp, ";\n"); + } + + if (view->listens != NULL) { + dns_c_lstnlist_print(fp, indent + 1, view->listens); + } + + if (view->ordering != NULL) { + dns_c_rrsolist_print(fp, indent + 1, view->ordering); + } + + if (DNS_C_CHECKBIT(CHECKNAME_PRIM_BIT, &view->setflags)) { + nameseverity = view->check_names[dns_trans_primary]; + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "check-names %s %s;\n", + dns_c_transport2string(dns_trans_primary, + ISC_TRUE), + dns_c_nameseverity2string(nameseverity, + ISC_TRUE)); + } + + if (DNS_C_CHECKBIT(CHECKNAME_SEC_BIT, &view->setflags)) { + nameseverity = view->check_names[dns_trans_secondary]; + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "check-names %s %s;\n", + dns_c_transport2string(dns_trans_secondary, + ISC_TRUE), + dns_c_nameseverity2string(nameseverity, + ISC_TRUE)); + } + + if (DNS_C_CHECKBIT(CHECKNAME_RESP_BIT, &view->setflags)) { + nameseverity = view->check_names[dns_trans_response]; + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "check-names %s %s;\n", + dns_c_transport2string(dns_trans_response, + ISC_TRUE), + dns_c_nameseverity2string(nameseverity, + ISC_TRUE)); + } + + + if (DNS_C_CHECKBIT(TRANSFER_FORMAT_BIT, &view->setflags)) { + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "transfer-format %s;\n", + dns_c_transformat2string(view->transfer_format, + ISC_TRUE)); + } + + + fprintf(fp, "\n"); + + + + /* XXXJAB rest of view fields */ + + if (view->zonelist != NULL) { + dns_c_zonelist_print(fp, indent + 1, view->zonelist); + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "};\n"); +} + + +isc_result_t +dns_c_view_setallowquery(dns_c_view_t *view, + dns_c_ipmatchlist_t *ipml, + isc_boolean_t deepcopy) +{ + isc_result_t res; + + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(DNS_C_IPMLIST_VALID(ipml)); + + if (view->allowquery != NULL) { + dns_c_ipmatchlist_detach(&view->allowquery); + } + + if (deepcopy) { + res = dns_c_ipmatchlist_copy(view->mem, + &view->allowquery, ipml); + } else { + view->allowquery = ipml; + res = ISC_R_SUCCESS; + } + + return (res); +} + + +isc_result_t +dns_c_view_setallowtransfer(dns_c_view_t *view, + dns_c_ipmatchlist_t *ipml, + isc_boolean_t deepcopy) +{ + isc_result_t res; + + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(DNS_C_IPMLIST_VALID(ipml)); + + if (view->transferacl != NULL) { + dns_c_ipmatchlist_detach(&view->transferacl); + } + + if (deepcopy) { + res = dns_c_ipmatchlist_copy(view->mem, + &view->transferacl, ipml); + } else { + view->transferacl = ipml; + res = ISC_R_SUCCESS; + } + + return (res); +} + + +isc_result_t +dns_c_view_setallowrecursion(dns_c_view_t *view, + dns_c_ipmatchlist_t *ipml, + isc_boolean_t deepcopy) +{ + isc_result_t res; + + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(DNS_C_IPMLIST_VALID(ipml)); + + if (view->recursionacl != NULL) { + dns_c_ipmatchlist_detach(&view->recursionacl); + } + + if (deepcopy) { + res = dns_c_ipmatchlist_copy(view->mem, + &view->recursionacl, ipml); + } else { + view->recursionacl = ipml; + res = ISC_R_SUCCESS; + } + + return (res); +} + + +isc_result_t +dns_c_view_setblackhole(dns_c_view_t *view, + dns_c_ipmatchlist_t *ipml, + isc_boolean_t deepcopy) +{ + isc_result_t res; + + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(DNS_C_IPMLIST_VALID(ipml)); + + if (view->blackhole != NULL) { + dns_c_ipmatchlist_detach(&view->blackhole); + } + + if (deepcopy) { + res = dns_c_ipmatchlist_copy(view->mem, + &view->blackhole, ipml); + } else { + view->blackhole = ipml; + res = ISC_R_SUCCESS; + } + + return (res); +} + + +isc_result_t +dns_c_view_setforwarders(dns_c_view_t *view, + dns_c_iplist_t *ipl, + isc_boolean_t deepcopy) +{ + isc_boolean_t existed = ISC_FALSE; + isc_result_t res; + + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(DNS_C_IPLIST_VALID(ipl)); + + if (view->forwarders != NULL) { + existed = ISC_TRUE; + dns_c_iplist_detach(&view->forwarders); + } + + if (deepcopy) { + res = dns_c_iplist_copy(view->mem, &view->forwarders, ipl); + } else { + view->forwarders = ipl; + res = ISC_R_SUCCESS; + } + + if (res == ISC_R_SUCCESS) { + return (existed ? ISC_R_EXISTS : res); + } else { + return (res); + } +} + + + +isc_result_t +dns_c_view_setsortlist(dns_c_view_t *view, + dns_c_ipmatchlist_t *ipml, + isc_boolean_t deepcopy) +{ + isc_result_t res; + + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(DNS_C_IPMLIST_VALID(ipml)); + + if (view->sortlist != NULL) { + dns_c_ipmatchlist_detach(&view->sortlist); + } + + if (deepcopy) { + res = dns_c_ipmatchlist_copy(view->mem, + &view->sortlist, ipml); + } else { + view->sortlist = ipml; + res = ISC_R_SUCCESS; + } + + return (res); +} + + +isc_result_t +dns_c_view_settopology(dns_c_view_t *view, + dns_c_ipmatchlist_t *ipml, + isc_boolean_t deepcopy) +{ + isc_result_t res; + + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(DNS_C_IPMLIST_VALID(ipml)); + + if (view->topology != NULL) { + dns_c_ipmatchlist_detach(&view->topology); + } + + if (deepcopy) { + res = dns_c_ipmatchlist_copy(view->mem, + &view->topology, ipml); + } else { + view->topology = ipml; + res = ISC_R_SUCCESS; + } + + return (res); +} + + +isc_result_t +dns_c_view_getallowquery(dns_c_view_t *view, dns_c_ipmatchlist_t **ipml) +{ + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(ipml != NULL); + + *ipml = view->allowquery; + + return (*ipml == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + +isc_result_t dns_c_view_getallowtransfer(dns_c_view_t *view, + dns_c_ipmatchlist_t **ipml) +{ + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(ipml != NULL); + + *ipml = view->transferacl; + + return (*ipml == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + +isc_result_t dns_c_view_getallowrecursion(dns_c_view_t *view, + dns_c_ipmatchlist_t **ipml) +{ + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(ipml != NULL); + + *ipml = view->recursionacl; + + return (*ipml == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + +isc_result_t dns_c_view_getblackhole(dns_c_view_t *view, + dns_c_ipmatchlist_t **ipml) +{ + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(ipml != NULL); + + *ipml = view->blackhole; + + return (*ipml == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + +isc_result_t dns_c_view_getforwarders(dns_c_view_t *view, + dns_c_iplist_t **ipl) +{ + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(ipl != NULL); + + *ipl = view->forwarders; + + return (*ipl == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + +isc_result_t dns_c_view_getsortlist(dns_c_view_t *view, + dns_c_ipmatchlist_t **ipml) +{ + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(ipml != NULL); + + *ipml = view->sortlist; + + return (*ipml == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + +isc_result_t dns_c_view_gettopology(dns_c_view_t *view, + dns_c_ipmatchlist_t **ipml) +{ + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(ipml != NULL); + + *ipml = view->topology; + + return (*ipml == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + + +isc_result_t +dns_c_view_getallowqueryexpanded(isc_mem_t *mem, + dns_c_view_t *view, + dns_c_acltable_t *acltable, + dns_c_ipmatchlist_t **retval) +{ + dns_c_ipmatchlist_t *newlist; + isc_result_t r; + + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(DNS_C_CONFACLTABLE_VALID(acltable)); + REQUIRE(retval != NULL); + + if (view->allowquery == NULL) { + newlist = NULL; + r = ISC_R_SUCCESS; + } else { + r = dns_c_ipmatchlist_copy(mem, &newlist, view->allowquery); + if (r != ISC_R_SUCCESS) { + return (r); + } + + r = dns_c_acl_expandacls(acltable, newlist); + } + + *retval = newlist; + + return (r); +} + + + +isc_result_t +dns_c_view_delete(dns_c_view_t **viewptr) +{ + dns_c_view_t *view; + + REQUIRE(viewptr != NULL); + REQUIRE(DNS_C_VIEW_VALID(*viewptr)); + + view = *viewptr; + + isc_mem_free(view->mem, view->name); + + if (view->allowquery != NULL) + dns_c_ipmatchlist_detach(&view->allowquery); + + if (view->transferacl != NULL) + dns_c_ipmatchlist_detach(&view->transferacl); + + if (view->recursionacl != NULL) + dns_c_ipmatchlist_detach(&view->recursionacl); + + if (view->blackhole != NULL) + dns_c_ipmatchlist_detach(&view->blackhole); + + if (view->forwarders != NULL) + dns_c_iplist_detach(&view->forwarders); + + if (view->sortlist != NULL) + dns_c_ipmatchlist_detach(&view->sortlist); + + if (view->topology != NULL) + dns_c_ipmatchlist_detach(&view->topology); + + if (view->listens != NULL) { + dns_c_lstnlist_delete(&view->listens); + } + + if (view->ordering != NULL) { + dns_c_rrsolist_delete(&view->ordering); + } + + if (view->zonelist != NULL) { + dns_c_zonelist_delete(&view->zonelist); + } + + view->magic = 0; + isc_mem_put(view->mem, view, sizeof *view); + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_view_getname(dns_c_view_t *view, const char **retval) +{ + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(retval != NULL); + + *retval = view->name; + + return (ISC_R_SUCCESS); +} + + + +isc_result_t +dns_c_view_addzone(dns_c_view_t *view, dns_c_zone_t *zone) +{ + isc_result_t res; + dns_c_zone_t *attached; + + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(DNS_C_ZONE_VALID(zone)); + + dns_c_zone_attach(zone, &attached); + + if (view->zonelist == NULL) { + res = dns_c_zonelist_new(view->mem, &view->zonelist); + if (res != ISC_R_SUCCESS) { + return (res); + } + } + + return (dns_c_zonelist_addzone(view->zonelist, attached)); +} + + +isc_result_t +dns_c_view_addlisten_on(dns_c_view_t *view, in_port_t port, + dns_c_ipmatchlist_t *ml, + isc_boolean_t copy) +{ + dns_c_lstnon_t *lo; + isc_result_t res; + + REQUIRE(DNS_C_VIEW_VALID(view)); + + if (view->listens == NULL) { + res = dns_c_lstnlist_new(view->mem, &view->listens); + if (res != ISC_R_SUCCESS) { + return (res); + } + } + + res = dns_c_lstnon_new(view->mem, &lo); + if (res != ISC_R_SUCCESS) { + return (res); + } + + lo->port = port; + res = dns_c_lstnon_setiml(lo, ml, copy); + + ISC_LIST_APPEND(view->listens->elements, lo, next); + + return (res); +} + + + +isc_result_t +dns_c_view_getlistenlist(dns_c_view_t *view, dns_c_lstnlist_t **ll) +{ + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(ll != NULL); + + *ll = NULL; + + if (view->listens != NULL) { + *ll = view->listens; + } + + return (*ll == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + +isc_result_t dns_c_view_setrrsetorderlist(dns_c_view_t *view, + isc_boolean_t copy, + dns_c_rrsolist_t *olist) +{ + isc_boolean_t existed; + isc_result_t res; + + REQUIRE(DNS_C_VIEW_VALID(view)); + + existed = (view->ordering == NULL ? ISC_FALSE : ISC_TRUE); + + if (copy) { + if (view->ordering == NULL) { + res = dns_c_rrsolist_new(view->mem, + &view->ordering); + if (res != ISC_R_SUCCESS) { + return (res); + } + } else { + dns_c_rrsolist_clear(view->ordering); + } + + res = dns_c_rrsolist_append(view->ordering, olist); + } else { + if (view->ordering != NULL) { + dns_c_rrsolist_delete(&view->ordering); + } + + view->ordering = olist; + res = ISC_R_SUCCESS; + } + + if (res == ISC_R_SUCCESS && existed) { + res = ISC_R_EXISTS; + } + + return (res); +} + + + + +isc_result_t dns_c_view_getrrsetorderlist(dns_c_view_t *view, + dns_c_rrsolist_t **olist) +{ + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(olist != NULL); + + if (view->ordering != NULL) { + *olist = view->ordering; + } + + return (*olist == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + + + +isc_result_t +dns_c_view_setchecknames(dns_c_view_t *view, + dns_c_trans_t transtype, + dns_severity_t sever) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_VIEW_VALID(view)); + + switch(transtype) { + case dns_trans_primary: + existed = DNS_C_CHECKBIT(CHECKNAME_PRIM_BIT, + &view->setflags); + DNS_C_SETBIT(CHECKNAME_PRIM_BIT, &view->setflags); + break; + + case dns_trans_secondary: + existed = DNS_C_CHECKBIT(CHECKNAME_SEC_BIT, + &view->setflags); + DNS_C_SETBIT(CHECKNAME_SEC_BIT, &view->setflags); + break; + + case dns_trans_response: + existed = DNS_C_CHECKBIT(CHECKNAME_RESP_BIT, + &view->setflags); + DNS_C_SETBIT(CHECKNAME_RESP_BIT, &view->setflags); + break; + + default: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "bad transport value: %d", transtype); + return (ISC_R_FAILURE); + } + + view->check_names[transtype] = sever; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + + +isc_result_t +dns_c_view_getchecknames(dns_c_view_t *view, + dns_c_trans_t transtype, + dns_severity_t *sever) +{ + isc_boolean_t isset = ISC_FALSE; + isc_result_t res; + + REQUIRE(DNS_C_VIEW_VALID(view)); + + REQUIRE(sever != NULL); + + switch (transtype) { + case dns_trans_primary: + isset = DNS_C_CHECKBIT(CHECKNAME_PRIM_BIT, + &view->setflags); + break; + + case dns_trans_secondary: + isset = DNS_C_CHECKBIT(CHECKNAME_SEC_BIT, + &view->setflags); + break; + + case dns_trans_response: + isset = DNS_C_CHECKBIT(CHECKNAME_RESP_BIT, + &view->setflags); + break; + + default: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "bad transport value: %d", transtype); + return (ISC_R_FAILURE); + } + + if (isset) { + *sever = view->check_names[transtype]; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t dns_c_view_settransferformat(dns_c_view_t *view, + dns_transfer_format_t format) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_VIEW_VALID(view)); + + existed = DNS_C_CHECKBIT(TRANSFER_FORMAT_BIT, + &view->setflags); + DNS_C_SETBIT(TRANSFER_FORMAT_BIT, &view->setflags); + + view->transfer_format = format; + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t dns_c_view_gettransferformat(dns_c_view_t *view, + dns_transfer_format_t *format) +{ + REQUIRE(DNS_C_VIEW_VALID(view)); + REQUIRE(format != NULL); + + + if (!DNS_C_CHECKBIT(TRANSFER_FORMAT_BIT, &view->setflags)) { + return (ISC_R_NOTFOUND); + } + + *format = view->transfer_format; + + return (ISC_R_SUCCESS); +} + + + diff --git a/lib/dns/config/confzone.c b/lib/dns/config/confzone.c new file mode 100644 index 00000000..11b5e091 --- /dev/null +++ b/lib/dns/config/confzone.c @@ -0,0 +1,3596 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +#include <config.h> + +#include <isc/assertions.h> + +#include <dns/confzone.h> +#include <dns/confcommon.h> +#include <dns/log.h> + +#include "confpvt.h" + + +/* + * Bit positions in the dns_c_masterzone_t structure setflags field. + */ +#define MZ_CHECK_NAME_BIT 0 +#define MZ_DIALUP_BIT 1 +#define MZ_NOTIFY_BIT 2 +#define MZ_MAINT_IXFR_BASE_BIT 3 +#define MZ_MAX_IXFR_LOG_BIT 4 +#define MZ_FORWARD_BIT 5 +#define MZ_MAX_TRANS_TIME_OUT_BIT 6 +#define MZ_MAX_TRANS_IDLE_OUT_BIT 7 + + + +/* + * Bit positions in the dns_c_slavezone_t structure setflags field. + */ +#define SZ_CHECK_NAME_BIT 0 +#define SZ_DIALUP_BIT 1 +#define SZ_MASTER_PORT_BIT 2 +#define SZ_TRANSFER_SOURCE_BIT 3 +#define SZ_MAX_TRANS_TIME_IN_BIT 4 +#define SZ_MAX_TRANS_TIME_OUT_BIT 5 +#define SZ_MAX_TRANS_IDLE_IN_BIT 6 +#define SZ_MAX_TRANS_IDLE_OUT_BIT 7 +#define SZ_NOTIFY_BIT 8 +#define SZ_MAINT_IXFR_BASE_BIT 9 +#define SZ_MAX_IXFR_LOG_BIT 10 +#define SZ_FORWARD_BIT 11 + + + +/* Bit positions of the stub zones */ +#define TZ_CHECK_NAME_BIT 0 +#define TZ_DIALUP_BIT 1 +#define TZ_MASTER_PORT_BIT 2 +#define TZ_TRANSFER_SOURCE_BIT 3 +#define TZ_MAX_TRANS_TIME_IN_BIT 4 +#define TZ_MAX_TRANS_TIME_OUT_BIT 5 +#define TZ_MAX_TRANS_IDLE_IN_BIT 6 +#define TZ_MAX_TRANS_IDLE_OUT_BIT 7 +#define TZ_FORWARD_BIT 8 + + +/* + * Bit positions in the dns_c_forwardzone_t structure setflags field. + */ +#define FZ_CHECK_NAME_BIT 0 +#define FZ_FORWARD_BIT 1 + + +/* + * Bit positions in the dns_c_hintzone_t structure setflags field. + */ +#define HZ_CHECK_NAME_BIT 0 + + +typedef enum { zones_preopts, zones_postopts, zones_all } zone_print_type; + +static isc_result_t master_zone_init(dns_c_masterzone_t *mzone); +static isc_result_t slave_zone_init(dns_c_slavezone_t *szone); +static isc_result_t stub_zone_init(dns_c_stubzone_t *szone); +static isc_result_t hint_zone_init(dns_c_hintzone_t *hzone); +static isc_result_t forward_zone_init(dns_c_forwardzone_t *fzone); +static isc_result_t zone_delete(dns_c_zone_t **zone); +static isc_result_t master_zone_clear(isc_mem_t *mem, + dns_c_masterzone_t *mzone); +static isc_result_t slave_zone_clear(isc_mem_t *mem, + dns_c_slavezone_t *szone); +static isc_result_t stub_zone_clear(isc_mem_t *mem, + dns_c_stubzone_t *szone); +static isc_result_t forward_zone_clear(isc_mem_t *mem, + dns_c_forwardzone_t *fzone); +static isc_result_t hint_zone_clear(isc_mem_t *mem, + dns_c_hintzone_t *hzone); + +static void master_zone_print(FILE *fp, int indent, + dns_c_masterzone_t *mzone); +static void slave_zone_print(FILE *fp, int indent, + dns_c_slavezone_t *szone); +static void stub_zone_print(FILE *fp, int indent, + dns_c_stubzone_t *szone); +static void hint_zone_print(FILE *fp, int indent, + dns_c_hintzone_t *hzone); +static void forward_zone_print(FILE *fp, int indent, + dns_c_forwardzone_t *fzone); +static isc_result_t set_iplist_field(isc_mem_t *mem, + dns_c_iplist_t **dest, + dns_c_iplist_t *src, + isc_boolean_t deepcopy); +static isc_result_t set_ipmatch_list_field(isc_mem_t *mem, + dns_c_ipmatchlist_t **dest, + dns_c_ipmatchlist_t *src, + isc_boolean_t deepcopy); + +static void zone_list_print(zone_print_type zpt, + FILE *fp, int indent, dns_c_zonelist_t *list); + + + +isc_result_t +dns_c_zonelist_new(isc_mem_t *mem, dns_c_zonelist_t **zlist) +{ + dns_c_zonelist_t *list; + + REQUIRE(zlist != NULL); + + list = isc_mem_get(mem, sizeof *list); + if (list == NULL) { + return (ISC_R_NOMEMORY); + } + + list->mem = mem; + list->magic = DNS_C_ZONELIST_MAGIC; + + ISC_LIST_INIT(list->zones); + + *zlist = list; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zonelist_delete(dns_c_zonelist_t **zlist) +{ + dns_c_zonelist_t *list; + dns_c_zonelem_t *zoneelem; + dns_c_zonelem_t *tmpelem; + dns_c_zone_t *zone; + isc_result_t res; + + REQUIRE(zlist != NULL); + REQUIRE(*zlist != NULL); + + list = *zlist; + + zoneelem = ISC_LIST_HEAD(list->zones); + while (zoneelem != NULL) { + tmpelem = ISC_LIST_NEXT(zoneelem, next); + ISC_LIST_UNLINK(list->zones, zoneelem, next); + + zone = zoneelem->thezone; + isc_mem_put(list->mem, zoneelem, sizeof *zoneelem); + + res = dns_c_zone_detach(&zone); + if (res != ISC_R_SUCCESS) { + return (res); + } + + zoneelem = tmpelem; + } + + list->magic = 0; + isc_mem_put(list->mem, list, sizeof *list); + + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_c_zonelist_addzone(dns_c_zonelist_t *zlist, + dns_c_zone_t *zone) +{ + dns_c_zonelem_t *zoneelem; + + REQUIRE(DNS_C_ZONELIST_VALID(zlist)); + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(zone->refcount > 0); + + zoneelem = isc_mem_get(zlist->mem, sizeof *zoneelem); + if (zoneelem == NULL) { + return (ISC_R_NOMEMORY); + } + + zoneelem->thezone = zone; + ISC_LINK_INIT(zoneelem, next); + + ISC_LIST_APPEND(zlist->zones, zoneelem, next); + + return (ISC_R_SUCCESS); +} + + + +isc_result_t +dns_c_zonelist_find(dns_c_zonelist_t *zlist, const char *name, + dns_c_zone_t **retval) +{ + dns_c_zonelem_t *zoneelem; + + REQUIRE(DNS_C_ZONELIST_VALID(zlist)); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + REQUIRE(retval != NULL); + + zoneelem = ISC_LIST_HEAD(zlist->zones); + while (zoneelem != NULL) { + REQUIRE(zoneelem->thezone != NULL); + + if (strcmp(name, zoneelem->thezone->name) == 0) { + break; + } + } + + if (zoneelem != NULL) { + *retval = zoneelem->thezone; + } + + return (zoneelem == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zonelist_rmbyname(dns_c_zonelist_t *zlist, + const char *name) +{ + dns_c_zonelem_t *zoneelem; + isc_result_t res; + + REQUIRE(DNS_C_ZONELIST_VALID(zlist)); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + + zoneelem = ISC_LIST_HEAD(zlist->zones); + while (zoneelem != NULL) { + REQUIRE(zoneelem->thezone != NULL); + + if (strcmp(name, zoneelem->thezone->name) == 0) { + break; + } + } + + if (zoneelem != NULL) { + ISC_LIST_UNLINK(zlist->zones, zoneelem, next); + res = dns_c_zone_detach(&zoneelem->thezone); + isc_mem_put(zlist->mem, zoneelem, sizeof *zoneelem); + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zonelist_rmzone(dns_c_zonelist_t *zlist, + dns_c_zone_t *zone) +{ + dns_c_zonelem_t *zoneelem; + isc_result_t res; + + REQUIRE(zlist != NULL); + REQUIRE(zone != NULL); + + zoneelem = ISC_LIST_HEAD(zlist->zones); + while (zoneelem != NULL) { + REQUIRE(zoneelem->thezone != NULL); + + if (zone == zoneelem->thezone) { + break; + } + } + + if (zoneelem != NULL) { + ISC_LIST_UNLINK(zlist->zones, zoneelem, next); + res = dns_c_zone_detach(&zoneelem->thezone); + isc_mem_put(zlist->mem, zoneelem, sizeof *zoneelem); + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +void +dns_c_zonelist_print(FILE *fp, int indent, + dns_c_zonelist_t *list) +{ + REQUIRE(DNS_C_ZONELIST_VALID(list)); + zone_list_print(zones_all, fp, indent, list); +} + + +void +dns_c_zonelist_printpreopts(FILE *fp, int indent, + dns_c_zonelist_t *list) +{ + REQUIRE(DNS_C_ZONELIST_VALID(list)); + zone_list_print(zones_preopts, fp, indent, list); +} + + +void +dns_c_zonelist_printpostopts(FILE *fp, int indent, + dns_c_zonelist_t *list) +{ + REQUIRE(DNS_C_ZONELIST_VALID(list)); + zone_list_print(zones_postopts, fp, indent, list); +} + + + +static void +zone_list_print(zone_print_type zpt, FILE *fp, int indent, + dns_c_zonelist_t *list) +{ + dns_c_zonelem_t *zoneelem; + + REQUIRE(fp != NULL); + REQUIRE(indent >= 0); + + if (list == NULL) { + return; + } + +#define PRINTIT(zone, zpt) \ + (zpt == zones_all || \ + (zone->view == NULL && \ + ((zpt == zones_preopts && zone->afteropts == ISC_FALSE) || \ + ((zpt == zones_postopts && zone->afteropts == ISC_TRUE))))) + + zoneelem = ISC_LIST_HEAD(list->zones); + while (zoneelem != NULL) { + if (PRINTIT(zoneelem->thezone, zpt)) { + dns_c_zone_print(fp, indent, zoneelem->thezone); + } + + zoneelem = ISC_LIST_NEXT(zoneelem, next); + if (zoneelem != NULL && PRINTIT(zoneelem->thezone, zpt)) { + fprintf(fp, "\n"); + } + } + +#undef PRINTIT + + return; +} + + +/* ************************************************************************ */ +/* ******************************** ZONEs ********************************* */ +/* ************************************************************************ */ + +isc_result_t +dns_c_zone_new(isc_mem_t *mem, + dns_c_zonetype_t ztype, dns_rdataclass_t zclass, + const char *name, const char *internalname, + dns_c_zone_t **zone) +{ + dns_c_zone_t *newzone; + isc_result_t res; + + REQUIRE(mem != NULL); + REQUIRE(name != NULL); + REQUIRE(strlen(name) > 0); + + newzone = isc_mem_get(mem, sizeof *newzone); + if (newzone == NULL) { + return (ISC_R_NOMEMORY); + } + + newzone->magic = DNS_C_ZONE_MAGIC; + newzone->mem = mem; + newzone->refcount = 1; + newzone->ztype = ztype; + newzone->zclass = zclass; + newzone->view = NULL; + newzone->afteropts = ISC_FALSE; + newzone->name = isc_mem_strdup(mem, name); + newzone->internalname = (internalname == NULL ? + isc_mem_strdup(mem, name) : + isc_mem_strdup(mem, internalname)); + + switch (ztype) { + case dns_c_zone_master: + res = master_zone_init(&newzone->u.mzone); + break; + + case dns_c_zone_slave: + res = slave_zone_init(&newzone->u.szone); + break; + + case dns_c_zone_stub: + res = stub_zone_init(&newzone->u.tzone); + break; + + case dns_c_zone_hint: + res = hint_zone_init(&newzone->u.hzone); + break; + + case dns_c_zone_forward: + res = forward_zone_init(&newzone->u.fzone); + break; + } + + *zone = newzone; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_detach(dns_c_zone_t **zone) +{ + dns_c_zone_t *zoneptr; + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(zone != NULL); + REQUIRE(DNS_C_ZONE_VALID(*zone)); + + zoneptr = *zone; + *zone = NULL; + + REQUIRE(zoneptr->refcount > 0); + zoneptr->refcount--; + + if (zoneptr->refcount == 0) { + res = zone_delete(&zoneptr); + } + + return (res); +} + + +void +dns_c_zone_attach(dns_c_zone_t *source, + dns_c_zone_t **target) +{ + REQUIRE(DNS_C_ZONE_VALID(source)); + REQUIRE(target != NULL); + + source->refcount++; + + *target = source; +} + + + +void +dns_c_zone_print(FILE *fp, int indent, dns_c_zone_t *zone) +{ + REQUIRE(fp != NULL); + REQUIRE(DNS_C_ZONE_VALID(zone)); + + dns_c_printtabs(fp, indent); + fprintf(fp, "zone \"%s\"", zone->name); + if (zone->zclass != dns_rdataclass_in) { + fputc(' ', fp); + dns_c_dataclass_tostream(fp, zone->zclass); + } + + fprintf(fp, " {\n"); + + switch (zone->ztype) { + case dns_c_zone_master: + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "type master;\n"); + master_zone_print(fp, indent + 1, &zone->u.mzone); + break; + + case dns_c_zone_slave: + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "type slave;\n"); + slave_zone_print(fp, indent + 1, &zone->u.szone); + break; + + case dns_c_zone_stub: + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "type stub;\n"); + stub_zone_print(fp, indent + 1, &zone->u.tzone); + break; + + case dns_c_zone_hint: + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "type hint;\n"); + hint_zone_print(fp, indent + 1, &zone->u.hzone); + break; + + case dns_c_zone_forward: + dns_c_printtabs(fp, indent + 1); + fprintf(fp, "type forward;\n"); + forward_zone_print(fp, indent + 1, &zone->u.fzone); + break; + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "};\n"); +} + + +isc_result_t +dns_c_zone_setfile(dns_c_zone_t *zone, const char *newfile) +{ + char **p = NULL; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(newfile != NULL); + REQUIRE(strlen(newfile) > 0); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.file; + break; + + case dns_c_zone_slave: + p = &zone->u.szone.file; + break; + + case dns_c_zone_stub: + p = &zone->u.tzone.file; + break; + + case dns_c_zone_hint: + p = &zone->u.hzone.file; + break; + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a file field"); + return (ISC_R_FAILURE); + } + + if (*p != NULL) { + isc_mem_free(zone->mem, *p); + res = ISC_R_EXISTS; + } else { + res = ISC_R_SUCCESS; + } + + *p = isc_mem_strdup(zone->mem, newfile); + if (*p == NULL) { + res = ISC_R_NOMEMORY; + } + + return (res); +} + + +isc_result_t +dns_c_zone_setchecknames(dns_c_zone_t *zone, + dns_severity_t severity) +{ + dns_severity_t *p = NULL; + dns_c_setbits_t *bits = NULL; + int bit = 0; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.check_names; + bits = &zone->u.mzone.setflags; + bit = MZ_CHECK_NAME_BIT; + break; + + case dns_c_zone_slave: + p = &zone->u.szone.check_names; + bits = &zone->u.szone.setflags; + bit = SZ_CHECK_NAME_BIT; + break; + + case dns_c_zone_stub: + p = &zone->u.tzone.check_names; + bits = &zone->u.tzone.setflags; + bit = TZ_CHECK_NAME_BIT; + break; + + case dns_c_zone_hint: + p = &zone->u.hzone.check_names; + bits = &zone->u.hzone.setflags; + bit = HZ_CHECK_NAME_BIT; + break; + + case dns_c_zone_forward: + p = &zone->u.fzone.check_names; + bits = &zone->u.fzone.setflags; + bit = FZ_CHECK_NAME_BIT; + break; + } + + if (DNS_C_CHECKBIT(bit, bits)) { + res = ISC_R_EXISTS; + } else { + res = ISC_R_SUCCESS; + } + + *p = severity; + DNS_C_SETBIT(bit, bits); + + return (res); +} + + +isc_result_t +dns_c_zone_setallowupd(dns_c_zone_t *zone, + dns_c_ipmatchlist_t *ipml, + isc_boolean_t deepcopy) +{ + dns_c_ipmatchlist_t **p = NULL; + isc_result_t res; + isc_boolean_t existed; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(DNS_C_IPMLIST_VALID(ipml)); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.allow_update; + break; + + case dns_c_zone_slave: + p = &zone->u.szone.allow_update; + break; + + case dns_c_zone_stub: + p = &zone->u.tzone.allow_update; + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have an allow_update field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have an " + "allow_update field"); + return (ISC_R_FAILURE); + } + + existed = (*p != NULL ? ISC_TRUE : ISC_FALSE); + + res = set_ipmatch_list_field(zone->mem, p, + ipml, deepcopy); + if (res == ISC_R_SUCCESS && existed) { + res = ISC_R_EXISTS; + } + + return (res); +} + + +isc_result_t +dns_c_zone_setallowquery(dns_c_zone_t *zone, + dns_c_ipmatchlist_t *ipml, + isc_boolean_t deepcopy) +{ + dns_c_ipmatchlist_t **p = NULL; + isc_boolean_t existed; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(DNS_C_IPMLIST_VALID(ipml)); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.allow_query; + break; + + case dns_c_zone_slave: + p = &zone->u.szone.allow_query; + break; + + case dns_c_zone_stub: + p = &zone->u.tzone.allow_query; + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have an allow_query field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have an " + "allow_query field"); + return (ISC_R_FAILURE); + } + + existed = (*p != NULL ? ISC_TRUE : ISC_FALSE); + + res = set_ipmatch_list_field(zone->mem, p, + ipml, deepcopy); + if (res == ISC_R_SUCCESS && existed) { + res = ISC_R_EXISTS; + } + + return (res); +} + + +isc_result_t +dns_c_zone_setallowtransfer(dns_c_zone_t *zone, + dns_c_ipmatchlist_t *ipml, + isc_boolean_t deepcopy) +{ + dns_c_ipmatchlist_t **p = NULL; + isc_boolean_t existed; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(DNS_C_IPMLIST_VALID(ipml)); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.allow_transfer; + break; + + case dns_c_zone_slave: + p = &zone->u.szone.allow_transfer; + break; + + case dns_c_zone_stub: + p = &zone->u.tzone.allow_transfer; + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have an " + "allow_transfer field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have an " + "allow_transfer field"); + return (ISC_R_FAILURE); + } + + existed = (*p != NULL ? ISC_TRUE : ISC_FALSE); + res = set_ipmatch_list_field(zone->mem, p, + ipml, deepcopy); + + if (res == ISC_R_SUCCESS && existed) { + res = ISC_R_EXISTS; + } + + return (res); +} + + +isc_result_t +dns_c_zone_setdialup(dns_c_zone_t *zone, isc_boolean_t newval) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch (zone->ztype) { + case dns_c_zone_master: + zone->u.mzone.dialup = newval; + existed = DNS_C_CHECKBIT(MZ_DIALUP_BIT, + &zone->u.mzone.setflags); + DNS_C_SETBIT(MZ_DIALUP_BIT, &zone->u.mzone.setflags); + break; + + case dns_c_zone_slave: + zone->u.szone.dialup = newval; + existed = DNS_C_CHECKBIT(SZ_DIALUP_BIT, + &zone->u.szone.setflags); + DNS_C_SETBIT(SZ_DIALUP_BIT, &zone->u.szone.setflags); + break; + + case dns_c_zone_stub: + zone->u.tzone.dialup = newval; + existed = DNS_C_CHECKBIT(TZ_DIALUP_BIT, + &zone->u.tzone.setflags); + DNS_C_SETBIT(TZ_DIALUP_BIT, &zone->u.tzone.setflags); + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a dialup field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a dialup field"); + return (ISC_R_FAILURE); + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_setnotify(dns_c_zone_t *zone, isc_boolean_t newval) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch (zone->ztype) { + case dns_c_zone_master: + zone->u.mzone.notify = newval; + existed = DNS_C_CHECKBIT(MZ_NOTIFY_BIT, + &zone->u.mzone.setflags); + DNS_C_SETBIT(MZ_NOTIFY_BIT, &zone->u.mzone.setflags); + break; + + case dns_c_zone_slave: + zone->u.szone.notify = newval; + existed = DNS_C_CHECKBIT(SZ_NOTIFY_BIT, + &zone->u.szone.setflags); + DNS_C_SETBIT(SZ_NOTIFY_BIT, &zone->u.szone.setflags); + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a notify field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a notify field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a notify field"); + return (ISC_R_FAILURE); + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_setmaintixfrbase(dns_c_zone_t *zone, + isc_boolean_t newval) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch (zone->ztype) { + case dns_c_zone_master: + zone->u.mzone.maint_ixfr_base = newval; + existed = DNS_C_CHECKBIT(MZ_MAINT_IXFR_BASE_BIT, + &zone->u.mzone.setflags); + DNS_C_SETBIT(MZ_MAINT_IXFR_BASE_BIT, &zone->u.mzone.setflags); + break; + + case dns_c_zone_slave: + zone->u.szone.maint_ixfr_base = newval; + existed = DNS_C_CHECKBIT(SZ_MAINT_IXFR_BASE_BIT, + &zone->u.szone.setflags); + DNS_C_SETBIT(SZ_MAINT_IXFR_BASE_BIT, &zone->u.szone.setflags); + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a " + "maintain-xfer-base field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a " + "maintain-xfer-base field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "maintain-xfer-base field"); + return (ISC_R_FAILURE); + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_setalsonotify(dns_c_zone_t *zone, + dns_c_iplist_t *newval, + isc_boolean_t deepcopy) +{ + isc_boolean_t existed; + isc_result_t res; + dns_c_iplist_t **p = NULL; + + REQUIRE(zone != NULL); + REQUIRE(DNS_C_IPLIST_VALID(newval)); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.also_notify ; + break; + + case dns_c_zone_slave: + p = &zone->u.szone.also_notify ; + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a also_notify field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a also_notify field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a also_notify field"); + return (ISC_R_FAILURE); + } + + existed = (*p != NULL ? ISC_TRUE : ISC_FALSE); + res = set_iplist_field(zone->mem, p, newval, deepcopy); + if (res == ISC_R_SUCCESS && existed) { + res = ISC_R_EXISTS; + } + + return (res); +} + + +isc_result_t +dns_c_zone_setixfrbase(dns_c_zone_t *zone, const char *newval) +{ + isc_boolean_t existed ; + char **p = NULL; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(newval != NULL); + REQUIRE(strlen(newval) > 0); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.ixfr_base; + break; + + case dns_c_zone_slave: + p = &zone->u.szone.ixfr_base; + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a ixfr_base field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a ixfr_base field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a file field"); + return (ISC_R_FAILURE); + } + + if (*p != NULL) { + existed = ISC_TRUE; + isc_mem_free(zone->mem, *p); + } else { + existed = ISC_FALSE; + } + + *p = isc_mem_strdup(zone->mem, newval); + if (*p == NULL) { + return (ISC_R_NOMEMORY); + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_setixfrtmp(dns_c_zone_t *zone, const char *newval) +{ + isc_boolean_t existed; + char **p = NULL; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(newval != NULL); + REQUIRE(strlen(newval) > 0); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.ixfr_tmp; + break; + + case dns_c_zone_slave: + p = &zone->u.szone.ixfr_tmp; + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a ixfr_tmp field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a ixfr_tmp field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a file field"); + return (ISC_R_FAILURE); + } + + if (*p != NULL) { + existed = ISC_TRUE; + isc_mem_free(zone->mem, *p); + } else { + existed = ISC_FALSE; + } + + *p = isc_mem_strdup(zone->mem, newval); + if (*p == NULL) { + return (ISC_R_NOMEMORY); + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_addpubkey(dns_c_zone_t *zone, + dns_c_pubkey_t *pubkey, + isc_boolean_t deepcopy) +{ + dns_c_pklist_t **p = NULL; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(DNS_C_PUBKEY_VALID(pubkey)); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.pubkeylist; + break; + + case dns_c_zone_slave: + p = &zone->u.szone.pubkeylist; + break; + + case dns_c_zone_stub: + p = &zone->u.tzone.pubkeylist; + break; + + case dns_c_zone_hint: +#if 1 + p = &zone->u.hzone.pubkeylist; +#else + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a pubkey field"); +#endif + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a pubkey field"); + return (ISC_R_FAILURE); + } + + if (*p == NULL) { + res = dns_c_pklist_new(zone->mem, p); + if (res != ISC_R_SUCCESS) { + return (res); + } + } + + res = dns_c_pklist_addpubkey(*p, pubkey, deepcopy); + + return (res); +} + + +isc_result_t +dns_c_zone_setmasterport(dns_c_zone_t *zone, in_port_t port) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch(zone->ztype) { + case dns_c_zone_master: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "master_port field"); + return (ISC_R_FAILURE); + + case dns_c_zone_slave: + zone->u.szone.master_port = port; + existed = DNS_C_CHECKBIT(SZ_MASTER_PORT_BIT, + &zone->u.szone.setflags); + DNS_C_SETBIT(SZ_MASTER_PORT_BIT, &zone->u.szone.setflags); + break; + + case dns_c_zone_stub: + zone->u.tzone.master_port = port; + existed = DNS_C_CHECKBIT(TZ_MASTER_PORT_BIT, + &zone->u.tzone.setflags); + DNS_C_SETBIT(TZ_MASTER_PORT_BIT, &zone->u.tzone.setflags); + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a master_port field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "master_port field"); + return (ISC_R_FAILURE); + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_setmasterips(dns_c_zone_t *zone, + dns_c_iplist_t *newval, + isc_boolean_t deepcopy) +{ + isc_boolean_t existed; + isc_result_t res = ISC_R_SUCCESS; + dns_c_iplist_t **p; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(DNS_C_IPLIST_VALID(newval)); + + switch (zone->ztype) { + case dns_c_zone_master: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Master zones do not have a master_ips field"); + return (ISC_R_FAILURE); + + case dns_c_zone_slave: + case dns_c_zone_stub: + if (zone->ztype == dns_c_zone_slave) { + p = &zone->u.szone.master_ips ; + } else { + p = &zone->u.tzone.master_ips ; + } + + existed = (*p != NULL ? ISC_TRUE : ISC_FALSE); + res = set_iplist_field(zone->mem, p, + newval, deepcopy); + if (res == ISC_R_SUCCESS && existed) { + res = ISC_R_EXISTS; + } + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a master_ips field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a master_ips field"); + return (ISC_R_FAILURE); + } + + return (res); +} + + +isc_result_t +dns_c_zone_settransfersource(dns_c_zone_t *zone, + isc_sockaddr_t newval) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch (zone->ztype) { + case dns_c_zone_master: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Master zones do not have a " + "transfer_source field"); + return (ISC_R_FAILURE); + + case dns_c_zone_slave: + zone->u.szone.transfer_source = newval ; + existed = DNS_C_CHECKBIT(SZ_TRANSFER_SOURCE_BIT, + &zone->u.szone.setflags); + DNS_C_SETBIT(SZ_TRANSFER_SOURCE_BIT, &zone->u.szone.setflags); + break; + + case dns_c_zone_stub: + zone->u.tzone.transfer_source = newval ; + existed = DNS_C_CHECKBIT(TZ_TRANSFER_SOURCE_BIT, + &zone->u.tzone.setflags); + DNS_C_SETBIT(TZ_TRANSFER_SOURCE_BIT, &zone->u.tzone.setflags); + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a master_ips field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a master_ips field"); + return (ISC_R_FAILURE); + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_setmaxtranstimein(dns_c_zone_t *zone, + isc_int32_t newval) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch (zone->ztype) { + case dns_c_zone_master: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Master zones do not have a " + "max_trans_time_in field"); + return (ISC_R_FAILURE); + + case dns_c_zone_slave: + zone->u.szone.max_trans_time_in = newval ; + existed = DNS_C_CHECKBIT(SZ_MAX_TRANS_TIME_IN_BIT, + &zone->u.szone.setflags); + DNS_C_SETBIT(SZ_MAX_TRANS_TIME_IN_BIT, + &zone->u.szone.setflags); + break; + + case dns_c_zone_stub: + zone->u.tzone.max_trans_time_in = newval ; + existed = DNS_C_CHECKBIT(TZ_MAX_TRANS_TIME_IN_BIT, + &zone->u.tzone.setflags); + DNS_C_SETBIT(TZ_MAX_TRANS_TIME_IN_BIT, + &zone->u.tzone.setflags); + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a " + "max_trans_time_in field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "max_trans_time_in field"); + return (ISC_R_FAILURE); + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_setmaxtranstimeout(dns_c_zone_t *zone, + isc_int32_t newval) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch (zone->ztype) { + case dns_c_zone_master: + zone->u.mzone.max_trans_time_out = newval ; + existed = DNS_C_CHECKBIT(MZ_MAX_TRANS_TIME_OUT_BIT, + &zone->u.mzone.setflags); + DNS_C_SETBIT(MZ_MAX_TRANS_TIME_OUT_BIT, + &zone->u.mzone.setflags); + break; + + case dns_c_zone_slave: + zone->u.szone.max_trans_time_out = newval ; + existed = DNS_C_CHECKBIT(SZ_MAX_TRANS_TIME_OUT_BIT, + &zone->u.szone.setflags); + DNS_C_SETBIT(SZ_MAX_TRANS_TIME_OUT_BIT, + &zone->u.szone.setflags); + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a " + "max_trans_time_out field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a " + "max_trans_time_out field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "max_trans_time_out field"); + return (ISC_R_FAILURE); + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_setmaxtransidlein(dns_c_zone_t *zone, + isc_int32_t newval) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch (zone->ztype) { + case dns_c_zone_master: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Master zones do not have a " + "max_trans_idle_in field"); + return (ISC_R_FAILURE); + + case dns_c_zone_slave: + zone->u.szone.max_trans_idle_in = newval ; + existed = DNS_C_CHECKBIT(SZ_MAX_TRANS_IDLE_IN_BIT, + &zone->u.szone.setflags); + DNS_C_SETBIT(SZ_MAX_TRANS_IDLE_IN_BIT, + &zone->u.szone.setflags); + break; + + case dns_c_zone_stub: + zone->u.tzone.max_trans_idle_in = newval ; + existed = DNS_C_CHECKBIT(TZ_MAX_TRANS_IDLE_IN_BIT, + &zone->u.tzone.setflags); + DNS_C_SETBIT(TZ_MAX_TRANS_IDLE_IN_BIT, + &zone->u.tzone.setflags); + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a " + "max_trans_idle_in field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "max_trans_idle_in field"); + return (ISC_R_FAILURE); + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_setmaxtransidleout(dns_c_zone_t *zone, + isc_int32_t newval) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch (zone->ztype) { + case dns_c_zone_master: + zone->u.mzone.max_trans_idle_out = newval ; + existed = DNS_C_CHECKBIT(MZ_MAX_TRANS_IDLE_OUT_BIT, + &zone->u.mzone.setflags); + DNS_C_SETBIT(MZ_MAX_TRANS_IDLE_OUT_BIT, + &zone->u.mzone.setflags); + break; + + case dns_c_zone_slave: + zone->u.szone.max_trans_idle_out = newval ; + existed = DNS_C_CHECKBIT(SZ_MAX_TRANS_IDLE_OUT_BIT, + &zone->u.szone.setflags); + DNS_C_SETBIT(SZ_MAX_TRANS_IDLE_OUT_BIT, + &zone->u.szone.setflags); + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a " + "max_trans_idle_out field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a " + "max_trans_idle_out field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "max_trans_idle_out field"); + return (ISC_R_FAILURE); + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_setmaxixfrlog(dns_c_zone_t *zone, + isc_int32_t newval) +{ + dns_c_setbits_t *bits = NULL; + isc_int32_t *p = NULL; + int bit = 0; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.max_ixfr_log; + bits = &zone->u.mzone.setflags; + bit = MZ_MAX_IXFR_LOG_BIT; + break; + + case dns_c_zone_slave: + p = &zone->u.szone.max_ixfr_log; + bits = &zone->u.mzone.setflags; + bit = SZ_MAX_IXFR_LOG_BIT; + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a max-ixfr-log field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a max-ixfr-log field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "max-ixfr-log field"); + return (ISC_R_FAILURE); + } + + if (DNS_C_CHECKBIT(bit, bits)) { + res = ISC_R_EXISTS; + } else { + res = ISC_R_SUCCESS; + } + + *p = newval; + DNS_C_SETBIT(bit, bits); + + return (res); +} + + +isc_result_t +dns_c_zone_setforward(dns_c_zone_t *zone, dns_c_forw_t newval) +{ + isc_boolean_t existed = ISC_FALSE; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + + switch (zone->ztype) { + case dns_c_zone_master: + zone->u.mzone.forward = newval; + existed = DNS_C_CHECKBIT(MZ_FORWARD_BIT, + &zone->u.mzone.setflags); + DNS_C_SETBIT(MZ_FORWARD_BIT, &zone->u.mzone.setflags); + break; + + case dns_c_zone_slave: + zone->u.szone.forward = newval; + existed = DNS_C_CHECKBIT(SZ_FORWARD_BIT, + &zone->u.szone.setflags); + DNS_C_SETBIT(SZ_FORWARD_BIT, &zone->u.szone.setflags); + break; + + case dns_c_zone_stub: + zone->u.tzone.forward = newval; + existed = DNS_C_CHECKBIT(TZ_FORWARD_BIT, + &zone->u.tzone.setflags); + DNS_C_SETBIT(TZ_FORWARD_BIT, &zone->u.tzone.setflags); + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a forward field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + zone->u.fzone.forward = newval; + existed = DNS_C_CHECKBIT(FZ_FORWARD_BIT, + &zone->u.fzone.setflags); + DNS_C_SETBIT(FZ_FORWARD_BIT, &zone->u.fzone.setflags); + break; + } + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_setforwarders(dns_c_zone_t *zone, + dns_c_iplist_t *ipl, + isc_boolean_t deepcopy) +{ + isc_boolean_t existed = ISC_FALSE; + isc_result_t res; + dns_c_iplist_t **p = NULL; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(DNS_C_IPLIST_VALID(ipl)); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.forwarders; + existed = (*p == NULL ? ISC_FALSE : ISC_TRUE); + break; + + case dns_c_zone_slave: + p = &zone->u.szone.forwarders; + existed = (*p == NULL ? ISC_FALSE : ISC_TRUE); + break; + + case dns_c_zone_stub: + p = &zone->u.tzone.forwarders; + existed = (*p == NULL ? ISC_FALSE : ISC_TRUE); + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a forwarders field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + p = &zone->u.fzone.forwarders; + existed = (*p == NULL ? ISC_FALSE : ISC_TRUE); + break; + } + + res = set_iplist_field(zone->mem, p, ipl, deepcopy); + if (res == ISC_R_SUCCESS && existed) { + res = ISC_R_EXISTS; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getname(dns_c_zone_t *zone, const char **retval) +{ + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + *retval = zone->name; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_getinternalname(dns_c_zone_t *zone, + const char **retval) +{ + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + *retval = zone->internalname; + + return (ISC_R_SUCCESS); +} + + +isc_result_t +dns_c_zone_getfile(dns_c_zone_t *zone, const char **retval) +{ + const char *p = NULL; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + p = zone->u.mzone.file; + break; + + case dns_c_zone_slave: + p = zone->u.szone.file; + break; + + case dns_c_zone_stub: + p = zone->u.tzone.file; + break; + + case dns_c_zone_hint: + p = zone->u.hzone.file; + break; + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a file field"); + return (ISC_R_FAILURE); + } + + if (p != NULL) { + *retval = p; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getchecknames(dns_c_zone_t *zone, + dns_severity_t *retval) +{ + dns_severity_t *p = NULL; + dns_c_setbits_t *bits = NULL; + int bit = 0; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + p = &zone->u.mzone.check_names; + bits = &zone->u.mzone.setflags; + bit = MZ_CHECK_NAME_BIT; + break; + + case dns_c_zone_slave: + p = &zone->u.szone.check_names; + bits = &zone->u.szone.setflags; + bit = SZ_CHECK_NAME_BIT; + break; + + case dns_c_zone_stub: + p = &zone->u.tzone.check_names; + bits = &zone->u.tzone.setflags; + bit = TZ_CHECK_NAME_BIT; + break; + + case dns_c_zone_hint: + p = &zone->u.hzone.check_names; + bits = &zone->u.hzone.setflags; + bit = HZ_CHECK_NAME_BIT; + break; + + case dns_c_zone_forward: + p = &zone->u.fzone.check_names; + bits = &zone->u.fzone.setflags; + bit = FZ_CHECK_NAME_BIT; + break; + } + + if (DNS_C_CHECKBIT(bit, bits)) { + *retval = *p; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getallowupd(dns_c_zone_t *zone, + dns_c_ipmatchlist_t **retval) +{ + dns_c_ipmatchlist_t *p = NULL; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + p = zone->u.mzone.allow_update; + break; + + case dns_c_zone_slave: + p = zone->u.szone.allow_update; + break; + + case dns_c_zone_stub: + p = zone->u.tzone.allow_update; + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have an allow_update field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have an " + "allow_update field"); + return (ISC_R_FAILURE); + } + + if (p != NULL) { + dns_c_ipmatchlist_attach(p, retval); + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getallowquery(dns_c_zone_t *zone, + dns_c_ipmatchlist_t **retval) +{ + dns_c_ipmatchlist_t *p = NULL; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + p = zone->u.mzone.allow_query; + break; + + case dns_c_zone_slave: + p = zone->u.szone.allow_query; + break; + + case dns_c_zone_stub: + p = zone->u.tzone.allow_query; + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have an allow_query field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have an " + "allow_query field"); + return (ISC_R_FAILURE); + } + + if (p != NULL) { + dns_c_ipmatchlist_attach(p, retval); + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getallowtransfer(dns_c_zone_t *zone, + dns_c_ipmatchlist_t **retval) +{ + dns_c_ipmatchlist_t *p = NULL; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + p = zone->u.mzone.allow_transfer; + break; + + case dns_c_zone_slave: + p = zone->u.szone.allow_transfer; + break; + + case dns_c_zone_stub: + p = zone->u.tzone.allow_transfer; + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have an " + "allow_transfer field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have an " + "allow_transfer field"); + return (ISC_R_FAILURE); + } + + if (p != NULL) { + dns_c_ipmatchlist_attach(p, retval); + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getdialup(dns_c_zone_t *zone, + isc_boolean_t *retval) +{ + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + if (DNS_C_CHECKBIT(MZ_DIALUP_BIT, &zone->u.mzone.setflags)) { + *retval = zone->u.mzone.dialup; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_slave: + if (DNS_C_CHECKBIT(SZ_DIALUP_BIT, &zone->u.szone.setflags)) { + *retval = zone->u.szone.dialup; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_stub: + if (DNS_C_CHECKBIT(TZ_DIALUP_BIT, &zone->u.tzone.setflags)) { + *retval = zone->u.tzone.dialup; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a dialup field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a dialup field"); + return (ISC_R_FAILURE); + } + + return (res); +} + + +isc_result_t +dns_c_zone_getnotify(dns_c_zone_t *zone, + isc_boolean_t *retval) +{ + isc_result_t res; + dns_c_setbits_t *bits = NULL; + isc_boolean_t val = ISC_FALSE; + int bit = 0; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + val = zone->u.mzone.notify; + bit = MZ_DIALUP_BIT; + bits = &zone->u.mzone.setflags; + break; + + case dns_c_zone_slave: + val = zone->u.szone.notify; + bit = SZ_DIALUP_BIT; + bits = &zone->u.szone.setflags; + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a notify field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a notify field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a notify field"); + return (ISC_R_FAILURE); + } + + if (DNS_C_CHECKBIT(bit,bits)) { + *retval = val; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getmaintixfrbase(dns_c_zone_t *zone, + isc_boolean_t *retval) +{ + isc_result_t res; + dns_c_setbits_t *bits = NULL; + isc_boolean_t val = ISC_FALSE; + int bit = 0; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + val = zone->u.mzone.maint_ixfr_base; + bit = MZ_MAINT_IXFR_BASE_BIT; + bits = &zone->u.mzone.setflags; + break; + + case dns_c_zone_slave: + val = zone->u.szone.maint_ixfr_base; + bit = SZ_MAINT_IXFR_BASE_BIT; + bits = &zone->u.szone.setflags; + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a notify field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a notify field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a notify field"); + return (ISC_R_FAILURE); + } + + if (DNS_C_CHECKBIT(bit,bits)) { + *retval = val; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getalsonotify(dns_c_zone_t *zone, + dns_c_iplist_t **retval) +{ + dns_c_iplist_t *p = NULL; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + p = zone->u.mzone.also_notify ; + break; + + case dns_c_zone_slave: + p = zone->u.szone.also_notify ; + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a also_notify field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a also_notify field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a also_notify field"); + return (ISC_R_FAILURE); + } + + if (p != NULL) { + *retval = p; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getixfrbase(dns_c_zone_t *zone, + const char **retval) +{ + char *p = NULL; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + p = zone->u.mzone.ixfr_base; + break; + + case dns_c_zone_slave: + p = zone->u.szone.ixfr_base; + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a ixfr_base field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a ixfr_base field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a file field"); + return (ISC_R_FAILURE); + } + + if (p != NULL) { + *retval = p; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getixfrtmp(dns_c_zone_t *zone, const char **retval) +{ + char *p = NULL; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + p = zone->u.mzone.ixfr_tmp; + break; + + case dns_c_zone_slave: + p = zone->u.szone.ixfr_tmp; + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a ixfr_tmp field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a ixfr_tmp field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a file field"); + return (ISC_R_FAILURE); + } + + if (p != NULL) { + *retval = p; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getpubkeylist(dns_c_zone_t *zone, + dns_c_pklist_t **retval) +{ + dns_c_pklist_t *p = NULL; + isc_result_t res; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + p = zone->u.mzone.pubkeylist; + break; + + case dns_c_zone_slave: + p = zone->u.szone.pubkeylist; + break; + + case dns_c_zone_stub: + p = zone->u.tzone.pubkeylist; + break; + + case dns_c_zone_hint: +#if 1 + p = zone->u.hzone.pubkeylist; +#else + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a pubkey field"); +#endif + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a pubkey field"); + return (ISC_R_FAILURE); + } + + if (p != NULL) { + *retval = p; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getmasterport(dns_c_zone_t *zone, + in_port_t *retval) +{ + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch(zone->ztype) { + case dns_c_zone_master: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "master_port field"); + return (ISC_R_FAILURE); + + case dns_c_zone_slave: + if (DNS_C_CHECKBIT(SZ_MASTER_PORT_BIT, + &zone->u.szone.setflags)) { + *retval = zone->u.szone.master_port; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_stub: + if (DNS_C_CHECKBIT(TZ_MASTER_PORT_BIT, + &zone->u.tzone.setflags)) { + *retval = zone->u.tzone.master_port; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a master_port field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "master_port field"); + return (ISC_R_FAILURE); + } + + return (res); +} + + +isc_result_t +dns_c_zone_getmasterips(dns_c_zone_t *zone, + dns_c_iplist_t **retval) +{ + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Master zones do not have a master_ips field"); + return (ISC_R_FAILURE); + + case dns_c_zone_slave: + if (zone->u.szone.master_ips != NULL) { + *retval = zone->u.szone.master_ips; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_stub: + if (zone->u.tzone.master_ips != NULL) { + *retval = zone->u.tzone.master_ips; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a master_ips field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a master_ips field"); + return (ISC_R_FAILURE); + } + + return (res); +} + + +isc_result_t +dns_c_zone_gettransfersource(dns_c_zone_t *zone, + isc_sockaddr_t *retval) +{ + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Master zones do not have a " + "transfer_source field"); + return (ISC_R_FAILURE); + + case dns_c_zone_slave: + if (DNS_C_CHECKBIT(SZ_TRANSFER_SOURCE_BIT, + &zone->u.szone.setflags)) { + *retval = zone->u.szone.transfer_source ; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + break; + + case dns_c_zone_stub: + if (DNS_C_CHECKBIT(TZ_TRANSFER_SOURCE_BIT, + &zone->u.tzone.setflags)) { + *retval = zone->u.tzone.transfer_source ; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a master_ips field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a master_ips field"); + return (ISC_R_FAILURE); + } + + return (res); +} + + +isc_result_t +dns_c_zone_getmaxtranstimein(dns_c_zone_t *zone, + isc_int32_t *retval) +{ + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Master zones do not have a " + "max_trans_time_in field"); + return (ISC_R_FAILURE); + + case dns_c_zone_slave: + if (DNS_C_CHECKBIT(SZ_MAX_TRANS_TIME_IN_BIT, + &zone->u.szone.setflags)) { + *retval = zone->u.szone.max_trans_time_in; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_stub: + if (DNS_C_CHECKBIT(TZ_MAX_TRANS_TIME_IN_BIT, + &zone->u.tzone.setflags)) { + *retval = zone->u.tzone.max_trans_time_in; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a " + "max_trans_time_in field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "max_trans_time_in field"); + return (ISC_R_FAILURE); + } + + return (res); +} + + +isc_result_t +dns_c_zone_getmaxtranstimeout(dns_c_zone_t *zone, + isc_int32_t *retval) +{ + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + if (DNS_C_CHECKBIT(SZ_MAX_TRANS_TIME_OUT_BIT, + &zone->u.mzone.setflags)) { + *retval = zone->u.mzone.max_trans_time_out; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_slave: + if (DNS_C_CHECKBIT(SZ_MAX_TRANS_TIME_OUT_BIT, + &zone->u.szone.setflags)) { + *retval = zone->u.szone.max_trans_time_out; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a " + "max_trans_time_out field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a " + "max_trans_time_out field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "max_trans_time_out field"); + return (ISC_R_FAILURE); + } + + return (res); +} + + + +isc_result_t +dns_c_zone_getmaxtransidlein(dns_c_zone_t *zone, + isc_int32_t *retval) +{ + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Master zones do not have a " + "max_trans_idle_in field"); + return (ISC_R_FAILURE); + + case dns_c_zone_slave: + if (DNS_C_CHECKBIT(SZ_MAX_TRANS_IDLE_IN_BIT, + &zone->u.szone.setflags)) { + *retval = zone->u.szone.max_trans_idle_in; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_stub: + if (DNS_C_CHECKBIT(TZ_MAX_TRANS_IDLE_IN_BIT, + &zone->u.tzone.setflags)) { + *retval = zone->u.tzone.max_trans_idle_in; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a " + "max_trans_idle_in field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "max_trans_idle_in field"); + return (ISC_R_FAILURE); + } + + return (res); +} + + +isc_result_t +dns_c_zone_getmaxtransidleout(dns_c_zone_t *zone, + isc_int32_t *retval) +{ + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + if (DNS_C_CHECKBIT(SZ_MAX_TRANS_IDLE_OUT_BIT, + &zone->u.mzone.setflags)) { + *retval = zone->u.mzone.max_trans_idle_out; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + + case dns_c_zone_slave: + if (DNS_C_CHECKBIT(SZ_MAX_TRANS_IDLE_OUT_BIT, + &zone->u.szone.setflags)) { + *retval = zone->u.szone.max_trans_idle_out; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a " + "max_trans_idle_out field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a " + "max_trans_idle_out field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "max_trans_idle_out field"); + return (ISC_R_FAILURE); + } + + return (res); +} + + + +isc_result_t +dns_c_zone_getmaxixfrlog(dns_c_zone_t *zone, + isc_int32_t *retval) +{ + isc_result_t res; + dns_c_setbits_t *bits = NULL; + int bit = 0; + isc_int32_t *ptr = NULL; + + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + bits = &zone->u.mzone.setflags; + bit = MZ_MAX_IXFR_LOG_BIT; + ptr = &zone->u.mzone.max_ixfr_log; + break; + + case dns_c_zone_slave: + bits = &zone->u.szone.setflags; + bit = SZ_MAX_IXFR_LOG_BIT; + ptr = &zone->u.szone.max_ixfr_log; + break; + + case dns_c_zone_stub: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Stub zones do not have a max_ixfr_log field"); + return (ISC_R_FAILURE); + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a max_ixfr_log field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Forward zones do not have a " + "max_ixfr_log field"); + return (ISC_R_FAILURE); + } + + if (DNS_C_CHECKBIT(bit, bits)) { + *retval = *ptr; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getforward(dns_c_zone_t *zone, + dns_c_forw_t *retval) +{ + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + if (DNS_C_CHECKBIT(MZ_FORWARD_BIT, &zone->u.mzone.setflags)) { + *retval = zone->u.mzone.forward; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_slave: + if (DNS_C_CHECKBIT(SZ_FORWARD_BIT, &zone->u.szone.setflags)) { + *retval = zone->u.szone.forward; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_stub: + if (DNS_C_CHECKBIT(TZ_FORWARD_BIT, &zone->u.tzone.setflags)) { + *retval = zone->u.tzone.forward; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a forward field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + if (DNS_C_CHECKBIT(FZ_FORWARD_BIT, &zone->u.fzone.setflags)) { + *retval = zone->u.fzone.forward; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + } + + return (res); +} + + +isc_result_t +dns_c_zone_getforwarders(dns_c_zone_t *zone, + dns_c_iplist_t **retval) +{ + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(DNS_C_ZONE_VALID(zone)); + REQUIRE(retval != NULL); + + switch (zone->ztype) { + case dns_c_zone_master: + if (zone->u.mzone.forwarders != NULL && + zone->u.mzone.forwarders->nextidx > 0) { + *retval = zone->u.mzone.forwarders; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_slave: + if (zone->u.szone.forwarders != NULL && + zone->u.szone.forwarders->nextidx > 0) { + *retval = zone->u.szone.forwarders; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_stub: + if (zone->u.tzone.forwarders != NULL && + zone->u.tzone.forwarders->nextidx > 0) { + *retval = zone->u.tzone.forwarders; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + + case dns_c_zone_hint: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, + DNS_LOGMODULE_CONFIG, ISC_LOG_CRITICAL, + "Hint zones do not have a forwarders field"); + return (ISC_R_FAILURE); + + case dns_c_zone_forward: + if (zone->u.fzone.forwarders != NULL && + zone->u.fzone.forwarders->nextidx > 0) { + *retval = zone->u.fzone.forwarders; + res = ISC_R_SUCCESS; + } else { + res = ISC_R_NOTFOUND; + } + break; + } + + return (res); +} + + +/* + * Zone privates + */ + +static void +master_zone_print(FILE *fp, int indent, + dns_c_masterzone_t *mzone) +{ + REQUIRE(mzone != NULL); + + if (mzone->file != NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, "file \"%s\";\n", mzone->file); + } + + if (DNS_C_CHECKBIT(MZ_CHECK_NAME_BIT, &mzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "check-names %s;\n", + dns_c_nameseverity2string(mzone->check_names, + ISC_TRUE)); + } + + if (mzone->allow_update != NULL && + !ISC_LIST_EMPTY(mzone->allow_update->elements)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "allow-update "); + dns_c_ipmatchlist_print(fp, indent + 1, + mzone->allow_update); + fprintf(fp, ";\n"); + } + + if (mzone->allow_query != NULL && + !ISC_LIST_EMPTY(mzone->allow_query->elements)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "allow-query "); + dns_c_ipmatchlist_print(fp, indent + 1, + mzone->allow_query); + fprintf(fp, ";\n"); + } + + if (mzone->allow_transfer != NULL && + !ISC_LIST_EMPTY(mzone->allow_transfer->elements)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "allow-transfer "); + dns_c_ipmatchlist_print(fp, indent + 1, + mzone->allow_transfer); + fprintf(fp, ";\n"); + } + + if (DNS_C_CHECKBIT(MZ_DIALUP_BIT, &mzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "dialup %s;\n", + (mzone->dialup ? "true" : "false")); + } + + if (DNS_C_CHECKBIT(MZ_MAINT_IXFR_BASE_BIT, &mzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "maintain-ixfr-base %s;\n", + (mzone->maint_ixfr_base ? "true" : "false")); + } + + if (DNS_C_CHECKBIT(MZ_NOTIFY_BIT, &mzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "notify %s;\n", + (mzone->notify ? "true" : "false")); + } + + if (mzone->also_notify != NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, "also-notify "); + dns_c_iplist_print(fp, indent + 1, mzone->also_notify); + fprintf(fp, ";\n"); + } + + if (mzone->ixfr_base != NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, "ixfr-base \"%s\";\n", mzone->ixfr_base); + } + + if (mzone->ixfr_tmp != NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, "ixfr-tmp-file \"%s\";\n", mzone->ixfr_tmp); + } + + if (DNS_C_CHECKBIT(MZ_MAX_TRANS_IDLE_OUT_BIT, &mzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "max-transfer-idle-out %d;\n", + mzone->max_trans_idle_out / 60); + } + + if (DNS_C_CHECKBIT(MZ_MAX_TRANS_TIME_OUT_BIT, &mzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "max-transfer-time-out %d;\n", + mzone->max_trans_time_out / 60); + } + + if (mzone->pubkeylist != NULL) { + fprintf(fp, "\n"); + dns_c_pklist_print(fp, indent, mzone->pubkeylist); + } + + if (DNS_C_CHECKBIT(MZ_FORWARD_BIT, &mzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "forward %s;\n", + dns_c_forward2string(mzone->forward, ISC_TRUE)); + } + + if (mzone->forwarders != NULL && mzone->forwarders->nextidx > 0) { + dns_c_printtabs(fp, indent); + fprintf(fp, "forwarders "); + dns_c_iplist_print(fp, indent + 1, + mzone->forwarders); + fprintf(fp, ";\n"); + } +} + + +static void +slave_zone_print(FILE *fp, int indent, + dns_c_slavezone_t *szone) +{ + REQUIRE(szone != NULL); + + if (szone->file != NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, "file \"%s\";\n", szone->file); + } + + if (szone->ixfr_base != NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, "ixfr-base \"%s\";\n", szone->ixfr_base); + } + + if (szone->ixfr_tmp != NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, "ixfr-tmp-file \"%s\";\n", szone->ixfr_tmp); + } + + if (DNS_C_CHECKBIT(SZ_MAINT_IXFR_BASE_BIT, &szone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "maintain-ixfr-base %s;\n", + (szone->maint_ixfr_base ? "true" : "false")); + } + + dns_c_printtabs(fp, indent); + fprintf(fp, "masters "); + if (DNS_C_CHECKBIT(SZ_MASTER_PORT_BIT, &szone->setflags)) { + if (szone->master_port != 0) { + fprintf(fp, "port %d ", szone->master_port); + } + } + if (szone->master_ips == NULL || + szone->master_ips->nextidx == 0) { + fprintf(fp, "{ /* none defined */ }"); + } else { + dns_c_iplist_print(fp, indent + 1, szone->master_ips); + } + fprintf(fp, ";\n"); + + if (DNS_C_CHECKBIT(SZ_FORWARD_BIT, &szone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "forward %s;\n", + dns_c_forward2string(szone->forward, ISC_TRUE)); + } + + if (szone->forwarders != NULL && szone->forwarders->nextidx > 0) { + dns_c_printtabs(fp, indent); + fprintf(fp, "forwarders "); + dns_c_iplist_print(fp, indent + 1, + szone->forwarders); + fprintf(fp, ";\n"); + } + + if (DNS_C_CHECKBIT(SZ_CHECK_NAME_BIT, &szone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "check-names %s;\n", + dns_c_nameseverity2string(szone->check_names, + ISC_TRUE)); + } + + if (szone->allow_update != NULL && + !ISC_LIST_EMPTY(szone->allow_update->elements)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "allow-update "); + dns_c_ipmatchlist_print(fp, indent + 1, + szone->allow_update); + fprintf(fp, ";\n"); + } + + if (szone->allow_query != NULL && + !ISC_LIST_EMPTY(szone->allow_query->elements)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "allow-query "); + dns_c_ipmatchlist_print(fp, indent + 1, + szone->allow_query); + fprintf(fp, ";\n"); + } + + if (szone->allow_transfer != NULL && + !ISC_LIST_EMPTY(szone->allow_transfer->elements)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "allow-transfer "); + dns_c_ipmatchlist_print(fp, indent + 1, + szone->allow_transfer); + fprintf(fp, ";\n"); + } + + if (DNS_C_CHECKBIT(SZ_TRANSFER_SOURCE_BIT, &szone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "transfer-source "); + dns_c_print_ipaddr(fp, &szone->transfer_source); + fprintf(fp, " ;\n"); + } + + if (DNS_C_CHECKBIT(SZ_MAX_TRANS_TIME_IN_BIT, &szone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "max-transfer-time-in %d;\n", + szone->max_trans_time_in / 60); + } + + if (DNS_C_CHECKBIT(SZ_MAX_TRANS_TIME_OUT_BIT, &szone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "max-transfer-time-out %d;\n", + szone->max_trans_time_out / 60); + } + + if (DNS_C_CHECKBIT(SZ_MAX_TRANS_IDLE_IN_BIT, &szone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "max-transfer-idle-in %d;\n", + szone->max_trans_idle_in / 60); + } + + if (DNS_C_CHECKBIT(SZ_MAX_TRANS_IDLE_OUT_BIT, &szone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "max-transfer-idle-out %d;\n", + szone->max_trans_idle_out / 60); + } + + if (DNS_C_CHECKBIT(SZ_DIALUP_BIT, &szone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "dialup %s;\n", + (szone->dialup ? "true" : "false")); + } + + if (DNS_C_CHECKBIT(SZ_NOTIFY_BIT, &szone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "notify %s;\n", + (szone->notify ? "true" : "false")); + } + + if (szone->also_notify != NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, "also-notify "); + dns_c_iplist_print(fp, indent + 1, szone->also_notify); + fprintf(fp, ";\n"); + } + + if (szone->pubkeylist != NULL) { + fprintf(fp, "\n"); + dns_c_pklist_print(fp, indent, szone->pubkeylist); + } +} + + +static void +stub_zone_print(FILE *fp, int indent, dns_c_stubzone_t *tzone) +{ + REQUIRE(tzone != NULL); + + if (tzone->file != NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, "file \"%s\";\n", tzone->file); + } + + + dns_c_printtabs(fp, indent); + fprintf(fp, "masters "); + if (DNS_C_CHECKBIT(TZ_MASTER_PORT_BIT, &tzone->setflags)) { + if (tzone->master_port != 0) { + fprintf(fp, "port %d ", tzone->master_port); + } + } + if (tzone->master_ips == NULL || + tzone->master_ips->nextidx == 0) { + fprintf(fp, "{ /* none defined */ }"); + } else { + dns_c_iplist_print(fp, indent + 1, tzone->master_ips); + } + fprintf(fp, ";\n"); + + if (DNS_C_CHECKBIT(TZ_FORWARD_BIT, &tzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "forward %s;\n", + dns_c_forward2string(tzone->forward, ISC_TRUE)); + } + + if (tzone->forwarders != NULL && tzone->forwarders->nextidx > 0) { + dns_c_printtabs(fp, indent); + fprintf(fp, "forwarders "); + dns_c_iplist_print(fp, indent + 1, + tzone->forwarders); + fprintf(fp, ";\n"); + } + + if (DNS_C_CHECKBIT(TZ_CHECK_NAME_BIT, &tzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "check-names %s;\n", + dns_c_nameseverity2string(tzone->check_names, + ISC_TRUE)); + } + + if (tzone->allow_update != NULL && + !ISC_LIST_EMPTY(tzone->allow_update->elements)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "allow-update "); + dns_c_ipmatchlist_print(fp, indent + 1, + tzone->allow_update); + fprintf(fp, ";\n"); + } + + if (tzone->allow_query != NULL && + !ISC_LIST_EMPTY(tzone->allow_query->elements)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "allow-query "); + dns_c_ipmatchlist_print(fp, indent + 1, + tzone->allow_query); + fprintf(fp, ";\n"); + } + + if (tzone->allow_transfer != NULL && + !ISC_LIST_EMPTY(tzone->allow_transfer->elements)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "allow-transfer "); + dns_c_ipmatchlist_print(fp, indent + 1, + tzone->allow_transfer); + fprintf(fp, ";\n"); + } + + if (DNS_C_CHECKBIT(TZ_DIALUP_BIT, &tzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "dialup %s;\n", + (tzone->dialup ? "true" : "false")); + } + + if (DNS_C_CHECKBIT(TZ_TRANSFER_SOURCE_BIT, &tzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "transfer-source "); + dns_c_print_ipaddr(fp, &tzone->transfer_source); + fprintf(fp, ";\n"); + } + + if (DNS_C_CHECKBIT(TZ_MAX_TRANS_TIME_IN_BIT, &tzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "max-transfer-time-in %d;\n", + tzone->max_trans_time_in / 60); + } + + if (DNS_C_CHECKBIT(TZ_MAX_TRANS_IDLE_IN_BIT, &tzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "max-transfer-idle-in %d;\n", + tzone->max_trans_idle_in / 60); + } + + if (tzone->pubkeylist != NULL) { + fprintf(fp, "\n"); + dns_c_pklist_print(fp, indent, tzone->pubkeylist); + } +} + + +static void +hint_zone_print(FILE *fp, int indent, dns_c_hintzone_t *hzone) +{ + REQUIRE(hzone != NULL); + + if (hzone->file != NULL) { + dns_c_printtabs(fp, indent); + fprintf(fp, "file \"%s\";\n", hzone->file); + } + + if (DNS_C_CHECKBIT(HZ_CHECK_NAME_BIT, &hzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "check-names %s;\n", + dns_c_nameseverity2string(hzone->check_names, + ISC_TRUE)); + } + + if (hzone->pubkeylist != NULL) { + fprintf(fp, "\n"); + dns_c_pklist_print(fp, indent, hzone->pubkeylist); + } +} + + +static void +forward_zone_print(FILE *fp, int indent, + dns_c_forwardzone_t *fzone) +{ + REQUIRE(fzone != NULL); + + if (DNS_C_CHECKBIT(FZ_FORWARD_BIT, &fzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "forward %s;\n", + dns_c_forward2string(fzone->forward, ISC_TRUE)); + } + + if (fzone->forwarders != NULL && fzone->forwarders->nextidx > 0) { + dns_c_printtabs(fp, indent); + fprintf(fp, "forwarders "); + dns_c_iplist_print(fp, indent + 1, + fzone->forwarders); + fprintf(fp, ";\n"); + } + + if (DNS_C_CHECKBIT(FZ_CHECK_NAME_BIT, &fzone->setflags)) { + dns_c_printtabs(fp, indent); + fprintf(fp, "check-names %s;\n", + dns_c_nameseverity2string(fzone->check_names, + ISC_TRUE)); + } +} + + +static isc_result_t +master_zone_init(dns_c_masterzone_t *mzone) +{ + REQUIRE(mzone != NULL); + + mzone->file = NULL; + mzone->allow_update = NULL; + mzone->allow_query = NULL; + mzone->allow_transfer = NULL; + mzone->also_notify = NULL; + mzone->ixfr_base = NULL; + mzone->ixfr_tmp = NULL; + mzone->pubkeylist = NULL; + mzone->forwarders = NULL; + + memset(&mzone->setflags, 0x0, sizeof (mzone->setflags)); + + return (ISC_R_SUCCESS); +} + + +static isc_result_t +slave_zone_init(dns_c_slavezone_t *szone) +{ + REQUIRE(szone != NULL); + + szone->file = NULL; + szone->ixfr_base = NULL; + szone->ixfr_tmp = NULL; + szone->master_ips = NULL; + szone->allow_update = NULL; + szone->allow_query = NULL; + szone->allow_transfer = NULL; + szone->also_notify = NULL; + szone->pubkeylist = NULL; + szone->forwarders = NULL; + + memset(&szone->setflags, 0x0, sizeof (szone->setflags)); + + return (ISC_R_SUCCESS); +} + + +static isc_result_t +stub_zone_init(dns_c_stubzone_t *tzone) +{ + REQUIRE(tzone != NULL); + + tzone->file = NULL; + tzone->master_ips = NULL; + tzone->allow_update = NULL; + tzone->allow_query = NULL; + tzone->allow_transfer = NULL; + tzone->pubkeylist = NULL; + tzone->forwarders = NULL; + + memset(&tzone->setflags, 0x0, sizeof (tzone->setflags)); + + return (ISC_R_SUCCESS); +} + + +static isc_result_t +hint_zone_init(dns_c_hintzone_t *hzone) +{ + REQUIRE(hzone != NULL); + + hzone->file = NULL; + hzone->pubkeylist = NULL; + memset(&hzone->setflags, 0x0, sizeof (hzone->setflags)); + + return (ISC_R_SUCCESS); +} + + +static isc_result_t +forward_zone_init(dns_c_forwardzone_t *fzone) +{ + REQUIRE(fzone != NULL); + + fzone->forwarders = NULL; + memset(&fzone->setflags, 0x0, sizeof (fzone->setflags)); + + return (ISC_R_SUCCESS); +} + + +static isc_result_t +zone_delete(dns_c_zone_t **zone) +{ + dns_c_zone_t *z; + isc_result_t res = ISC_R_SUCCESS; + + REQUIRE(zone != NULL); + REQUIRE(DNS_C_ZONE_VALID(*zone)); + + z = *zone; + + isc_mem_free(z->mem, z->name); + isc_mem_free(z->mem, z->internalname); + + switch(z->ztype) { + case dns_c_zone_master: + res = master_zone_clear(z->mem, &z->u.mzone); + break; + + case dns_c_zone_slave: + res = slave_zone_clear(z->mem, &z->u.szone); + break; + + case dns_c_zone_stub: + res = stub_zone_clear(z->mem, &z->u.tzone); + break; + + case dns_c_zone_hint: + res = hint_zone_clear(z->mem, &z->u.hzone); + break; + + case dns_c_zone_forward: + res = forward_zone_clear(z->mem, &z->u.fzone); + break; + } + + z->magic = 0; + z->view = NULL; + isc_mem_put(z->mem, z, sizeof *z); + + return (res); +} + + +static isc_result_t +master_zone_clear(isc_mem_t *mem, dns_c_masterzone_t *mzone) +{ + REQUIRE(mzone != NULL); + + if (mzone == NULL) { + return (ISC_R_SUCCESS); + } + + if (mzone->file != NULL) { + isc_mem_free(mem, mzone->file); + } + + if (mzone->allow_update != NULL) + dns_c_ipmatchlist_detach(&mzone->allow_update); + + if (mzone->allow_query != NULL) + dns_c_ipmatchlist_detach(&mzone->allow_query); + + if (mzone->allow_transfer != NULL) + dns_c_ipmatchlist_detach(&mzone->allow_transfer); + + if (mzone->also_notify != NULL) + dns_c_iplist_detach(&mzone->also_notify); + + if (mzone->ixfr_base != NULL) { + isc_mem_free(mem, mzone->ixfr_base); + } + + if (mzone->ixfr_tmp != NULL) { + isc_mem_free(mem, mzone->ixfr_tmp); + } + + if (mzone->pubkeylist != NULL) + dns_c_pklist_delete(&mzone->pubkeylist); + + if (mzone->forwarders != NULL) + dns_c_iplist_detach(&mzone->forwarders); + + return (ISC_R_SUCCESS); +} + + +static isc_result_t +slave_zone_clear(isc_mem_t *mem, dns_c_slavezone_t *szone) +{ + REQUIRE(szone != NULL); + + if (szone == NULL) { + return (ISC_R_SUCCESS); + } + + if (szone->file != NULL) { + isc_mem_free(mem, szone->file); + } + + if (szone->ixfr_base != NULL) { + isc_mem_free(mem, szone->ixfr_base); + } + + if (szone->ixfr_tmp != NULL) { + isc_mem_free(mem, szone->ixfr_tmp); + } + + if (szone->master_ips != NULL) + dns_c_iplist_detach(&szone->master_ips); + + if (szone->allow_update != NULL) + dns_c_ipmatchlist_detach(&szone->allow_update); + + if (szone->allow_query != NULL) + dns_c_ipmatchlist_detach(&szone->allow_query); + + if (szone->allow_transfer != NULL) + dns_c_ipmatchlist_detach(&szone->allow_transfer); + + if (szone->also_notify != NULL) + dns_c_iplist_detach(&szone->also_notify); + + if (szone->forwarders != NULL) + dns_c_iplist_detach(&szone->forwarders); + + if (szone->pubkeylist != NULL) + dns_c_pklist_delete(&szone->pubkeylist); + + return (ISC_R_SUCCESS); +} + + + +static isc_result_t +stub_zone_clear(isc_mem_t *mem, dns_c_stubzone_t *tzone) +{ + REQUIRE(tzone != NULL); + + if (tzone == NULL) { + return (ISC_R_SUCCESS); + } + + if (tzone->file != NULL) { + isc_mem_free(mem, tzone->file); + } + + if (tzone->master_ips != NULL) + dns_c_iplist_detach(&tzone->master_ips); + + if (tzone->allow_update != NULL) + dns_c_ipmatchlist_detach(&tzone->allow_update); + + if (tzone->allow_query != NULL) + dns_c_ipmatchlist_detach(&tzone->allow_query); + + if (tzone->allow_transfer != NULL) + dns_c_ipmatchlist_detach(&tzone->allow_transfer); + + if (tzone->forwarders != NULL) + dns_c_iplist_detach(&tzone->forwarders); + + if (tzone->pubkeylist != NULL) + dns_c_pklist_delete(&tzone->pubkeylist); + + return (ISC_R_SUCCESS); +} + + +static isc_result_t +forward_zone_clear(isc_mem_t *mem, dns_c_forwardzone_t *fzone) +{ + REQUIRE(fzone != NULL); + + if (fzone == NULL) { + return (ISC_R_SUCCESS); + } + + (void) mem; /* lint happiness */ + + if (fzone->forwarders != NULL) + dns_c_iplist_detach(&fzone->forwarders); + + return (ISC_R_SUCCESS); +} + + +static isc_result_t +hint_zone_clear(isc_mem_t *mem, dns_c_hintzone_t *hzone) +{ + REQUIRE(hzone != NULL); + + if (hzone == NULL) { + return (ISC_R_SUCCESS); + } + + if (hzone->file != NULL) { + isc_mem_free(mem, hzone->file); + } + + if (hzone->pubkeylist != NULL) + dns_c_pklist_delete(&hzone->pubkeylist); + + return (ISC_R_SUCCESS); +} + + +/**************************************************/ + +static isc_result_t +set_ipmatch_list_field(isc_mem_t *mem, + dns_c_ipmatchlist_t **dest, dns_c_ipmatchlist_t *src, + isc_boolean_t deepcopy) +{ + isc_result_t res; + + if (*dest != NULL) { + res = dns_c_ipmatchlist_detach(dest); + if (res != ISC_R_SUCCESS) { + return (res); + } + } + + if (deepcopy) { + res = dns_c_ipmatchlist_copy(mem, dest, src); + } else { + *dest = src; + res = ISC_R_SUCCESS; + } + + return (res); +} + + +static isc_result_t +set_iplist_field(isc_mem_t *mem, + dns_c_iplist_t **dest, dns_c_iplist_t *src, + isc_boolean_t deepcopy) +{ + isc_result_t res; + + if (*dest != NULL) { + res = dns_c_iplist_detach(dest); + if (res != ISC_R_SUCCESS) { + return (res); + } + } + + if (deepcopy) { + res = dns_c_iplist_copy(mem, dest, src); + } else { + *dest = src; + res = ISC_R_SUCCESS; + } + + return (res); +} + |