diff options
author | Internet Software Consortium, Inc <@isc.org> | 2007-09-07 14:08:19 -0600 |
---|---|---|
committer | LaMont Jones <lamont@debian.org> | 2007-09-07 14:08:19 -0600 |
commit | 93744e253a50cdd78097dc5a150f4c035e8cbcc9 (patch) | |
tree | f7470097a04345f967281dd4d658dd065c51d166 /bin/named | |
parent | 6257efc35455318993208bef65a551ac6039f51f (diff) | |
download | bind9-93744e253a50cdd78097dc5a150f4c035e8cbcc9.tar.gz |
9.0.0b3
Diffstat (limited to 'bin/named')
29 files changed, 1942 insertions, 1428 deletions
diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in index 98db3754..ca9d2de9 100644 --- a/bin/named/Makefile.in +++ b/bin/named/Makefile.in @@ -27,12 +27,17 @@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include \ CDEFINES = CWARNINGS = -DEPLIBS = ../../lib/dns/libdns.@A@ \ - ../../lib/omapi/libomapi.@A@ \ - ../../lib/isc/libisc.@A@ +OMAPILIBS = ../../lib/omapi/libomapi.@A@ +DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_OPENSSL_LIBS@ +ISCLIBS = ../../lib/isc/libisc.@A@ -LIBS = ${DEPLIBS} \ - @LIBS@ +OMAPIDEPLIBS = ../../lib/omapi/libomapi.@A@ +DNSDEPLIBS = ../../lib/dns/libdns.@A@ +ISCDEPLIBS = ../../lib/isc/libisc.@A@ + +DEPLIBS = ${OMAPIDEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS} + +LIBS = ${OMAPILIBS} ${DNSLIBS} ${ISCLIBS} @LIBS@ SUBDIRS = unix @@ -51,7 +56,7 @@ SRCS = client.c interfacemgr.c listenlist.c \ @BIND9_MAKE_RULES@ main.@O@: main.c - ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \ + ${LIBTOOL} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ -DNS_SYSCONFDIR=\"${sysconfdir}\" -c ${srcdir}/main.c diff --git a/bin/named/client.c b/bin/named/client.c index 7061ce05..6e4f7164 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -17,17 +17,12 @@ #include <config.h> -#include <string.h> - -#include <isc/assertions.h> -#include <isc/mem.h> -#include <isc/mutex.h> -#include <isc/result.h> +#include <isc/print.h> #include <isc/task.h> +#include <isc/string.h> #include <isc/timer.h> #include <isc/util.h> -#include <dns/acl.h> #include <dns/dispatch.h> #include <dns/events.h> #include <dns/message.h> @@ -37,12 +32,9 @@ #include <dns/view.h> #include <dns/zone.h> -#include <named/client.h> -#include <named/globals.h> #include <named/interfacemgr.h> #include <named/log.h> #include <named/notify.h> -#include <named/query.h> #include <named/server.h> #include <named/update.h> @@ -63,16 +55,19 @@ #define NS_CLIENT_TRACE #ifdef NS_CLIENT_TRACE -#define CTRACE(m) isc_log_write(ns_g_lctx, \ +#define CTRACE(m) ns_client_log(client, \ NS_LOGCATEGORY_CLIENT, \ NS_LOGMODULE_CLIENT, \ ISC_LOG_DEBUG(3), \ - "client %p: %s", client, (m)) + "%s", (m)) #define MTRACE(m) isc_log_write(ns_g_lctx, \ NS_LOGCATEGORY_GENERAL, \ NS_LOGMODULE_CLIENT, \ ISC_LOG_DEBUG(3), \ - "clientmgr %p: %s", manager, (m)) + "clientmgr @%p: %s", manager, (m)) +#else +#define CTRACE(m) ((void)(m)) +#define MTRACE(m) ((void)(m)) #endif #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0) @@ -166,24 +161,6 @@ static void ns_client_endrequest(ns_client_t *client); static void ns_client_checkactive(ns_client_t *client); /* - * Format a human-readable representation of the socket address '*sa' - * into the character array 'array', which is of size 'size'. - * The resulting string is guaranteed to be null-terminated. - */ -static void -sockaddr_format(isc_sockaddr_t *sa, char *array, unsigned int size) -{ - isc_result_t result; - isc_buffer_t buf; - isc_buffer_init(&buf, array, size, ISC_BUFFERTYPE_TEXT); - result = isc_sockaddr_totext(sa, &buf); - if (result != ISC_R_SUCCESS) { - strncpy(array, "<unknown address>", size); - array[size-1] = '\0'; - } -} - -/* * Enter the inactive state. * * Requires: @@ -192,6 +169,7 @@ sockaddr_format(isc_sockaddr_t *sa, char *array, unsigned int size) static void client_deactivate(ns_client_t *client) { REQUIRE(NS_CLIENT_VALID(client)); + if (client->interface) ns_interface_detach(&client->interface); @@ -205,9 +183,7 @@ client_deactivate(ns_client_t *client) { deventp = &client->dispevent; else deventp = NULL; - dns_dispatch_removerequest(client->dispatch, - &client->dispentry, - deventp); + dns_dispatch_removerequest(&client->dispentry, deventp); } if (client->dispatch != NULL) dns_dispatch_detach(&client->dispatch); @@ -279,11 +255,12 @@ static void set_timeout(ns_client_t *client, unsigned int seconds) { isc_result_t result; isc_interval_t interval; + isc_interval_set(&interval, seconds, 0); result = isc_timer_reset(client->timer, isc_timertype_once, NULL, &interval, ISC_FALSE); if (result != ISC_R_SUCCESS) { - isc_log_write(dns_lctx, NS_LOGCATEGORY_CLIENT, + ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_ERROR, "setting timouet: %s", isc_result_totext(result)); @@ -362,7 +339,6 @@ exit_check(ns_client_t *client) { * if any. */ INSIST(client->newstate <= NS_CLIENTSTATE_READY); - CTRACE("closetcp"); if (client->nreads > 0) dns_tcpmsg_cancelread(&client->tcpmsg); if (! client->nreads == 0) { @@ -374,8 +350,10 @@ exit_check(ns_client_t *client) { dns_tcpmsg_invalidate(&client->tcpmsg); client->tcpmsg_valid = ISC_FALSE; } - if (client->tcpsocket != NULL) + if (client->tcpsocket != NULL) { + CTRACE("closetcp"); isc_socket_detach(&client->tcpsocket); + } if (client->tcpquota != NULL) isc_quota_detach(&client->tcpquota); @@ -383,6 +361,8 @@ exit_check(ns_client_t *client) { (void) isc_timer_reset(client->timer, isc_timertype_inactive, NULL, NULL, ISC_TRUE); + client->peeraddr_valid = ISC_FALSE; + client->state = NS_CLIENTSTATE_READY; /* @@ -453,11 +433,13 @@ client_shutdown(isc_task_t *task, isc_event_t *event) { ns_client_t *client; REQUIRE(event != NULL); - REQUIRE(event->type == ISC_TASKEVENT_SHUTDOWN); - client = event->arg; + REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN); + client = event->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); + UNUSED(task); + CTRACE("shutdown"); isc_event_free(&event); @@ -469,7 +451,7 @@ client_shutdown(isc_task_t *task, isc_event_t *event) { } client->newstate = NS_CLIENTSTATE_FREED; - (void) exit_check(client); + (void)exit_check(client); } @@ -479,10 +461,10 @@ ns_client_endrequest(ns_client_t *client) { INSIST(client->nreads == 0); INSIST(client->nsends == 0); INSIST(client->lockview == NULL); - CTRACE("endrequest"); - INSIST(client->state == NS_CLIENTSTATE_WORKING); + CTRACE("endrequest"); + if (client->next != NULL) { (client->next)(client); client->next = NULL; @@ -540,15 +522,16 @@ ns_client_checkactive(ns_client_t *client) { void ns_client_next(ns_client_t *client, isc_result_t result) { int newstate; + REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(client->state == NS_CLIENTSTATE_WORKING); + CTRACE("next"); - if (result != ISC_R_SUCCESS) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, + if (result != ISC_R_SUCCESS) + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "request failed: %s", isc_result_totext(result)); - } /* * An error processing a TCP request may have left @@ -571,14 +554,22 @@ client_senddone(isc_task_t *task, isc_event_t *event) { ns_client_t *client; isc_socketevent_t *sevent = (isc_socketevent_t *) event; + UNUSED(task); + REQUIRE(sevent != NULL); - REQUIRE(sevent->type == ISC_SOCKEVENT_SENDDONE); - client = sevent->arg; + REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE); + client = sevent->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); CTRACE("senddone"); + if (sevent->result != ISC_R_SUCCESS) + ns_client_log(client, NS_LOGCATEGORY_CLIENT, + NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, + "error sending response: %s", + isc_result_totext(sevent->result)); + INSIST(client->nsends > 0); client->nsends--; @@ -618,16 +609,14 @@ ns_client_send(ns_client_t *client) { /* * XXXRTH "tcpbuffer" is a hack to get things working. */ - isc_buffer_init(&tcpbuffer, data, SEND_BUFFER_SIZE, - ISC_BUFFERTYPE_BINARY); - isc_buffer_init(&buffer, data + 2, SEND_BUFFER_SIZE - 2, - ISC_BUFFERTYPE_BINARY); + isc_buffer_init(&tcpbuffer, data, SEND_BUFFER_SIZE); + isc_buffer_init(&buffer, data + 2, SEND_BUFFER_SIZE - 2); } else { if (client->udpsize < SEND_BUFFER_SIZE) bufsize = client->udpsize; else bufsize = SEND_BUFFER_SIZE; - isc_buffer_init(&buffer, data, bufsize, ISC_BUFFERTYPE_BINARY); + isc_buffer_init(&buffer, data, bufsize); } result = dns_message_renderbegin(client->message, &buffer); @@ -674,14 +663,14 @@ ns_client_send(ns_client_t *client) { if (TCP_CLIENT(client)) { socket = client->tcpsocket; address = NULL; - isc_buffer_used(&buffer, &r); + isc_buffer_usedregion(&buffer, &r); isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length); isc_buffer_add(&tcpbuffer, r.length); - isc_buffer_used(&tcpbuffer, &r); + isc_buffer_usedregion(&tcpbuffer, &r); } else { socket = dns_dispatch_getsocket(client->dispatch); address = &client->dispevent->addr; - isc_buffer_used(&buffer, &r); + isc_buffer_usedregion(&buffer, &r); } CTRACE("sendto"); if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0) @@ -778,6 +767,8 @@ client_addopt(ns_client_t *client) { */ rdata->data = NULL; rdata->length = 0; + rdata->rdclass = rdatalist->rdclass; + rdata->type = rdatalist->type; ISC_LIST_INIT(rdatalist->rdata); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); @@ -801,13 +792,14 @@ client_request(isc_task_t *task, isc_event_t *event) { dns_view_t *view; dns_rdataset_t *opt; isc_boolean_t ra; /* Recursion available. */ - char peerbuf[256]; REQUIRE(event != NULL); - client = event->arg; + client = event->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); + UNUSED(task); + INSIST(client->recursionquota == NULL); INSIST(client->state == @@ -818,7 +810,7 @@ client_request(isc_task_t *task, isc_event_t *event) { RWLOCK(&ns_g_server->conflock, isc_rwlocktype_read); dns_zonemgr_lockconf(ns_g_server->zonemgr, isc_rwlocktype_read); - if (event->type == DNS_EVENT_DISPATCH) { + if (event->ev_type == DNS_EVENT_DISPATCH) { INSIST(!TCP_CLIENT(client)); devent = (dns_dispatchevent_t *)event; REQUIRE(client->dispentry != NULL); @@ -826,18 +818,17 @@ client_request(isc_task_t *task, isc_event_t *event) { buffer = &devent->buffer; result = devent->result; client->peeraddr = devent->addr; - if ((devent->attributes & DNS_DISPATCHATTR_PKTINFO) != 0) { + client->peeraddr_valid = ISC_TRUE; + if ((devent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) { client->attributes |= NS_CLIENTATTR_PKTINFO; client->pktinfo = devent->pktinfo; - printf("client: interface %u\n", - client->pktinfo.ipi6_ifindex); } else { client->attributes &= ~NS_CLIENTATTR_PKTINFO; } } else { INSIST(TCP_CLIENT(client)); - REQUIRE(event->type == DNS_EVENT_TCPMSG); - REQUIRE(event->sender == &client->tcpmsg); + REQUIRE(event->ev_type == DNS_EVENT_TCPMSG); + REQUIRE(event->ev_sender == &client->tcpmsg); buffer = &client->tcpmsg.buffer; result = client->tcpmsg.result; INSIST(client->nreads == 1); @@ -847,12 +838,10 @@ client_request(isc_task_t *task, isc_event_t *event) { client->nreads--; } - sockaddr_format(&client->peeraddr, peerbuf, sizeof(peerbuf)); - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT, + ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), - "client %p: %s request from %s", - client, TCP_CLIENT(client) ? "TCP" : "UDP", - peerbuf); + "%s request", + TCP_CLIENT(client) ? "TCP" : "UDP"); if (exit_check(client)) goto cleanup_serverlock; @@ -922,29 +911,44 @@ client_request(isc_task_t *task, isc_event_t *event) { } /* + * Find a view that matches the client's source address. + * * XXXRTH View list management code will be moving to its own module * soon. */ for (view = ISC_LIST_HEAD(ns_g_server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { - /* - * XXXRTH View matching will become more powerful later. - */ if (client->message->rdclass == view->rdclass || client->message->rdclass == dns_rdataclass_any) { - dns_view_attach(view, &client->view); - break; + isc_netaddr_t netaddr; + int match; + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); + if (view->matchclients == NULL || + (dns_acl_match(&netaddr, NULL, view->matchclients, + &ns_g_server->aclenv, + &match, NULL) == ISC_R_SUCCESS && + match > 0)) + { + dns_view_attach(view, &client->view); + break; + } } } if (view == NULL) { - CTRACE("no view"); + ns_client_log(client, NS_LOGCATEGORY_CLIENT, + NS_LOGMODULE_CLIENT, ISC_LOG_ERROR, + "no matching view"); ns_client_error(client, DNS_R_REFUSED); goto cleanup_serverlock; } + ns_client_log(client, NS_LOGCATEGORY_CLIENT, + NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5), + "using view '%s'", view->name); + /* * Lock the view's configuration data for reading. * We must attach a separate view reference for this @@ -972,22 +976,22 @@ client_request(isc_task_t *task, isc_event_t *event) { client->signer = NULL; dns_name_init(&client->signername, NULL); result = dns_message_signer(client->message, &client->signername); - if (result == DNS_R_SUCCESS) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, + if (result == ISC_R_SUCCESS) { + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "request has valid signature"); client->signer = &client->signername; - } else if (result == DNS_R_NOTFOUND) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, + } else if (result == ISC_R_NOTFOUND) { + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "request is not signed"); } else if (result == DNS_R_NOIDENTITY) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "request is signed by a nonauthoritative key"); } else { /* There is a signature, but it is bad. */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_ERROR, "request has invalid signature: %s", isc_result_totext(result)); @@ -999,20 +1003,15 @@ client_request(isc_task_t *task, isc_event_t *event) { * set the RA bit correctly on all kinds of responses, not just * responses to ordinary queries. */ - if (client->view->resolver == NULL) { - ra = ISC_FALSE; - } else { + ra = ISC_FALSE; + if (client->view->resolver != NULL && + client->view->recursion == ISC_TRUE && + /* XXX this will log too much too early */ + ns_client_checkacl(client, "recursion", + client->view->recursionacl, + ISC_TRUE) == ISC_R_SUCCESS) ra = ISC_TRUE; - if (ns_g_server->recursion == ISC_TRUE) { - /* XXX ACL should be view specific. */ - /* XXX this will log too much too early */ - result = ns_client_checkacl(client, "recursion", - ns_g_server->recursionacl, - ISC_TRUE); - if (result != DNS_R_SUCCESS) - ra = ISC_FALSE; - } - } + if (ra == ISC_TRUE) client->attributes |= NS_CLIENTATTR_RA; @@ -1054,13 +1053,15 @@ client_timeout(isc_task_t *task, isc_event_t *event) { ns_client_t *client; REQUIRE(event != NULL); - REQUIRE(event->type == ISC_TIMEREVENT_LIFE || - event->type == ISC_TIMEREVENT_IDLE); - client = event->arg; + REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE || + event->ev_type == ISC_TIMEREVENT_IDLE); + client = event->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); REQUIRE(client->timer != NULL); + UNUSED(task); + CTRACE("timeout"); isc_event_free(&event); @@ -1097,8 +1098,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) return (ISC_R_NOMEMORY); client->task = NULL; - result = isc_task_create(manager->taskmgr, manager->mctx, 0, - &client->task); + result = isc_task_create(manager->taskmgr, 0, &client->task); if (result != ISC_R_SUCCESS) goto cleanup_client; isc_task_setname(client->task, "client", client); @@ -1152,6 +1152,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) client->tcpquota = NULL; client->recursionquota = NULL; client->interface = NULL; + client->peeraddr_valid = ISC_FALSE; ISC_LINK_INIT(client, link); client->list = NULL; @@ -1218,19 +1219,18 @@ client_read(ns_client_t *client) { static void client_newconn(isc_task_t *task, isc_event_t *event) { - ns_client_t *client = event->arg; + ns_client_t *client = event->ev_arg; isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event; isc_result_t result; - char peerbuf[256]; - REQUIRE(event->type == ISC_SOCKEVENT_NEWCONN); + REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN); REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(client->task == task); + UNUSED(task); + INSIST(client->state == NS_CLIENTSTATE_READY); - CTRACE("newconn"); - INSIST(client->naccepts == 1); client->naccepts--; @@ -1249,11 +1249,10 @@ client_newconn(isc_task_t *task, isc_event_t *event) { (void) isc_socket_getpeername(client->tcpsocket, &client->peeraddr); - sockaddr_format(&client->peeraddr, peerbuf, sizeof(peerbuf)); - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT, - NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), - "client %p: TCP connection from %s", - client, peerbuf); + client->peeraddr_valid = ISC_TRUE; + ns_client_log(client, NS_LOGCATEGORY_CLIENT, + NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), + "new TCP connection"); } else { /* * XXXRTH What should we do? We're trying to accept but @@ -1265,9 +1264,9 @@ client_newconn(isc_task_t *task, isc_event_t *event) { * Going idle is probably the right thing if the * I/O was canceled. */ - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT, + ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), - "client %p: accept failed: %s", client, + "accept failed: %s", isc_result_totext(nevent->result)); } @@ -1291,7 +1290,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { if (result == ISC_R_SUCCESS) result = ns_client_replace(client); if (result != ISC_R_SUCCESS) { - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT, + ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, "no more TCP clients: %s", isc_result_totext(result)); @@ -1335,6 +1334,7 @@ void ns_client_attach(ns_client_t *source, ns_client_t **targetp) { REQUIRE(NS_CLIENT_VALID(source)); REQUIRE(targetp != NULL && *targetp == NULL); + source->references++; *targetp = source; } @@ -1342,6 +1342,7 @@ ns_client_attach(ns_client_t *source, ns_client_t **targetp) { void ns_client_detach(ns_client_t **clientp) { ns_client_t *client = *clientp; + client->references--; INSIST(client->references >= 0); *clientp = NULL; @@ -1350,12 +1351,13 @@ ns_client_detach(ns_client_t **clientp) { isc_boolean_t ns_client_shuttingdown(ns_client_t *client) { - return (client->newstate == NS_CLIENTSTATE_FREED); + return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED)); } isc_result_t ns_client_replace(ns_client_t *client) { isc_result_t result; + CTRACE("replace"); result = ns_clientmgr_createclients(client->manager, @@ -1519,7 +1521,7 @@ ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n, client, &client->dispentry); if (result != ISC_R_SUCCESS) { - isc_log_write(dns_lctx, + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), @@ -1573,22 +1575,53 @@ ns_client_checkacl(ns_client_t *client, result = dns_acl_match(&netaddr, client->signer, acl, &ns_g_server->aclenv, &match, NULL); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto deny; /* Internal error, already logged. */ if (match > 0) goto allow; goto deny; /* Negative match or no match. */ allow: - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "%s approved", opname); - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); deny: - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_ERROR, "%s denied", opname); return (DNS_R_REFUSED); } +static void +ns_client_logv(ns_client_t *client, isc_logcategory_t *category, + isc_logmodule_t *module, int level, const char *fmt, va_list ap) +{ + char msgbuf[2048]; + char peerbuf[256]; + + vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); + + if (client->peeraddr_valid) { + isc_sockaddr_format(&client->peeraddr, + peerbuf, sizeof peerbuf); + isc_log_write(ns_g_lctx, category, module, level, + "client %s: %s", peerbuf, msgbuf); + } else { + isc_log_write(ns_g_lctx, category, module, level, + "client @%p: %s", client, msgbuf); + } +} + +void +ns_client_log(ns_client_t *client, isc_logcategory_t *category, + isc_logmodule_t *module, int level, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + ns_client_logv(client, category, module, level, fmt, ap); + va_end(ap); +} + diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index b2637cf4..5c901901 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -15,8 +15,8 @@ * SOFTWARE. */ -#ifndef NS_CLIENT_H -#define NS_CLIENT_H 1 +#ifndef NAMED_CLIENT_H +#define NAMED_CLIENT_H 1 /***** ***** Module Info @@ -60,9 +60,8 @@ *** Imports ***/ -#include <isc/types.h> -#include <isc/stdtime.h> #include <isc/buffer.h> +#include <isc/stdtime.h> #include <isc/quota.h> #include <dns/name.h> @@ -79,54 +78,56 @@ typedef ISC_LIST(ns_client_t) client_list_t; struct ns_client { - unsigned int magic; - isc_mem_t * mctx; - ns_clientmgr_t * manager; - int state; - int newstate; - isc_boolean_t disconnect; - int naccepts; - int nreads; - int nsends; - int references; - unsigned int attributes; - isc_task_t * task; - dns_view_t * view; - dns_view_t * lockview; - dns_dispatch_t * dispatch; - dns_dispentry_t * dispentry; - dns_dispatchevent_t * dispevent; - isc_socket_t * tcplistener; - isc_socket_t * tcpsocket; - dns_tcpmsg_t tcpmsg; - isc_boolean_t tcpmsg_valid; - isc_timer_t * timer; - dns_message_t * message; - unsigned char * sendbuf; - dns_rdataset_t * opt; - isc_uint16_t udpsize; - void (*next)(ns_client_t *); - void (*shutdown)(void *arg, isc_result_t result); - void *shutdown_arg; - ns_query_t query; - isc_stdtime_t requesttime; - isc_stdtime_t now; - dns_name_t signername; /* [T]SIG key name */ - dns_name_t * signer; /* NULL if not valid sig */ - isc_boolean_t mortal; /* Die after handling request. */ - isc_quota_t *tcpquota; - isc_quota_t *recursionquota; - ns_interface_t *interface; - isc_sockaddr_t peeraddr; - struct in6_pktinfo pktinfo; - ISC_LINK(ns_client_t) link; - client_list_t *list; /* The list 'link' is part of, - or NULL if not on any list. */ + unsigned int magic; + isc_mem_t * mctx; + ns_clientmgr_t * manager; + int state; + int newstate; + isc_boolean_t disconnect; + int naccepts; + int nreads; + int nsends; + int references; + unsigned int attributes; + isc_task_t * task; + dns_view_t * view; + dns_view_t * lockview; + dns_dispatch_t * dispatch; + dns_dispentry_t * dispentry; + dns_dispatchevent_t * dispevent; + isc_socket_t * tcplistener; + isc_socket_t * tcpsocket; + dns_tcpmsg_t tcpmsg; + isc_boolean_t tcpmsg_valid; + isc_timer_t * timer; + dns_message_t * message; + unsigned char * sendbuf; + dns_rdataset_t * opt; + isc_uint16_t udpsize; + void (*next)(ns_client_t *); + void (*shutdown)(void *arg, isc_result_t result); + void *shutdown_arg; + ns_query_t query; + isc_stdtime_t requesttime; + isc_stdtime_t now; + dns_name_t signername; /* [T]SIG key name */ + dns_name_t * signer; /* NULL if not valid sig */ + isc_boolean_t mortal; /* Die after handling request */ + isc_quota_t *tcpquota; + isc_quota_t *recursionquota; + ns_interface_t *interface; + isc_sockaddr_t peeraddr; + isc_boolean_t peeraddr_valid; + struct in6_pktinfo pktinfo; + ISC_LINK(ns_client_t) link; + /* + * The list 'link' is part of, or NULL if not on any list. + */ + client_list_t *list; }; #define NS_CLIENT_MAGIC 0x4E534363U /* NSCc */ -#define NS_CLIENT_VALID(c) ((c) != NULL && \ - (c)->magic == NS_CLIENT_MAGIC) +#define NS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, NS_CLIENT_MAGIC) #define NS_CLIENTATTR_TCP 0x01 #define NS_CLIENTATTR_RA 0x02 /* Client gets recusive service */ @@ -249,5 +250,9 @@ ns_client_checkacl(ns_client_t *client, * No other return values are possible. */ +void +ns_client_log(ns_client_t *client, isc_logcategory_t *category, + isc_logmodule_t *module, int level, + const char *fmt, ...); -#endif /* NS_CLIENT_H */ +#endif /* NAMED_CLIENT_H */ diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index 66681e06..1e442b8f 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -15,16 +15,13 @@ * SOFTWARE. */ -#ifndef NS_GLOBALS_H -#define NS_GLOBALS_H 1 +#ifndef NAMED_GLOBALS_H +#define NAMED_GLOBALS_H 1 -#include <isc/types.h> #include <isc/rwlock.h> #include <isc/log.h> #include <isc/net.h> -#include <dns/types.h> - #include <omapi/types.h> #include <named/types.h> @@ -42,6 +39,7 @@ EXTERN isc_mem_t * ns_g_mctx INIT(NULL); EXTERN unsigned int ns_g_cpus INIT(1); EXTERN isc_taskmgr_t * ns_g_taskmgr INIT(NULL); +EXTERN dns_dispatchmgr_t * ns_g_dispatchmgr INIT(NULL); /* * XXXRTH We're going to want multiple timer managers eventually. One * for really short timers, another for client timers, and one @@ -89,4 +87,4 @@ EXTERN const char * ns_g_cachefile INIT(NULL); #undef EXTERN #undef INIT -#endif /* NS_GLOBALS_H */ +#endif /* NAMED_GLOBALS_H */ diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h index df896633..d0535217 100644 --- a/bin/named/include/named/interfacemgr.h +++ b/bin/named/include/named/interfacemgr.h @@ -15,8 +15,8 @@ * SOFTWARE. */ -#ifndef NS_INTERFACEMGR_H -#define NS_INTERFACEMGR_H 1 +#ifndef NAMED_INTERFACEMGR_H +#define NAMED_INTERFACEMGR_H 1 /***** ***** Module Info @@ -47,8 +47,7 @@ *** Imports ***/ -#include <isc/types.h> -#include <isc/result.h> +#include <isc/magic.h> #include <isc/mem.h> #include <isc/socket.h> @@ -62,7 +61,7 @@ ***/ #define IFACE_MAGIC 0x493A2D29U /* I:-). */ -#define NS_INTERFACE_VALID(t) ((t) != NULL && (t)->magic == IFACE_MAGIC) +#define NS_INTERFACE_VALID(t) ISC_MAGIC_VALID(t, IFACE_MAGIC) struct ns_interface { unsigned int magic; /* Magic number. */ @@ -86,15 +85,14 @@ struct ns_interface { *** Functions ***/ - isc_result_t ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, - isc_socketmgr_t *socketmgr, ns_clientmgr_t *clientmgr, - ns_interfacemgr_t **mgrp); + isc_socketmgr_t *socketmgr, + dns_dispatchmgr_t *dispatchmgr, + ns_clientmgr_t *clientmgr, ns_interfacemgr_t **mgrp); void -ns_interfacemgr_attach(ns_interfacemgr_t *source, - ns_interfacemgr_t **target); +ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target); void ns_interfacemgr_detach(ns_interfacemgr_t **targetp); @@ -115,8 +113,7 @@ ns_interfacemgr_scan(ns_interfacemgr_t *mgr); */ void -ns_interfacemgr_setlistenon(ns_interfacemgr_t *mgr, - ns_listenlist_t *value); +ns_interfacemgr_setlistenon(ns_interfacemgr_t *mgr, ns_listenlist_t *value); /* * Set the "listen-on" list of 'mgr' to 'value'. * The previous listen-on list is freed. @@ -134,10 +131,9 @@ dns_aclenv_t * ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr); void -ns_interface_attach(ns_interface_t *source, - ns_interface_t **target); +ns_interface_attach(ns_interface_t *source, ns_interface_t **target); void ns_interface_detach(ns_interface_t **targetp); -#endif /* NS_INTERFACEMGR_H */ +#endif /* NAMED_INTERFACEMGR_H */ diff --git a/bin/named/include/named/listenlist.h b/bin/named/include/named/listenlist.h index 4eca218b..00ab6cbc 100644 --- a/bin/named/include/named/listenlist.h +++ b/bin/named/include/named/listenlist.h @@ -15,8 +15,8 @@ * SOFTWARE. */ -#ifndef NS_LISTENLIST_H -#define NS_LISTENLIST_H 1 +#ifndef NAMED_LISTENLIST_H +#define NAMED_LISTENLIST_H 1 /***** ***** Module Info @@ -29,6 +29,7 @@ /*** *** Imports ***/ +#include <isc/net.h> #include <dns/types.h> @@ -56,8 +57,6 @@ struct ns_listenlist { *** Functions ***/ -ISC_LANG_BEGINDECLS - isc_result_t ns_listenelt_create(isc_mem_t *mctx, in_port_t port, dns_acl_t *acl, ns_listenelt_t **target); @@ -82,8 +81,6 @@ ns_listenlist_default(isc_mem_t *mctx, in_port_t port, * all addresses with port 'port'. */ -ISC_LANG_ENDDECLS - -#endif /* NS_LISTENLIST_H */ +#endif /* NAMED_LISTENLIST_H */ diff --git a/bin/named/include/named/log.h b/bin/named/include/named/log.h index 74aac91d..0ce529c9 100644 --- a/bin/named/include/named/log.h +++ b/bin/named/include/named/log.h @@ -15,22 +15,24 @@ * SOFTWARE. */ -#ifndef NS_LOG_H -#define NS_LOG_H 1 +#ifndef NAMED_LOG_H +#define NAMED_LOG_H 1 -#include <isc/types.h> #include <isc/log.h> +#include <isc/types.h> #include <dns/log.h> -#include <named/globals.h> +#include <named/globals.h> /* Required for ns_g_(categories|modules). */ -/* Unused slot */ +/* Unused slot 0. */ #define NS_LOGCATEGORY_CLIENT (&ns_g_categories[1]) #define NS_LOGCATEGORY_NETWORK (&ns_g_categories[2]) #define NS_LOGCATEGORY_UPDATE (&ns_g_categories[3]) -/* Backwards compatibility. */ +/* + * Backwards compatibility. + */ #define NS_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL #define NS_LOGMODULE_MAIN (&ns_g_modules[0]) @@ -45,12 +47,38 @@ #define NS_LOGMODULE_OMAPI (&ns_g_modules[9]) isc_result_t -ns_log_init(void); +ns_log_init(isc_boolean_t safe); +/* + * Initialize the logging system and set up an initial default + * logging default configuration that will be used until the + * config file has been read. + * + * If 'safe' is true, use a default configuration that refrains + * from opening files. This is to avoid creating log files + * as root. + */ isc_result_t -ns_log_setdefaults(isc_logconfig_t *lcfg); +ns_log_setdefaultchannels(isc_logconfig_t *lcfg); +/* + * Set up logging channels according to the named defaults, which + * may differ from the logging library defaults. Currently, + * this just means setting up default_debug. + */ + +isc_result_t +ns_log_setsafechannels(isc_logconfig_t *lcfg); +/* + * Like ns_log_setdefaultchannels(), but omits any logging to files. + */ + +isc_result_t +ns_log_setdefaultcategory(isc_logconfig_t *lcfg); +/* + * Set up "category default" to go to the right places. + */ void ns_log_shutdown(void); -#endif /* NS_LOG_H */ +#endif /* NAMED_LOG_H */ diff --git a/bin/named/include/named/logconf.h b/bin/named/include/named/logconf.h index d456a951..5ccd3e91 100644 --- a/bin/named/include/named/logconf.h +++ b/bin/named/include/named/logconf.h @@ -15,8 +15,8 @@ * SOFTWARE. */ -#ifndef NS_LOGCONF_H -#define NS_LOGCONF_H 1 +#ifndef NAMED_LOGCONF_H +#define NAMED_LOGCONF_H 1 #include <isc/log.h> @@ -29,4 +29,4 @@ ns_log_configure(isc_logconfig_t *logconf, dns_c_logginglist_t *clog); * the named.conf data in 'clog'. */ -#endif /* NS_LOGCONF_H */ +#endif /* NAMED_LOGCONF_H */ diff --git a/bin/named/include/named/main.h b/bin/named/include/named/main.h index b737b7c1..7a2caf07 100644 --- a/bin/named/include/named/main.h +++ b/bin/named/include/named/main.h @@ -15,10 +15,10 @@ * SOFTWARE. */ -#ifndef NS_MAIN_H -#define NS_MAIN_H 1 +#ifndef NAMED_MAIN_H +#define NAMED_MAIN_H 1 void ns_main_earlyfatal(const char *format, ...); -#endif /* NS_MAIN_H */ +#endif /* NAMED_MAIN_H */ diff --git a/bin/named/include/named/notify.h b/bin/named/include/named/notify.h index a3b43a37..51873a9f 100644 --- a/bin/named/include/named/notify.h +++ b/bin/named/include/named/notify.h @@ -48,4 +48,5 @@ ns_notify_start(ns_client_t *client); * client to be valid. */ -#endif +#endif /* NAMED_NOTIFY_H */ + diff --git a/bin/named/include/named/omapi.h b/bin/named/include/named/omapi.h index 828106e4..1f83107f 100644 --- a/bin/named/include/named/omapi.h +++ b/bin/named/include/named/omapi.h @@ -15,6 +15,9 @@ * SOFTWARE. */ +#ifndef NAMED_OMAPI_H +#define NAMED_OMAPI_H 1 + #include <omapi/omapi.h> #define NS_OMAPI_PORT 953 @@ -34,3 +37,4 @@ ns_omapi_init(void); isc_result_t ns_omapi_listen(omapi_object_t **managerp); +#endif /* NAMED_OMAPI_H */ diff --git a/bin/named/include/named/query.h b/bin/named/include/named/query.h index 4dd5255a..4fc259ed 100644 --- a/bin/named/include/named/query.h +++ b/bin/named/include/named/query.h @@ -15,8 +15,8 @@ * SOFTWARE. */ -#ifndef NS_QUERY_H -#define NS_QUERY_H 1 +#ifndef NAMED_QUERY_H +#define NAMED_QUERY_H 1 #include <isc/types.h> #include <isc/buffer.h> @@ -29,6 +29,7 @@ typedef struct ns_dbversion { dns_db_t *db; dns_dbversion_t *version; + isc_boolean_t queryok; ISC_LINK(struct ns_dbversion) link; } ns_dbversion_t; @@ -53,6 +54,8 @@ struct ns_query { #define NS_QUERYATTR_NAMEBUFUSED 0x08 #define NS_QUERYATTR_RECURSING 0x10 #define NS_QUERYATTR_CACHEGLUEOK 0x20 +#define NS_QUERYATTR_QUERYOKVALID 0x40 +#define NS_QUERYATTR_QUERYOK 0x80 isc_result_t ns_query_init(ns_client_t *client); @@ -63,4 +66,4 @@ ns_query_free(ns_client_t *client); void ns_query_start(ns_client_t *client); -#endif /* NS_QUERY_H */ +#endif /* NAMED_QUERY_H */ diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 56ce3389..2d1fab43 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -15,8 +15,8 @@ * SOFTWARE. */ -#ifndef NS_SERVER_H -#define NS_SERVER_H 1 +#ifndef NAMED_SERVER_H +#define NAMED_SERVER_H 1 #include <isc/log.h> #include <isc/sockaddr.h> @@ -42,15 +42,9 @@ struct ns_server { isc_rwlock_t conflock; /* Configurable data. */ - isc_boolean_t recursion; - isc_boolean_t auth_nxdomain; - dns_transfer_format_t transfer_format; - dns_acl_t * queryacl; - dns_acl_t * recursionacl; isc_quota_t xfroutquota; isc_quota_t tcpquota; isc_quota_t recursionquota; - isc_boolean_t provide_ixfr; /* Not really configurable, but covered by conflock. */ dns_aclenv_t aclenv; @@ -60,12 +54,8 @@ struct ns_server { ns_clientmgr_t * clientmgr; dns_viewlist_t viewlist; ns_interfacemgr_t * interfacemgr; - dns_db_t * roothints; + dns_db_t * in_roothints; dns_tkey_ctx_t * tkeyctx; - isc_sockaddr_t querysrc_addressv4; - dns_dispatch_t * querysrc_dispatchv4; - isc_sockaddr_t querysrc_addressv6; - dns_dispatch_t * querysrc_dispatchv6; isc_timer_t * interface_timer; isc_mutex_t reload_event_lock; @@ -100,4 +90,4 @@ ns_server_reloadwanted(ns_server_t *server); */ -#endif /* NS_SERVER_H */ +#endif /* NAMED_SERVER_H */ diff --git a/bin/named/include/named/types.h b/bin/named/include/named/types.h index d3f4b2ef..cc061ab3 100644 --- a/bin/named/include/named/types.h +++ b/bin/named/include/named/types.h @@ -15,10 +15,8 @@ * SOFTWARE. */ -#ifndef NS_TYPES_H -#define NS_TYPES_H 1 - -#include <isc/list.h> +#ifndef NAMED_TYPES_H +#define NAMED_TYPES_H 1 #include <dns/types.h> @@ -29,4 +27,4 @@ typedef struct ns_server ns_server_t; typedef struct ns_interface ns_interface_t; typedef struct ns_interfacemgr ns_interfacemgr_t; -#endif /* NS_TYPES_H */ +#endif /* NAMED_TYPES_H */ diff --git a/bin/named/include/named/update.h b/bin/named/include/named/update.h index 72109756..ad5d33b8 100644 --- a/bin/named/include/named/update.h +++ b/bin/named/include/named/update.h @@ -15,8 +15,8 @@ * SOFTWARE. */ -#ifndef NS_UPDATE_H -#define NS_UPDATE_H 1 +#ifndef NAMED_UPDATE_H +#define NAMED_UPDATE_H 1 /***** ***** Module Info @@ -30,7 +30,6 @@ *** Imports ***/ -#include <isc/types.h> #include <dns/types.h> #include <dns/result.h> @@ -42,6 +41,7 @@ *** Functions ***/ -void ns_update_start(ns_client_t *client); +void +ns_update_start(ns_client_t *client); -#endif /* NS_UPDATE_H */ +#endif /* NAMED_UPDATE_H */ diff --git a/bin/named/include/named/xfrout.h b/bin/named/include/named/xfrout.h index bb2dfecf..66b1e439 100644 --- a/bin/named/include/named/xfrout.h +++ b/bin/named/include/named/xfrout.h @@ -15,8 +15,8 @@ * SOFTWARE. */ -#ifndef NS_XFROUT_H -#define NS_XFROUT_H 1 +#ifndef NAMED_XFROUT_H +#define NAMED_XFROUT_H 1 /***** ***** Module Info @@ -30,6 +30,7 @@ *** Functions ***/ -void ns_xfr_start(ns_client_t *client, dns_rdatatype_t xfrtype); +void +ns_xfr_start(ns_client_t *client, dns_rdatatype_t xfrtype); -#endif /* NS_XFROUT_H */ +#endif /* NAMED_XFROUT_H */ diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c index b33ff244..28999b12 100644 --- a/bin/named/interfacemgr.c +++ b/bin/named/interfacemgr.c @@ -17,33 +17,20 @@ #include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - -#include <isc/assertions.h> -#include <isc/error.h> -#include <isc/mem.h> -#include <isc/result.h> -#include <isc/socket.h> -#include <isc/types.h> -#include <isc/net.h> #include <isc/interfaceiter.h> +#include <isc/string.h> +#include <isc/task.h> #include <isc/util.h> #include <dns/acl.h> #include <dns/dispatch.h> #include <named/client.h> -#include <named/globals.h> -#include <named/listenlist.h> #include <named/log.h> #include <named/interfacemgr.h> #define IFMGR_MAGIC 0x49464D47U /* IFMG. */ -#define NS_INTERFACEMGR_VALID(t) ((t) != NULL && (t)->magic == IFMGR_MAGIC) +#define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC) #define IFMGR_COMMON_LOGARGS \ ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR @@ -55,6 +42,7 @@ struct ns_interfacemgr { isc_mem_t * mctx; /* Memory context. */ isc_taskmgr_t * taskmgr; /* Task manager. */ isc_socketmgr_t * socketmgr; /* Socket manager. */ + dns_dispatchmgr_t * dispatchmgr; ns_clientmgr_t * clientmgr; /* Client manager. */ unsigned int generation; /* Current generation no. */ ns_listenlist_t * listenon; @@ -62,30 +50,14 @@ struct ns_interfacemgr { ISC_LIST(ns_interface_t) interfaces; /* List of interfaces. */ }; -static void purge_old_interfaces(ns_interfacemgr_t *mgr); - -/* - * Format a human-readable representation of the socket address '*sa' - * into the character array 'array', which is of size 'size'. - * The resulting string is guaranteed to be null-terminated. - */ static void -sockaddr_format(isc_sockaddr_t *sa, char *array, unsigned int size) -{ - isc_result_t result; - isc_buffer_t buf; - isc_buffer_init(&buf, array, size, ISC_BUFFERTYPE_TEXT); - result = isc_sockaddr_totext(sa, &buf); - if (result != ISC_R_SUCCESS) { - strncpy(array, "<unknown address>", size); - array[size-1] = '\0'; - } -} +purge_old_interfaces(ns_interfacemgr_t *mgr); isc_result_t ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, - isc_socketmgr_t *socketmgr, ns_clientmgr_t *clientmgr, - ns_interfacemgr_t **mgrp) + isc_socketmgr_t *socketmgr, + dns_dispatchmgr_t *dispatchmgr, + ns_clientmgr_t *clientmgr, ns_interfacemgr_t **mgrp) { isc_result_t result; ns_interfacemgr_t *mgr; @@ -96,7 +68,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, mgr = isc_mem_get(mctx, sizeof(*mgr)); if (mgr == NULL) - return (DNS_R_NOMEMORY); + return (ISC_R_NOMEMORY); result = isc_mutex_init(&mgr->lock); if (result != ISC_R_SUCCESS) @@ -105,6 +77,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, mgr->mctx = mctx; mgr->taskmgr = taskmgr; mgr->socketmgr = socketmgr; + mgr->dispatchmgr = dispatchmgr; mgr->clientmgr = clientmgr; mgr->generation = 1; mgr->listenon = NULL; @@ -112,7 +85,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, result = ns_listenlist_default(mctx, ns_g_port, &mgr->listenon); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto cleanup_mem; result = dns_aclenv_init(mctx, &mgr->aclenv); @@ -122,7 +95,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, mgr->references = 1; mgr->magic = IFMGR_MAGIC; *mgrp = mgr; - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); cleanup_listenon: ns_listenlist_detach(&mgr->listenon); @@ -132,8 +105,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, } static void -ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) -{ +ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) { REQUIRE(NS_INTERFACEMGR_VALID(mgr)); dns_aclenv_destroy(&mgr->aclenv); ns_listenlist_detach(&mgr->listenon); @@ -143,15 +115,12 @@ ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) } dns_aclenv_t * -ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) -{ +ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) { return (&mgr->aclenv); } void -ns_interfacemgr_attach(ns_interfacemgr_t *source, - ns_interfacemgr_t **target) -{ +ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) { REQUIRE(NS_INTERFACEMGR_VALID(source)); LOCK(&source->lock); INSIST(source->references > 0); @@ -161,8 +130,7 @@ ns_interfacemgr_attach(ns_interfacemgr_t *source, } void -ns_interfacemgr_detach(ns_interfacemgr_t **targetp) -{ +ns_interfacemgr_detach(ns_interfacemgr_t **targetp) { isc_result_t need_destroy = ISC_FALSE; ns_interfacemgr_t *target = *targetp; REQUIRE(target != NULL); @@ -179,8 +147,7 @@ ns_interfacemgr_detach(ns_interfacemgr_t **targetp) } void -ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) -{ +ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) { REQUIRE(NS_INTERFACEMGR_VALID(mgr)); LOCK(&mgr->lock); @@ -206,7 +173,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, REQUIRE(NS_INTERFACEMGR_VALID(mgr)); ifp = isc_mem_get(mgr->mctx, sizeof(*ifp)); if (ifp == NULL) - return (DNS_R_NOMEMORY); + return (ISC_R_NOMEMORY); ifp->mgr = NULL; ifp->generation = mgr->generation; ifp->addr = *addr; @@ -221,7 +188,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, * Create a task. */ ifp->task = NULL; - result = isc_task_create(mgr->taskmgr, mgr->mctx, 0, &ifp->task); + result = isc_task_create(mgr->taskmgr, 0, &ifp->task); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "isc_task_create() failed: %s", @@ -230,7 +197,6 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, } isc_task_setname(ifp->task, "ifp", ifp); - ifp->udpsocket = NULL; ifp->udpdispatch = NULL; ifp->tcpsocket = NULL; @@ -250,7 +216,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, ifp->magic = IFACE_MAGIC; *ifpret = ifp; - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); task_create_failure: isc_mutex_destroy(&ifp->lock); @@ -258,36 +224,28 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, ifp->magic = 0; isc_mem_put(mgr->mctx, ifp, sizeof(*ifp)); - return (DNS_R_UNEXPECTED); + return (ISC_R_UNEXPECTED); } static isc_result_t ns_interface_listenudp(ns_interface_t *ifp) { isc_result_t result; + unsigned int attrs; + unsigned int attrmask; - /* - * Open a UDP socket. - */ - result = isc_socket_create(ifp->mgr->socketmgr, - isc_sockaddr_pf(&ifp->addr), - isc_sockettype_udp, - &ifp->udpsocket); - if (result != ISC_R_SUCCESS) { - isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, - "creating UDP socket: %s", - isc_result_totext(result)); - goto udp_socket_failure; - } - result = isc_socket_bind(ifp->udpsocket, &ifp->addr); - if (result != ISC_R_SUCCESS) { - isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, - "binding UDP socket: %s", - isc_result_totext(result)); - goto udp_bind_failure; - } - result = dns_dispatch_create(ifp->mgr->mctx, ifp->udpsocket, ifp->task, - 4096, 1000, 32768, 8219, 8237, NULL, - &ifp->udpdispatch); + attrs = 0; + attrs |= DNS_DISPATCHATTR_UDP; + if (isc_sockaddr_pf(&ifp->addr) == AF_INET) + attrs |= DNS_DISPATCHATTR_IPV4; + else + attrs |= DNS_DISPATCHATTR_IPV6; + attrmask = 0; + attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP; + attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; + result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr, + ns_g_taskmgr, &ifp->addr, + 4096, 1000, 32768, 8219, 8237, + attrs, attrmask, &ifp->udpdispatch); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "UDP dns_dispatch_create(): %s", @@ -308,9 +266,6 @@ ns_interface_listenudp(ns_interface_t *ifp) { addtodispatch_failure: dns_dispatch_detach(&ifp->udpdispatch); udp_dispatch_failure: - udp_bind_failure: - isc_socket_detach(&ifp->udpsocket); - udp_socket_failure: return (result); } @@ -362,7 +317,7 @@ ns_interface_accepttcp(ns_interface_t *ifp) { tcp_bind_failure: isc_socket_detach(&ifp->tcpsocket); tcp_socket_failure: - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } static isc_result_t @@ -374,20 +329,20 @@ ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, REQUIRE(ifpret != NULL && *ifpret == NULL); result = ns_interface_create(mgr, addr, name, &ifp); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) return (result); result = ns_interface_listenudp(ifp); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto cleanup_interface; result = ns_interface_accepttcp(ifp); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { /* - * XXXRTH We don't currently have a way to easily stop dispatch - * service, so we return currently return DNS_R_SUCCESS (the UDP - * stuff will work even if TCP creation failed). This will be fixed - * later. + * XXXRTH We don't currently have a way to easily stop dispatch + * service, so we return currently return ISC_R_SUCCESS (the + * UDP stuff will work even if TCP creation failed). This will + * be fixed later. */ result = ISC_R_SUCCESS; } @@ -407,10 +362,6 @@ ns_interface_destroy(ns_interface_t *ifp) { if (ifp->udpdispatch != NULL) dns_dispatch_detach(&ifp->udpdispatch); - if (ifp->udpsocket != NULL) { - isc_socket_cancel(ifp->udpsocket, NULL, ISC_SOCKCANCEL_ALL); - isc_socket_detach(&ifp->udpsocket); - } if (ifp->tcpsocket != NULL) { isc_socket_cancel(ifp->tcpsocket, NULL, ISC_SOCKCANCEL_ALL); isc_socket_detach(&ifp->tcpsocket); @@ -426,9 +377,7 @@ ns_interface_destroy(ns_interface_t *ifp) { } void -ns_interface_attach(ns_interface_t *source, - ns_interface_t **target) -{ +ns_interface_attach(ns_interface_t *source, ns_interface_t **target) { REQUIRE(NS_INTERFACE_VALID(source)); LOCK(&source->lock); INSIST(source->references > 0); @@ -438,8 +387,7 @@ ns_interface_attach(ns_interface_t *source, } void -ns_interface_detach(ns_interface_t **targetp) -{ +ns_interface_detach(ns_interface_t **targetp) { isc_result_t need_destroy = ISC_FALSE; ns_interface_t *target = *targetp; REQUIRE(target != NULL); @@ -482,7 +430,7 @@ purge_old_interfaces(ns_interfacemgr_t *mgr) { if (ifp->generation != mgr->generation) { char sabuf[256]; ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); - sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf)); + isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf)); isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, "no longer listening on %s", sabuf); @@ -590,8 +538,8 @@ do_ipv4(ns_interfacemgr_t *mgr) { ifp->generation = mgr->generation; } else { char sabuf[256]; - sockaddr_format(&listen_sockaddr, - sabuf, sizeof(sabuf)); + isc_sockaddr_format(&listen_sockaddr, + sabuf, sizeof(sabuf)); isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, "listening on IPv4 interface " @@ -601,7 +549,7 @@ do_ipv4(ns_interfacemgr_t *mgr) { &listen_sockaddr, interface.name, &ifp); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "creating IPv4 interface %s " @@ -647,7 +595,7 @@ do_ipv6(ns_interfacemgr_t *mgr) { "listening on IPv6 interfaces, port %u", ns_g_port); result = ns_interface_setup(mgr, &listen_addr, "<any>", &ifp); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "listening on IPv6 interfaces failed"); @@ -692,9 +640,7 @@ ns_interfacemgr_scan(ns_interfacemgr_t *mgr) { } void -ns_interfacemgr_setlistenon(ns_interfacemgr_t *mgr, - ns_listenlist_t *value) -{ +ns_interfacemgr_setlistenon(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { LOCK(&mgr->lock); ns_listenlist_detach(&mgr->listenon); ns_listenlist_attach(value, &mgr->listenon); diff --git a/bin/named/listenlist.c b/bin/named/listenlist.c index c9fd7c46..c5f36e09 100644 --- a/bin/named/listenlist.c +++ b/bin/named/listenlist.c @@ -17,15 +17,15 @@ #include <config.h> -#include <isc/assertions.h> #include <isc/mem.h> -#include <isc/result.h> +#include <isc/util.h> #include <dns/acl.h> #include <named/listenlist.h> -static void destroy(ns_listenlist_t *list); +static void +destroy(ns_listenlist_t *list); isc_result_t ns_listenelt_create(isc_mem_t *mctx, in_port_t port, @@ -79,16 +79,14 @@ destroy(ns_listenlist_t *list) { } void -ns_listenlist_attach(ns_listenlist_t *source, ns_listenlist_t **target) -{ +ns_listenlist_attach(ns_listenlist_t *source, ns_listenlist_t **target) { INSIST(source->refcount > 0); source->refcount++; *target = source; } void -ns_listenlist_detach(ns_listenlist_t **listp) -{ +ns_listenlist_detach(ns_listenlist_t **listp) { ns_listenlist_t *list = *listp; INSIST(list->refcount > 0); list->refcount--; diff --git a/bin/named/log.c b/bin/named/log.c index f9c11bb9..4811a4d0 100644 --- a/bin/named/log.c +++ b/bin/named/log.c @@ -17,13 +17,6 @@ #include <config.h> -#include <isc/assertions.h> -#include <isc/log.h> -#include <isc/result.h> - -#include <dns/log.h> - -#include <named/globals.h> #include <named/log.h> /* @@ -56,7 +49,7 @@ static isc_logmodule_t modules[] = { }; isc_result_t -ns_log_init(void) { +ns_log_init(isc_boolean_t safe) { isc_result_t result; isc_logconfig_t *lcfg; @@ -64,11 +57,6 @@ ns_log_init(void) { ns_g_modules = modules; /* - * XXXRTH This is not necessarily the final default logging - * setup. - */ - - /* * Setup a logging context. */ result = isc_log_create(ns_g_mctx, &ns_g_lctx, &lcfg); @@ -77,9 +65,18 @@ ns_log_init(void) { isc_log_registercategories(ns_g_lctx, ns_g_categories); isc_log_registermodules(ns_g_lctx, ns_g_modules); + isc_log_setcontext(ns_g_lctx); dns_log_init(ns_g_lctx); + dns_log_setcontext(ns_g_lctx); + + if (safe) + result = ns_log_setsafechannels(lcfg); + else + result = ns_log_setdefaultchannels(lcfg); + if (result != ISC_R_SUCCESS) + goto cleanup; - result = ns_log_setdefaults(lcfg); + result = ns_log_setdefaultcategory(lcfg); if (result != ISC_R_SUCCESS) goto cleanup; @@ -92,7 +89,7 @@ ns_log_init(void) { } isc_result_t -ns_log_setdefaults(isc_logconfig_t *lcfg) { +ns_log_setdefaultchannels(isc_logconfig_t *lcfg) { isc_result_t result; isc_logdestination_t destination; @@ -116,6 +113,46 @@ ns_log_setdefaults(isc_logconfig_t *lcfg) { goto cleanup; } + /* + * Set the initial debug level. + */ + isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel); + + result = ISC_R_SUCCESS; + + cleanup: + return (result); +} + +isc_result_t +ns_log_setsafechannels(isc_logconfig_t *lcfg) { + isc_result_t result; + + if (! ns_g_logstderr) { + result = isc_log_createchannel(lcfg, "default_debug", + ISC_LOG_TONULL, + ISC_LOG_DYNAMIC, + NULL, 0); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + + /* + * Setting the debug level to zero should get the output + * discarded a bit faster. + */ + isc_log_setdebuglevel(ns_g_lctx, 0); + + result = ISC_R_SUCCESS; + + cleanup: + return (result); +} + +isc_result_t +ns_log_setdefaultcategory(isc_logconfig_t *lcfg) { + isc_result_t result; + result = isc_log_usechannel(lcfg, "default_syslog", ISC_LOGCATEGORY_DEFAULT, NULL); if (result != ISC_R_SUCCESS) @@ -126,12 +163,7 @@ ns_log_setdefaults(isc_logconfig_t *lcfg) { if (result != ISC_R_SUCCESS) goto cleanup; - /* - * Set the initial debug level. - */ - isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel); - - return (ISC_R_SUCCESS); + result = ISC_R_SUCCESS; cleanup: return (result); diff --git a/bin/named/logconf.c b/bin/named/logconf.c index 042380b8..e349a1a0 100644 --- a/bin/named/logconf.c +++ b/bin/named/logconf.c @@ -17,9 +17,8 @@ #include <config.h> -#include <isc/result.h> +#include <isc/string.h> -#include <named/globals.h> #include <named/log.h> #include <named/logconf.h> @@ -28,14 +27,12 @@ if (result != ISC_R_SUCCESS) goto cleanup; \ } while (0) - /* * Set up a logging category according to the named.conf data * in 'ccat' and add it to 'lctx'. */ static isc_result_t -category_fromconf(dns_c_logcat_t *ccat, isc_logconfig_t *lctx) -{ +category_fromconf(dns_c_logcat_t *ccat, isc_logconfig_t *lctx) { isc_result_t result; unsigned int i; isc_logcategory_t *category; @@ -69,8 +66,7 @@ category_fromconf(dns_c_logcat_t *ccat, isc_logconfig_t *lctx) * in 'cchan' and add it to 'lctx'. */ static isc_result_t -channel_fromconf(dns_c_logchan_t *cchan, isc_logconfig_t *lctx) -{ +channel_fromconf(dns_c_logchan_t *cchan, isc_logconfig_t *lctx) { isc_result_t result; isc_logdestination_t dest; unsigned int type; @@ -83,9 +79,13 @@ channel_fromconf(dns_c_logchan_t *cchan, isc_logconfig_t *lctx) type = ISC_LOG_TOFILE; { const char *path = NULL; - isc_uint32_t versions = ISC_LOG_ROLLNEVER; + isc_int32_t versions = ISC_LOG_ROLLNEVER; + /* + * XXXDCL should be isc_offset_t, but that + * is incompatible with dns_c_logchan_getsize. + */ isc_uint32_t size = 0; - (void) dns_c_logchan_getpath(cchan, &path); + (void)dns_c_logchan_getpath(cchan, &path); if (path == NULL) { isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_CONFIG, @@ -95,11 +95,13 @@ channel_fromconf(dns_c_logchan_t *cchan, isc_logconfig_t *lctx) "no file name"); return (ISC_R_UNEXPECTED); } - (void) dns_c_logchan_getversions(cchan, &versions); - (void) dns_c_logchan_getsize(cchan, &size); + (void)dns_c_logchan_getversions(cchan, + (isc_uint32_t *) + &versions); + (void)dns_c_logchan_getsize(cchan, &size); dest.file.stream = NULL; dest.file.name = cchan->u.filec.path; - dest.file.versions = (int)versions; + dest.file.versions = versions; dest.file.maximum_size = size; } break; @@ -108,7 +110,7 @@ channel_fromconf(dns_c_logchan_t *cchan, isc_logconfig_t *lctx) type = ISC_LOG_TOSYSLOG; { int facility = LOG_DAEMON; - (void) dns_c_logchan_getfacility(cchan, &facility); + (void)dns_c_logchan_getfacility(cchan, &facility); dest.facility = facility; } break; @@ -125,9 +127,9 @@ channel_fromconf(dns_c_logchan_t *cchan, isc_logconfig_t *lctx) isc_boolean_t printsev = ISC_FALSE; isc_boolean_t printtime = ISC_FALSE; - (void) dns_c_logchan_getprintcat(cchan, &printcat); - (void) dns_c_logchan_getprintsev(cchan, &printsev); - (void) dns_c_logchan_getprinttime(cchan, &printtime); + (void)dns_c_logchan_getprintcat(cchan, &printcat); + (void)dns_c_logchan_getprintsev(cchan, &printsev); + (void)dns_c_logchan_getprinttime(cchan, &printtime); if (printcat) flags |= ISC_LOG_PRINTCATEGORY; @@ -139,7 +141,7 @@ channel_fromconf(dns_c_logchan_t *cchan, isc_logconfig_t *lctx) } level = ISC_LOG_INFO; - (void) dns_c_logchan_getdebuglevel(cchan, &level); + (void)dns_c_logchan_getdebuglevel(cchan, &level); result = isc_log_createchannel(lctx, cchan->name, type, level, &dest, flags); @@ -147,13 +149,14 @@ channel_fromconf(dns_c_logchan_t *cchan, isc_logconfig_t *lctx) } isc_result_t -ns_log_configure(isc_logconfig_t *lcctx, dns_c_logginglist_t *clog) -{ +ns_log_configure(isc_logconfig_t *lcctx, dns_c_logginglist_t *clog) { isc_result_t result; dns_c_logchan_t *cchan; dns_c_logcat_t *ccat; isc_boolean_t default_set = ISC_FALSE; + CHECK(ns_log_setdefaultchannels(lcctx)); + for (cchan = ISC_LIST_HEAD(clog->channels); cchan != NULL; cchan = ISC_LIST_NEXT(cchan, next)) { @@ -170,7 +173,7 @@ ns_log_configure(isc_logconfig_t *lcctx, dns_c_logginglist_t *clog) } if (! default_set) - CHECK(ns_log_setdefaults(lcctx)); + CHECK(ns_log_setdefaultcategory(lcctx)); return (ISC_R_SUCCESS); @@ -179,5 +182,3 @@ ns_log_configure(isc_logconfig_t *lcctx, dns_c_logginglist_t *clog) isc_logconfig_destroy(&lcctx); return (result); } - - diff --git a/bin/named/main.c b/bin/named/main.c index 3b5e16aa..fc2be1f5 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -17,30 +17,25 @@ #include <config.h> -#include <errno.h> -#include <string.h> -#include <stdarg.h> #include <stdlib.h> -#include <stddef.h> #include <isc/app.h> -#include <isc/assertions.h> -#include <isc/error.h> -#include <isc/boolean.h> #include <isc/commandline.h> #include <isc/task.h> #include <isc/timer.h> +#include <isc/util.h> -#include <dns/dbtable.h> -#include <dns/tsig.h> -#include <dns/tkey.h> -#include <dns/result.h> +#include <dns/dispatch.h> #include <dst/result.h> -#define NS_MAIN 1 +/* + * Defining NS_MAIN provides storage declaratons (rather than extern) + * for variables in named/globals.h. + */ +#define NS_MAIN 1 -#include <named/globals.h> +#include <named/globals.h> /* Explicit, though named/log.h includes it. */ #include <named/interfacemgr.h> #include <named/log.h> #include <named/omapi.h> @@ -238,7 +233,7 @@ parse_command_line(int argc, char *argv[]) { } static isc_result_t -create_managers() { +create_managers(void) { isc_result_t result; result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr); @@ -284,12 +279,22 @@ destroy_managers(void) { } static void -setup() { +setup(void) { isc_result_t result; ns_os_chroot(ns_g_chrootdir); - result = ns_log_init(); + /* + * For operating systems which have a capability mechanism, now + * is the time to switch to minimal privs and change our user id. + * On traditional UNIX systems, this call will be a no-op, and we + * will change the user ID after reading the config file the first + * time. (We need to read the config file to know which possibly + * privileged ports to bind() to.) + */ + ns_os_minprivs(ns_g_username); + + result = ns_log_init(ISC_TF(ns_g_username != NULL)); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("ns_log_init() failed: %s", isc_result_totext(result)); @@ -332,7 +337,7 @@ setup() { } static void -cleanup() { +cleanup(void) { destroy_managers(); ns_server_destroy(&ns_g_server); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, diff --git a/bin/named/notify.c b/bin/named/notify.c index 082b20e7..b9994353 100644 --- a/bin/named/notify.c +++ b/bin/named/notify.c @@ -17,40 +17,13 @@ #include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> - -#include <isc/assertions.h> -#include <isc/error.h> -#include <isc/mem.h> -#include <isc/result.h> -#include <isc/taskpool.h> - -#include <dns/db.h> -#include <dns/dbiterator.h> -#include <dns/dbtable.h> -#include <dns/dnssec.h> -#include <dns/events.h> -#include <dns/fixedname.h> -#include <dns/journal.h> #include <dns/message.h> -#include <dns/name.h> -#include <dns/nxt.h> -#include <dns/rdata.h> -#include <dns/rdatalist.h> #include <dns/rdataset.h> -#include <dns/rdatasetiter.h> -#include <dns/rdatastruct.h> #include <dns/result.h> -#include <dns/types.h> #include <dns/view.h> #include <dns/zone.h> #include <dns/zt.h> -#include <named/globals.h> -#include <named/client.h> #include <named/log.h> #include <named/notify.h> @@ -91,23 +64,28 @@ */ #define CHECK(op) \ do { result = (op); \ - if (result != DNS_R_SUCCESS) goto failure; \ + if (result != ISC_R_SUCCESS) goto failure; \ } while (0) /* * Fail unconditionally with result 'code', which must not - * be DNS_R_SUCCESS. The reason for failure presumably has + * be ISC_R_SUCCESS. The reason for failure presumably has * been logged already. + * + * The test is there to keep the Solaris compiler from complaining + * about "end-of-loop code not reached". */ #define FAIL(code) \ do { \ result = (code); \ - goto failure; \ + if (code != ISC_R_SUCCESS) goto failure; \ } while (0) /* * Fail unconditionally and log as a client error. + * The test against ISC_R_SUCCESS is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". */ #define FAILC(code, msg) \ do { \ @@ -115,11 +93,13 @@ isc_log_write(NOTIFY_PROTOCOL_LOGARGS, \ "notify failed: %s (%s)", \ msg, isc_result_totext(code)); \ - goto failure; \ + if (code != ISC_R_SUCCESS) goto failure; \ } while (0) /* * Fail unconditionally and log as a server error. + * The test against ISC_R_SUCCESS is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". */ #define FAILS(code, msg) \ do { \ @@ -127,7 +107,7 @@ isc_log_write(NOTIFY_PROTOCOL_LOGARGS, \ "notify error: %s: %s", \ msg, isc_result_totext(code)); \ - goto failure; \ + if (code != ISC_R_SUCCESS) goto failure; \ } while (0) /**************************************************************************/ @@ -166,7 +146,7 @@ ns_notify_start(ns_client_t *client) * Interpret the question section. */ result = dns_message_firstname(request, DNS_SECTION_QUESTION); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) FAILC(DNS_R_FORMERR, "notify question section empty"); @@ -183,12 +163,13 @@ ns_notify_start(ns_client_t *client) /* The zone section must have exactly one name. */ result = dns_message_nextname(request, DNS_SECTION_ZONE); - if (result != DNS_R_NOMORE) + if (result != ISC_R_NOMORE) FAILC(DNS_R_FORMERR, "notify question section contains multiple RRs"); - result = dns_zt_find(client->view->zonetable, zonename, NULL, &zone); - if (result != DNS_R_SUCCESS) + result = dns_zt_find(client->view->zonetable, zonename, 0, NULL, + &zone); + if (result != ISC_R_SUCCESS) FAILC(DNS_R_REFUSED, "not authoritative for notify zone"); @@ -202,8 +183,11 @@ ns_notify_start(ns_client_t *client) FAILC(DNS_R_REFUSED, "not authoritative for notify zone"); } + dns_zone_detach(&zone); return; failure: + if (zone != NULL) + dns_zone_detach(&zone); respond(client, result); } diff --git a/bin/named/omapi.c b/bin/named/omapi.c index 3107a029..09238b8a 100644 --- a/bin/named/omapi.c +++ b/bin/named/omapi.c @@ -15,19 +15,17 @@ * SOFTWARE. */ -/* $Id: omapi.c,v 1.10 2000/03/18 02:38:20 tale Exp $ */ +/* $Id: omapi.c,v 1.13 2000/05/08 14:32:57 tale Exp $ */ /* * Principal Author: DCL */ -#include <stdlib.h> -#include <stdarg.h> +#include <config.h> -#include <isc/assertions.h> +#include <isc/event.h> #include <isc/util.h> -#include <named/globals.h> #include <named/log.h> #include <named/omapi.h> #include <named/server.h> diff --git a/bin/named/query.c b/bin/named/query.c index 1a775d57..de0dc1bb 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -17,41 +17,26 @@ #include <config.h> -#include <isc/assertions.h> -#include <isc/buffer.h> #include <isc/mem.h> -#include <isc/mutex.h> -#include <isc/result.h> -#include <isc/task.h> -#include <isc/timer.h> -#include <isc/event.h> -#include <isc/log.h> #include <isc/util.h> -#include <dns/a6.h> -#include <dns/acl.h> #include <dns/db.h> -#include <dns/dbtable.h> -#include <dns/dispatch.h> #include <dns/events.h> -#include <dns/fixedname.h> #include <dns/message.h> -#include <dns/name.h> #include <dns/rdata.h> -#include <dns/rdatatype.h> #include <dns/rdatalist.h> #include <dns/rdataset.h> #include <dns/rdatasetiter.h> +#include <dns/rdatatype.h> #include <dns/resolver.h> -#include <dns/view.h> +#include <dns/result.h> #include <dns/tkey.h> +#include <dns/view.h> #include <dns/zone.h> #include <dns/zt.h> #include <named/client.h> -#include <named/globals.h> #include <named/log.h> -#include <named/query.h> #include <named/server.h> #include <named/xfrout.h> @@ -203,8 +188,7 @@ query_newnamebuf(ns_client_t *client) { */ dbuf = NULL; - result = isc_buffer_allocate(client->mctx, &dbuf, 1024, - ISC_BUFFERTYPE_BINARY); + result = isc_buffer_allocate(client->mctx, &dbuf, 1024); if (result != ISC_R_SUCCESS) { CTRACE("query_newnamebuf: isc_buffer_allocate failed: done"); return (result); @@ -237,7 +221,7 @@ query_getnamebuf(ns_client_t *client) { dbuf = ISC_LIST_TAIL(client->query.namebufs); INSIST(dbuf != NULL); - isc_buffer_available(dbuf, &r); + isc_buffer_availableregion(dbuf, &r); if (r.length < 255) { result = query_newnamebuf(client); if (result != ISC_R_SUCCESS) { @@ -246,7 +230,7 @@ query_getnamebuf(ns_client_t *client) { } dbuf = ISC_LIST_TAIL(client->query.namebufs); - isc_buffer_available(dbuf, &r); + isc_buffer_availableregion(dbuf, &r); INSIST(r.length >= 255); } CTRACE("query_getnamebuf: done"); @@ -308,8 +292,8 @@ query_newname(ns_client_t *client, isc_buffer_t *dbuf, CTRACE("query_newname: dns_message_gettempname failed: done"); return (NULL); } - isc_buffer_available(dbuf, &r); - isc_buffer_init(nbuf, r.base, r.length, ISC_BUFFERTYPE_BINARY); + isc_buffer_availableregion(dbuf, &r); + isc_buffer_init(nbuf, r.base, r.length); dns_name_init(name, NULL); dns_name_setbuffer(name, nbuf); client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED; @@ -342,7 +326,7 @@ query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) { CTRACE("query_putrdataset"); if (rdataset != NULL) { - if (rdataset->methods != NULL) + if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); dns_message_puttemprdataset(client->message, rdatasetp); } @@ -412,11 +396,12 @@ ns_query_init(ns_client_t *client) { return (query_newnamebuf(client)); } -static inline dns_dbversion_t * -query_findversion(ns_client_t *client, dns_db_t *db) { +static inline ns_dbversion_t * +query_findversion(ns_client_t *client, dns_db_t *db, + isc_boolean_t *newzonep) +{ ns_dbversion_t *dbversion; - CTRACE("query_findversion"); /* * We may already have done a query related to this * database. If so, we must be sure to make subsequent @@ -438,12 +423,129 @@ query_findversion(ns_client_t *client, dns_db_t *db) { return (NULL); dns_db_attach(db, &dbversion->db); dns_db_currentversion(db, &dbversion->version); + dbversion->queryok = ISC_FALSE; ISC_LIST_APPEND(client->query.activeversions, dbversion, link); - } + *newzonep = ISC_TRUE; + } else + *newzonep = ISC_FALSE; - CTRACE("query_findversion: done"); - return (dbversion->version); + return (dbversion); +} + +static inline isc_result_t +query_getdb(ns_client_t *client, dns_name_t *name, unsigned int options, + dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp, + isc_boolean_t *is_zonep) +{ + isc_result_t result; + isc_boolean_t check_acl, new_zone; + dns_acl_t *queryacl; + ns_dbversion_t *dbversion; + + /* + * Find a database to answer the query. + */ + + result = dns_zt_find(client->view->zonetable, name, options, NULL, + zonep); + if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { + result = dns_zone_getdb(*zonep, dbp); + *is_zonep = ISC_TRUE; + } + + if (result == ISC_R_NOTFOUND) { + if (!USECACHE(client)) + return (DNS_R_REFUSED); + dns_db_attach(client->view->cachedb, dbp); + *is_zonep = ISC_FALSE; + } else if (result != ISC_R_SUCCESS) + return (result); + + /* + * If we have a zone, and it has an ACL, we'll check it, otherwise + * we use the view's "allow-query" ACL. Each ACL is only checked + * once per query. + * + * Also, if we have a zone, we will get the version to use. + */ + + check_acl = ISC_TRUE; /* Keep compiler happy. */ + queryacl = NULL; + dbversion = NULL; + if (*is_zonep) { + /* + * Get the current version of this database. + */ + dbversion = query_findversion(client, *dbp, &new_zone); + if (dbversion == NULL) + return (DNS_R_SERVFAIL); + *versionp = dbversion->version; + if (new_zone) { + queryacl = dns_zone_getqueryacl(*zonep); + check_acl = ISC_TRUE; + } else if (!dbversion->queryok) + return (DNS_R_REFUSED); + else + check_acl = ISC_FALSE; + } else + *versionp = NULL; + + if (queryacl == NULL) { + queryacl = client->view->queryacl; + if ((client->query.attributes & + NS_QUERYATTR_QUERYOKVALID) != 0) { + /* + * We've evaluated the view's queryacl already. If + * NS_QUERYATTR_QUERYOK is set, then the client is + * allowed to make queries, otherwise the query should + * be refused. + */ + check_acl = ISC_FALSE; + if ((client->query.attributes & + NS_QUERYATTR_QUERYOK) == 0) + return (DNS_R_REFUSED); + } else { + /* + * We haven't evaluated the view's queryacl yet. + */ + check_acl = ISC_TRUE; + } + } + + if (check_acl) { + /* + * XXX RTH need a "should we log acl failure" flag. + */ + result = ns_client_checkacl(client, "query", queryacl, + ISC_TRUE); + if (queryacl == client->view->queryacl) { + if (result == ISC_R_SUCCESS) { + /* + * We were allowed by the default + * "allow-query" ACL. Remember this so we + * don't have to check again. + */ + client->query.attributes |= + NS_QUERYATTR_QUERYOK; + } + /* + * We've now evaluated the view's query ACL, and + * the NS_QUERYATTR_QUERYOK attribute is now valid. + */ + client->query.attributes |= NS_QUERYATTR_QUERYOKVALID; + } + } else + result = ISC_R_SUCCESS; + + /* + * Remember the result of the ACL check so we + * don't have to check again. + */ + if (dbversion != NULL && result == ISC_R_SUCCESS) + dbversion->queryok = ISC_TRUE; + + return (result); } static isc_result_t @@ -473,29 +575,10 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, */ zone = NULL; db = NULL; - result = dns_zt_find(client->view->zonetable, name, NULL, &zone); - if (result == DNS_R_SUCCESS || result == DNS_R_PARTIALMATCH) { - isc_result_t tresult; - tresult = dns_zone_getdb(zone, &db); - if (tresult != DNS_R_SUCCESS) - result = tresult; - } - - if (result == ISC_R_NOTFOUND && USECACHE(client)) - dns_db_attach(client->view->cachedb, &db); - else if (result != DNS_R_SUCCESS && result != DNS_R_PARTIALMATCH) - goto cleanup; - - /* - * Get the current version of this database. - */ version = NULL; - is_zone = dns_db_iszone(db); - if (is_zone) { - version = query_findversion(client, db); - if (version == NULL) - goto cleanup; - } + result = query_getdb(client, name, 0, &zone, &db, &version, &is_zone); + if (result != ISC_R_SUCCESS) + goto cleanup; db_find: /* @@ -508,12 +591,11 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, result = dns_db_find(db, name, version, type, dboptions, now, NULL, dns_fixedname_name(&foundname), rdataset, sigrdataset); - if (result == DNS_R_DELEGATION || - result == DNS_R_NOTFOUND) { - if (rdataset->methods != NULL) + result == ISC_R_NOTFOUND) { + if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); - if (sigrdataset->methods != NULL) + if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); if (is_zone) { if (USECACHE(client)) { @@ -532,9 +614,9 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, * We don't have the data in the cache. If we've got * glue from the zone, use it. */ - if (zrdataset.methods != NULL) { + if (dns_rdataset_isassociated(&zrdataset)) { dns_rdataset_clone(&zrdataset, rdataset); - if (zsigrdataset.methods != NULL) + if (dns_rdataset_isassociated(&zsigrdataset)) dns_rdataset_clone(&zsigrdataset, sigrdataset); result = ISC_R_SUCCESS; @@ -544,7 +626,7 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, /* * We don't know the answer. */ - result = DNS_R_NOTFOUND; + result = ISC_R_NOTFOUND; } else if (result == DNS_R_GLUE) { if (USECACHE(client) && RECURSIONOK(client)) { /* @@ -555,7 +637,7 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, version = NULL; dns_rdataset_clone(rdataset, &zrdataset); dns_rdataset_disassociate(rdataset); - if (sigrdataset->methods != NULL) { + if (dns_rdataset_isassociated(sigrdataset)) { dns_rdataset_clone(sigrdataset, &zsigrdataset); dns_rdataset_disassociate(sigrdataset); } @@ -568,17 +650,17 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, */ result = ISC_R_SUCCESS; } else if (result != ISC_R_SUCCESS) { - if (rdataset->methods != NULL) + if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); - if (sigrdataset->methods != NULL) + if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); - result = DNS_R_NOTFOUND; + result = ISC_R_NOTFOUND; } cleanup: - if (zrdataset.methods != NULL) { + if (dns_rdataset_isassociated(&zrdataset)) { dns_rdataset_disassociate(&zrdataset); - if (zsigrdataset.methods != NULL) + if (dns_rdataset_isassociated(&zsigrdataset)) dns_rdataset_disassociate(&zsigrdataset); } if (db != NULL) @@ -610,7 +692,7 @@ query_isduplicate(ns_client_t *client, dns_name_t *name, */ CTRACE("query_isduplicate: true: done"); return (ISC_TRUE); - } else if (result == DNS_R_NXRDATASET) { + } else if (result == DNS_R_NXRRSET) { /* * The name exists, but the rdataset does not. */ @@ -677,6 +759,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { added_something = ISC_FALSE; need_addname = ISC_FALSE; zone = NULL; + is_zone = ISC_FALSE; if (qtype == dns_rdatatype_a) type = dns_rdatatype_any; else @@ -685,27 +768,14 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { /* * Find a database to answer the query. */ - result = dns_zt_find(client->view->zonetable, name, NULL, &zone); - if (result == DNS_R_SUCCESS || result == DNS_R_PARTIALMATCH) { - isc_result_t tresult; - tresult = dns_zone_getdb(zone, &db); - if (tresult != DNS_R_SUCCESS) - result = tresult; - } - - if (result == ISC_R_NOTFOUND && USECACHE(client)) - dns_db_attach(client->view->cachedb, &db); - else if (result != DNS_R_SUCCESS && result != DNS_R_PARTIALMATCH) + result = query_getdb(client, name, 0, &zone, &db, &version, &is_zone); + if (result != ISC_R_SUCCESS) { + /* + * We don't want an ACL failure to fail the query. + */ + if (result == DNS_R_REFUSED) + result = ISC_R_SUCCESS; goto cleanup; - - /* - * Get the current version of this database. - */ - is_zone = dns_db_iszone(db); - if (is_zone) { - version = query_findversion(client, db); - if (version == NULL) - goto cleanup; } db_find: @@ -733,7 +803,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { client->now, &node, fname, rdataset, sigrdataset); - if (result == DNS_R_DELEGATION || result == DNS_R_NOTFOUND) { + if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) { if (is_zone) { if (USECACHE(client)) { /* @@ -809,7 +879,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { query_keepname(client, fname, dbuf); mname = NULL; - if (rdataset->methods != NULL && + if (dns_rdataset_isassociated(rdataset) && !query_isduplicate(client, fname, type, &mname)) { if (mname != NULL) { query_releasename(client, &fname); @@ -825,7 +895,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { * so we do not need to check if the SIG rdataset is already * in the response. */ - if (sigrdataset->methods != NULL) { + if (dns_rdataset_isassociated(sigrdataset)) { ISC_LIST_APPEND(fname->list, sigrdataset, link); sigrdataset = NULL; } @@ -842,7 +912,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { * XXXRTH This code could be more efficient. */ if (rdataset != NULL) { - if (rdataset->methods != NULL) + if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); } else { rdataset = query_newrdataset(client); @@ -850,7 +920,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { goto addname; } if (sigrdataset != NULL) { - if (sigrdataset->methods != NULL) + if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); } else { sigrdataset = query_newrdataset(client); @@ -868,7 +938,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { /* * Negative cache entries don't have sigrdatasets. */ - INSIST(sigrdataset->methods == NULL); + INSIST(! dns_rdataset_isassociated(sigrdataset)); } if (zdb != NULL && result == ISC_R_NOTFOUND) { /* @@ -892,7 +962,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { need_addname = ISC_TRUE; ISC_LIST_APPEND(fname->list, rdataset, link); added_something = ISC_TRUE; - if (sigrdataset->methods != NULL) { + if (dns_rdataset_isassociated(sigrdataset)) { ISC_LIST_APPEND(fname->list, sigrdataset, link); sigrdataset = @@ -903,7 +973,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { goto addname; } else { dns_rdataset_disassociate(rdataset); - if (sigrdataset->methods != NULL) + if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); } } @@ -915,7 +985,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { goto addname; if (result == DNS_R_NCACHENXRRSET) { dns_rdataset_disassociate(rdataset); - INSIST(sigrdataset->methods == NULL); + INSIST(! dns_rdataset_isassociated(sigrdataset)); } if (zdb != NULL && result == ISC_R_NOTFOUND) { /* @@ -940,7 +1010,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { a6rdataset = rdataset; ISC_LIST_APPEND(fname->list, rdataset, link); added_something = ISC_TRUE; - if (sigrdataset->methods != NULL) { + if (dns_rdataset_isassociated(sigrdataset)) { ISC_LIST_APPEND(fname->list, sigrdataset, link); sigrdataset = @@ -960,7 +1030,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { goto addname; if (result == DNS_R_NCACHENXRRSET) { dns_rdataset_disassociate(rdataset); - INSIST(sigrdataset->methods == NULL); + INSIST(! dns_rdataset_isassociated(sigrdataset)); } if (zdb != NULL && result == ISC_R_NOTFOUND) { /* @@ -984,7 +1054,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { need_addname = ISC_TRUE; ISC_LIST_APPEND(fname->list, rdataset, link); added_something = ISC_TRUE; - if (sigrdataset->methods != NULL) { + if (dns_rdataset_isassociated(sigrdataset)) { ISC_LIST_APPEND(fname->list, sigrdataset, link); sigrdataset = NULL; @@ -1117,7 +1187,7 @@ query_adda6rrset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset, if (dns_name_concatenate(name, NULL, fname, NULL) != ISC_R_SUCCESS) goto cleanup; dns_rdataset_clone(rdataset, crdataset); - if (sigrdataset->methods != NULL) + if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_clone(sigrdataset, csigrdataset); mname = NULL; @@ -1139,7 +1209,7 @@ query_adda6rrset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset, * we do not need to check if the SIG rdataset is already in the * response. */ - if (csigrdataset->methods != NULL) { + if (dns_rdataset_isassociated(csigrdataset)) { ISC_LIST_APPEND(fname->list, csigrdataset, link); csigrdataset = NULL; } @@ -1210,6 +1280,12 @@ query_addrrset(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset, *mrdataset, *sigrdataset; isc_result_t result; + /* + * If 'dbuf' is not NULL, then '*namep' is name whose data is + * stored in 'dbuf'. In this case, query_addrrset() guarantees that + * when it returns the name will either have been kept or released. + */ + CTRACE("query_addrrset"); name = *namep; rdataset = *rdatasetp; @@ -1228,6 +1304,8 @@ query_addrrset(ns_client_t *client, dns_name_t **namep, * There's nothing else to do; */ CTRACE("query_addrrset: dns_message_findname succeeded: done"); + if (dbuf != NULL) + query_releasename(client, namep); return; } else if (result == DNS_R_NXDOMAIN) { /* @@ -1238,8 +1316,11 @@ query_addrrset(ns_client_t *client, dns_name_t **namep, dns_message_addname(client->message, name, section); *namep = NULL; mname = name; - } else - RUNTIME_CHECK(result == DNS_R_NXRDATASET); + } else { + RUNTIME_CHECK(result == DNS_R_NXRRSET); + if (dbuf != NULL) + query_releasename(client, namep); + } /* * Note: we only add SIGs if we've added the type they cover, so @@ -1248,7 +1329,7 @@ query_addrrset(ns_client_t *client, dns_name_t **namep, */ query_addrdataset(client, mname, rdataset); *rdatasetp = NULL; - if (sigrdataset != NULL && sigrdataset->methods != NULL) { + if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { /* * We have a signature. Add it to the response. */ @@ -1471,38 +1552,17 @@ query_addbestns(ns_client_t *client) { zdb = NULL; version = NULL; zone = NULL; + is_zone = ISC_FALSE; use_zone = ISC_FALSE; /* * Find the right database. */ - result = dns_zt_find(client->view->zonetable, client->query.qname, - NULL, &zone); - if (result == DNS_R_SUCCESS || result == DNS_R_PARTIALMATCH) - result = dns_zone_getdb(zone, &db); - if (result == ISC_R_NOTFOUND) { - /* - * We're not directly authoritative for this query name, nor - * is it a subdomain of any zone for which we're - * authoritative. - */ - if (!USECACHE(client)) - goto cleanup; - INSIST(client->view->cachedb != NULL); - dns_db_attach(client->view->cachedb, &db); - } else if (result != ISC_R_SUCCESS) { - /* - * Something is broken. - */ + result = query_getdb(client, client->query.qname, 0, &zone, &db, + &version, &is_zone); + if (result != ISC_R_SUCCESS) goto cleanup; - } - is_zone = dns_db_iszone(db); - if (is_zone) { - version = query_findversion(client, db); - if (version == NULL) - goto cleanup; - } else - version = NULL; + db_find: /* * We'll need some resources... @@ -1581,6 +1641,10 @@ query_addbestns(ns_client_t *client) { zsigrdataset = NULL; } + if ((client->message->flags & DNS_MESSAGEFLAG_CD) == 0 && + rdataset->trust == dns_trust_pending) + goto cleanup; + query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, DNS_SECTION_AUTHORITY); @@ -1638,8 +1702,10 @@ query_resume(isc_task_t *task, isc_event_t *event) { * Resume a query after recursion. */ - REQUIRE(event->type == DNS_EVENT_FETCHDONE); - client = devent->arg; + UNUSED(task); + + REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE); + client = devent->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); REQUIRE(RECURSING(client)); @@ -1720,7 +1786,7 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, if (result == ISC_R_SUCCESS) result = ns_client_replace(client); if (result != ISC_R_SUCCESS) { - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT, + ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, "no more recursive clients: %s", isc_result_totext(result)); @@ -1768,6 +1834,88 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, return (result); } +static inline isc_result_t +query_findparentkey(ns_client_t *client, dns_name_t *name, + dns_zone_t **zonep, dns_db_t **dbp, + dns_dbversion_t **versionp, dns_dbnode_t **nodep, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) +{ + dns_db_t *pdb; + dns_dbnode_t *pnode; + dns_dbversion_t *pversion; + dns_rdataset_t prdataset, psigrdataset; + isc_result_t result; + dns_zone_t *pzone; + isc_boolean_t is_zone; + dns_fixedname_t pfoundname; + + /* + * 'name' is at a zone cut. Try to find a KEY for 'name' in + * the deepest ancestor zone of 'name' (if any). If it exists, + * update *zonep, *dbp, *nodep, rdataset, and sigrdataset and + * return ISC_R_SUCCESS. If not, leave them alone and return a + * non-success status. + */ + + pzone = NULL; + pdb = NULL; + pnode = NULL; + pversion = NULL; + dns_rdataset_init(&prdataset); + dns_rdataset_init(&psigrdataset); + is_zone = ISC_FALSE; + dns_fixedname_init(&pfoundname); + + result = query_getdb(client, name, DNS_ZTFIND_NOEXACT, + &pzone, &pdb, &pversion, &is_zone); + if (result != ISC_R_SUCCESS) + goto cleanup; + if (!is_zone) { + result = ISC_R_FAILURE; + goto cleanup; + } + + result = dns_db_find(pdb, name, pversion, dns_rdatatype_key, 0, + client->now, &pnode, + dns_fixedname_name(&pfoundname), + &prdataset, &psigrdataset); + if (result == ISC_R_SUCCESS) { + if (dns_rdataset_isassociated(rdataset)) + dns_rdataset_disassociate(rdataset); + if (dns_rdataset_isassociated(sigrdataset)) + dns_rdataset_disassociate(sigrdataset); + dns_rdataset_clone(&prdataset, rdataset); + if (dns_rdataset_isassociated(&psigrdataset)) + dns_rdataset_clone(&psigrdataset, sigrdataset); + if (*nodep != NULL) + dns_db_detachnode(*dbp, nodep); + *nodep = pnode; + pnode = NULL; + *versionp = pversion; + if (*dbp != NULL) + dns_db_detach(dbp); + *dbp = pdb; + pdb = NULL; + if (*zonep != NULL) + dns_zone_detach(zonep); + *zonep = pzone; + pzone = NULL; + } + + cleanup: + if (dns_rdataset_isassociated(&prdataset)) + dns_rdataset_disassociate(&prdataset); + if (dns_rdataset_isassociated(&psigrdataset)) + dns_rdataset_disassociate(&psigrdataset); + if (pnode != NULL) + dns_db_detachnode(pdb, &pnode); + if (pdb != NULL) + dns_db_detach(&pdb); + if (pzone != NULL) + dns_zone_detach(&pzone); + + return (result); +} #define MAX_RESTARTS 16 @@ -1787,7 +1935,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset; dns_rdata_t rdata; dns_rdatasetiter_t *rdsiter; - isc_boolean_t want_restart, authoritative, is_zone, clear_fname; + isc_boolean_t want_restart, authoritative, is_zone; unsigned int qcount, n, nlabels, nbits; dns_namereln_t namereln; int order; @@ -1798,7 +1946,6 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { dns_fixedname_t fixed; dns_dbversion_t *version; dns_zone_t *zone; - dns_acl_t *queryacl; CTRACE("query_find"); @@ -1830,7 +1977,6 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { want_restart = ISC_FALSE; authoritative = ISC_FALSE; - clear_fname = ISC_FALSE; is_zone = ISC_FALSE; qtype = event->qtype; @@ -1873,71 +2019,23 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { CTRACE("query_find: restart"); want_restart = ISC_FALSE; authoritative = ISC_FALSE; - clear_fname = ISC_FALSE; + version = NULL; /* * First we must find the right database. */ - result = dns_zt_find(client->view->zonetable, client->query.qname, - NULL, &zone); - if (result == DNS_R_SUCCESS || result == DNS_R_PARTIALMATCH) - result = dns_zone_getdb(zone, &db); - - if (result == ISC_R_NOTFOUND) { - /* - * We're not directly authoritative for this query name, nor - * is it a subdomain of any zone for which we're - * authoritative. - */ - if (!USECACHE(client)) { - /* - * If we can't use the cache, either because we - * don't have one or because its use has been - * disallowed, there's no more progress we can make - * on this query. - */ + result = query_getdb(client, client->query.qname, 0, &zone, &db, + &version, &is_zone); + if (result != ISC_R_SUCCESS) { + if (result == DNS_R_REFUSED) QUERY_ERROR(DNS_R_REFUSED); - goto cleanup; - } - INSIST(client->view->cachedb != NULL); - dns_db_attach(client->view->cachedb, &db); - } else if (result != ISC_R_SUCCESS) { - /* - * Something is broken. - */ - QUERY_ERROR(DNS_R_SERVFAIL); + else + QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } - is_zone = dns_db_iszone(db); - if (is_zone) { - authoritative = ISC_TRUE; - - /* - * Get the current version of this database. - */ - version = query_findversion(client, db); - if (version == NULL) { - QUERY_ERROR(DNS_R_SERVFAIL); - goto cleanup; - } - } else - version = NULL; - - queryacl = NULL; if (is_zone) - queryacl = dns_zone_getqueryacl(zone); - if (queryacl == NULL) - queryacl = ns_g_server->queryacl; - /* - * Check the query against the "allow-query" AMLs. - * XXX there should also be a per-view one. - */ - result = ns_client_checkacl(client, "query", queryacl, ISC_TRUE); - if (result != DNS_R_SUCCESS) { - QUERY_ERROR(result); - goto cleanup; - } + authoritative = ISC_TRUE; /* * Find the first unanswered type in the question section. @@ -2015,10 +2113,67 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { client->now, &node, fname, rdataset, sigrdataset); + /* + * We interrupt our normal query processing to bring you this special + * case... + * + * RFC 2535 (DNSSEC), section 2.3.4, discusses various special + * cases that can occur at delegation points. + * + * One of these cases is that the NULL KEY for an unsecure zone + * may occur in the delegating zone instead of in the delegated zone. + * If we're authoritative for both zones, we need to look for the + * key in the delegator if we didn't find it in the delegatee. If + * we didn't do this, a client doing DNSSEC validation could fail + * because it couldn't get the NULL KEY. + */ + if (type == dns_rdatatype_key && + is_zone && + result == DNS_R_NXRRSET && + !dns_db_issecure(db) && + dns_name_equal(client->query.qname, dns_db_origin(db))) { + /* + * We're looking for a KEY at the top of an unsecure zone, + * and we didn't find it. + */ + result = query_findparentkey(client, client->query.qname, + &zone, &db, &version, &node, + rdataset, sigrdataset); + if (result == ISC_R_SUCCESS) { + /* + * We found the parent KEY. + * + * zone, db, version, node, rdataset, and sigrdataset + * have all been updated to refer to the parent's + * data. We will resume query processing as if + * we had looked for the KEY in the parent zone in + * the first place. + * + * We need to set fname correctly. We do this here + * instead of in query_findparentkey() because + * dns_name_concatenate() can fail (though it shouldn't + * ever do so since we should have enough space). + */ + result = dns_name_concatenate(client->query.qname, + NULL, fname, NULL); + if (result != ISC_R_SUCCESS) { + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + } else { + /* + * We couldn't find the KEY in a parent zone. + * Continue with processing of the original + * results of dns_db_find(). + */ + result = DNS_R_NXRRSET; + } + } + resume: CTRACE("query_find: resume"); switch (result) { - case DNS_R_SUCCESS: + case ISC_R_SUCCESS: /* * This case is handled in the main line below. */ @@ -2031,7 +2186,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { INSIST(is_zone); authoritative = ISC_FALSE; break; - case DNS_R_NOTFOUND: + case ISC_R_NOTFOUND: /* * The cache doesn't even have the root NS. Get them from * the hints DB. @@ -2163,7 +2318,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { } } goto cleanup; - case DNS_R_NXRDATASET: + case DNS_R_NXRRSET: INSIST(is_zone); if (dns_rdataset_isassociated(rdataset)) { /* @@ -2363,8 +2518,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { prefix, NULL); if (result != ISC_R_SUCCESS) goto cleanup; - if (fname != NULL) - query_releasename(client, &fname); + INSIST(fname == NULL); dbuf = query_getnamebuf(client); if (dbuf == NULL) goto cleanup; @@ -2431,6 +2585,19 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } + /* + * Calling query_addrrset() with a non-NULL dbuf is going + * to either keep or release the name. We don't want it to + * release fname, since we may have to call query_addrrset() + * more than once. That means we have to call query_keepname() + * now, and pass a NULL dbuf to query_addrrset(). + * + * Since we've done the keepname, it's important that we + * set fname to NULL before we leave this 'if' block + * otherwise we might try to cleanup fname even though we've + * kept it! + */ + query_keepname(client, fname, dbuf); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, rdataset); @@ -2438,18 +2605,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { rdataset->type == qtype) && rdataset->type != 0) { tname = fname; query_addrrset(client, &tname, &rdataset, NULL, - dbuf, DNS_SECTION_ANSWER); + NULL, DNS_SECTION_ANSWER); n++; - if (tname == NULL) { - clear_fname = ISC_TRUE; - /* - * We set dbuf to NULL because we only - * want the query_keepname() call in - * query_addrrset() to be called once. - */ - dbuf = NULL; - } - /* * We shouldn't ever fail to add 'rdataset' * because it's already in the answer. @@ -2466,15 +2623,17 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { } result = dns_rdatasetiter_next(rdsiter); } - if (n > 0) { - if (clear_fname) - fname = NULL; - } else { + /* + * As mentioned above, we must now clear fname since we have + * kept it. + */ + fname = NULL; + if (n == 0) { /* * We didn't match any rdatasets. */ if (qtype == dns_rdatatype_sig && - result == DNS_R_NOMORE) { + result == ISC_R_NOMORE) { /* * XXXRTH If this is a secure zone and we * didn't find any SIGs, we should generate @@ -2485,16 +2644,13 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { * We were searching for SIG records in * a nonsecure zone. Send a "no error, * no data" response. - * - * First we must release fname. */ - query_releasename(client, &fname); /* * Add SOA. */ result = query_addsoa(client, db); if (result == ISC_R_SUCCESS) - result = DNS_R_NOMORE; + result = ISC_R_NOMORE; } else { /* * Something went wrong. @@ -2503,7 +2659,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { } } dns_rdatasetiter_destroy(&rdsiter); - if (result != DNS_R_NOMORE) { + if (result != ISC_R_NOMORE) { QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } @@ -2512,26 +2668,18 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { * This is the "normal" case -- an ordinary question to which * we know the answer. */ - tname = fname; - query_addrrset(client, &tname, &rdataset, &sigrdataset, dbuf, + query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, DNS_SECTION_ANSWER); - if (tname == NULL) - clear_fname = ISC_TRUE; - /* * We shouldn't ever fail to add 'rdataset' * because it's already in the answer. */ INSIST(rdataset == NULL); - /* * Remember that we've answered this question. */ client->query.qrdataset->attributes |= DNS_RDATASETATTR_ANSWERED; - - if (clear_fname) - fname = NULL; } addauth: @@ -2607,7 +2755,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { * response. */ if (client->message->rcode == dns_rcode_nxdomain && - ns_g_server->auth_nxdomain == ISC_TRUE) + client->view->auth_nxdomain == ISC_TRUE) client->message->flags |= DNS_MESSAGEFLAG_AA; ns_client_send(client); @@ -2616,45 +2764,23 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { CTRACE("query_find: done"); } -/* - * XXXRTH Problem areas. - * - * If we're authoritative for both a parent and a child, the - * child is non-secure, and we are asked for the KEY of the - * nonsecure child, we need to get it from the parent. - * If we're not auth for the parent, then we have to go - * looking for it in the cache. How do we even know who - * the parent is? We probably won't find this KEY when doing - * additional data KEY retrievals, but that's probably OK, - * since it's a SHOULD not a MUST. We don't want to be doing - * tons of work just to fill out additional data. - * - * Similar problems occur with NXT queries, since there can - * be NXT records at a delegation point in both the parent - * and the child. RFC 2535 section 5.5 says that on explicit - * query we should return both, if available. That seems - * to imply we shouldn't recurse to get the missing one - * if only one is available. Is that right? - */ - static inline void log_query(ns_client_t *client) { isc_buffer_t b; - char text[1024]; + char namebuf[1024]; + char text[256]; isc_region_t r; dns_rdataset_t *rdataset; /* XXXRTH Allow this to be turned off! */ - isc_buffer_init(&b, (unsigned char *)text, sizeof text, - ISC_BUFFERTYPE_TEXT); - if (dns_name_totext(client->query.qname, ISC_TRUE, &b) != - ISC_R_SUCCESS) - return; + dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); + + isc_buffer_init(&b, (unsigned char *)text, sizeof(text)); for (rdataset = ISC_LIST_HEAD(client->query.qname->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { - isc_buffer_available(&b, &r); + isc_buffer_availableregion(&b, &r); if (r.length < 1) return; *r.base = ' '; @@ -2662,9 +2788,9 @@ log_query(ns_client_t *client) { if (dns_rdatatype_totext(rdataset->type, &b) != ISC_R_SUCCESS) return; } - isc_buffer_used(&b, &r); - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_QUERY, - ISC_LOG_DEBUG(1), "query: %.*s", + isc_buffer_usedregion(&b, &r); + ns_client_log(client, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_QUERY, + ISC_LOG_DEBUG(1), "query: %s%.*s", namebuf, (int)r.length, (char *)r.base); } diff --git a/bin/named/server.c b/bin/named/server.c index dea952f2..6df21523 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -17,61 +17,40 @@ #include <config.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <stdio.h> #include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <stdarg.h> #include <isc/app.h> -#include <isc/assertions.h> +#include <isc/base64.h> #include <isc/dir.h> -#include <isc/error.h> -#include <isc/mem.h> -#include <isc/result.h> -#include <isc/rwlock.h> -#include <isc/socket.h> +#include <isc/lex.h> +#include <isc/string.h> #include <isc/task.h> -#include <isc/thread.h> #include <isc/timer.h> #include <isc/util.h> -#include <dns/acl.h> -#include <dns/aclconf.h> #include <dns/cache.h> -#include <dns/confacl.h> -#include <dns/confctx.h> -#include <dns/confip.h> #include <dns/confparser.h> #include <dns/db.h> #include <dns/dispatch.h> -#include <dns/fixedname.h> #include <dns/journal.h> -#include <dns/master.h> -#include <dns/name.h> -#include <dns/rdata.h> +#include <dns/keytable.h> +#include <dns/peer.h> +#include <dns/rdatastruct.h> #include <dns/resolver.h> -#include <dns/result.h> #include <dns/rootns.h> +#include <dns/tkey.h> #include <dns/tkeyconf.h> #include <dns/tsigconf.h> -#include <dns/types.h> #include <dns/view.h> #include <dns/zone.h> #include <dns/zoneconf.h> #include <named/client.h> -#include <named/globals.h> #include <named/interfacemgr.h> -#include <named/listenlist.h> #include <named/log.h> #include <named/logconf.h> #include <named/os.h> #include <named/server.h> -#include <named/types.h> /* * Check an operation for failure. Assumes that the function @@ -120,11 +99,269 @@ ns_listenlist_fromconfig(dns_c_lstnlist_t *clist, dns_c_ctx_t *cctx, isc_mem_t *mctx, ns_listenlist_t **target); /* - * Configure 'view' according to 'cctx'. + * Configure a single view ACL at '*aclp'. Get its configuration by + * calling 'getvcacl' (for per-view configuration) and maybe 'getscacl' + * (for a global default). */ static isc_result_t -configure_view(dns_view_t *view, dns_c_ctx_t *cctx, isc_mem_t *mctx, - dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6) +configure_view_acl(dns_c_view_t *cview, + dns_c_ctx_t *cctx, + dns_aclconfctx_t *actx, isc_mem_t *mctx, + isc_result_t (*getvcacl) + (dns_c_view_t *, dns_c_ipmatchlist_t **), + isc_result_t (*getscacl) + (dns_c_ctx_t *, dns_c_ipmatchlist_t **), + dns_acl_t **aclp) +{ + isc_result_t result; + + dns_c_ipmatchlist_t *cacl = NULL; + if (*aclp != NULL) + dns_acl_detach(aclp); + if (getvcacl != NULL && cview != NULL) + (void) (*getvcacl)(cview, &cacl); + if (cacl == NULL && getscacl != NULL) + (void) (*getscacl)(cctx, &cacl); + if (cacl == NULL) { + /* No value available. *aclp == NULL. */ + return (ISC_R_SUCCESS); + } + + result = dns_acl_fromconfig(cacl, cctx, actx, mctx, aclp); + + dns_c_ipmatchlist_detach(&cacl); + + return (result); +} + + +/* + * Convert a null-terminated string of base64 text into + * binary, storing it in a buffer. + * 'mctx' is only used internally. + */ +static isc_result_t +base64_cstring_tobuffer(isc_mem_t *mctx, char *cstr, isc_buffer_t *target) +{ + isc_result_t result; + isc_buffer_t source; + isc_lex_t *lex = NULL; + isc_boolean_t isopen = ISC_FALSE; + + isc_buffer_init(&source, cstr, strlen(cstr)); + isc_buffer_add(&source, strlen(cstr)); + CHECK(isc_lex_create(mctx, 256, &lex)); + CHECK(isc_lex_openbuffer(lex, &source)); + isopen = ISC_TRUE; + CHECK(isc_base64_tobuffer(lex, target, -1)); + + cleanup: + if (isopen) + (void) isc_lex_close(lex); + if (lex != NULL) + isc_lex_destroy(&lex); + return (result); +} + +/* + * Configure the trusted keys or security roots of a view. + * The configuration values are read from 'cctx' and 'cview' using + * the function 'cget'. The variable to be configured is '*target'. + * XXX not really view specific yet + */ +static isc_result_t +configure_view_dnsseckeys(dns_c_ctx_t *cctx, + dns_c_view_t *cview, + isc_mem_t *mctx, + isc_result_t (*cget) + (dns_c_ctx_t *, dns_c_tkeylist_t **), + dns_keytable_t **target) +{ + isc_result_t result; + dns_c_tkeylist_t *ckeys = NULL; + dns_c_tkey_t *ckey; + dns_keytable_t *keytable = NULL; + dst_key_t *dstkey = NULL; + + CHECK(dns_keytable_create(mctx, &keytable)); + + result = (*cget)(cctx, &ckeys); + if (result == ISC_R_SUCCESS) { + for (ckey = ISC_LIST_HEAD(ckeys->tkeylist); + ckey != NULL; + ckey = ISC_LIST_NEXT(ckey, next)) + { + dns_rdataclass_t viewclass; + dns_rdata_key_t keystruct; + isc_int32_t flags, proto, alg; + unsigned char keydata[4096]; + isc_buffer_t keydatabuf; + unsigned char rrdata[4096]; + isc_buffer_t rrdatabuf; + isc_region_t r; + + if (cview == NULL) + viewclass = dns_rdataclass_in; + else + CHECK(dns_c_view_getviewclass(cview, + &viewclass)); + keystruct.common.rdclass = viewclass; + keystruct.common.rdtype = dns_rdatatype_key; + /* + * The key data in keystruct is not + * dynamically allocated. + */ + keystruct.mctx = NULL; + + ISC_LINK_INIT(&keystruct.common, link); + + flags = ckey->pubkey->flags; + proto = ckey->pubkey->protocol; + alg = ckey->pubkey->algorithm; + if (flags < 0 || flags > 0xffff) + CHECKM(ISC_R_RANGE, "key flags"); + if (proto < 0 || proto > 0xff) + CHECKM(ISC_R_RANGE, "key protocol"); + if (alg < 0 || alg > 0xff) + CHECKM(ISC_R_RANGE, "key algorithm"); + keystruct.flags = flags; + keystruct.protocol = proto; + keystruct.algorithm = alg; + + isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + + CHECK(base64_cstring_tobuffer(mctx, ckey->pubkey->key, + &keydatabuf)); + isc_buffer_usedregion(&keydatabuf, &r); + keystruct.datalen = r.length; + keystruct.data = r.base; + + CHECK(dns_rdata_fromstruct(NULL, + keystruct.common.rdclass, + keystruct.common.rdtype, + &keystruct, &rrdatabuf)); + CHECK(dst_key_fromdns(ckey->domain, &rrdatabuf, mctx, + &dstkey)); + + CHECK(dns_keytable_add(keytable, &dstkey)); + INSIST(dstkey == NULL); + } + } else if (result != ISC_R_NOTFOUND) + goto cleanup; + + dns_keytable_detach(target); + *target = keytable; /* Transfer ownership. */ + keytable = NULL; + result = ISC_R_SUCCESS; + + cleanup: + if (dstkey != NULL) + dst_key_free(&dstkey); + return (result); +} + + +/* + * Get a dispatch appropriate for the resolver of a given view. + */ +static isc_result_t +get_view_querysource_dispatch(dns_c_ctx_t *cctx, dns_c_view_t *cview, + int af, dns_dispatch_t **dispatchp) +{ + isc_result_t result; + dns_dispatch_t *disp; + isc_sockaddr_t sa; + unsigned int attrs, attrmask; + + /* + * Make compiler happy. + */ + result = ISC_R_FAILURE; + + switch (af) { + case AF_INET: + result = ISC_R_NOTFOUND; + if (cview != NULL) + result = dns_c_view_getquerysource(cview, &sa); + if (result != ISC_R_SUCCESS) + result = dns_c_ctx_getquerysource(cctx, &sa); + if (result != ISC_R_SUCCESS) + isc_sockaddr_any(&sa); + break; + case AF_INET6: + result = ISC_R_NOTFOUND; + if (cview != NULL) + result = dns_c_view_getquerysourcev6(cview, &sa); + if (result != ISC_R_SUCCESS) + result = dns_c_ctx_getquerysourcev6(cctx, &sa); + if (result != ISC_R_SUCCESS) + isc_sockaddr_any6(&sa); + break; + default: + INSIST(0); + } + + INSIST(isc_sockaddr_pf(&sa) == af); + + /* + * If we don't support this address family, we're done! + */ + switch (af) { + case AF_INET: + result = isc_net_probeipv4(); + break; + case AF_INET6: + result = isc_net_probeipv6(); + break; + default: + INSIST(0); + } + if (result != ISC_R_SUCCESS) + return (ISC_R_SUCCESS); + + /* + * Try to find a dispatcher that we can share. + */ + attrs = 0; + attrs |= DNS_DISPATCHATTR_UDP; + switch (af) { + case AF_INET: + attrs |= DNS_DISPATCHATTR_IPV4; + break; + case AF_INET6: + attrs |= DNS_DISPATCHATTR_IPV6; + break; + } + attrmask = 0; + attrmask |= DNS_DISPATCHATTR_UDP; + attrmask |= DNS_DISPATCHATTR_TCP; + attrmask |= DNS_DISPATCHATTR_IPV4; + attrmask |= DNS_DISPATCHATTR_IPV6; + + disp = NULL; + result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, + ns_g_taskmgr, &sa, 4096, + 1000, 32768, 16411, 16433, + attrs, attrmask, &disp); + if (result != ISC_R_SUCCESS) + return (result); + + *dispatchp = disp; + + return (ISC_R_SUCCESS); +} + +/* + * Configure 'view' according to 'cview', taking defaults from 'cctx' + * where values are missing in cctx. + * + * When configuring the default view, cctx will be NULL and the + * glboal defaults in cview used exclusively. + */ +static isc_result_t +configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview, + isc_mem_t *mctx, dns_aclconfctx_t *actx) { dns_cache_t *cache = NULL; isc_result_t result; @@ -137,10 +374,14 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, isc_mem_t *mctx, isc_sockaddr_t *sa, *next_sa; dns_view_t *pview = NULL; /* Production view */ unsigned int i; + isc_mem_t *cmctx; + dns_dispatch_t *dispatch4 = NULL; + dns_dispatch_t *dispatch6 = NULL; REQUIRE(DNS_VIEW_VALID(view)); ISC_LIST_INIT(addresses); + cmctx = NULL; RWLOCK(&view->conflock, isc_rwlocktype_write); @@ -170,13 +411,22 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, isc_mem_t *mctx, dns_cache_attach(pview->cache, &cache); dns_view_detach(&pview); } else { - CHECK(dns_cache_create(mctx, ns_g_taskmgr, ns_g_timermgr, + CHECK(isc_mem_create(0, 0, &cmctx)); + CHECK(dns_cache_create(cmctx, ns_g_taskmgr, ns_g_timermgr, view->rdclass, "rbt", 0, NULL, &cache)); } dns_view_setcache(view, cache); - cleaning_interval = 3600; /* Default is 1 hour. */ - (void) dns_c_ctx_getcleaninterval(cctx, &cleaning_interval); + + result = ISC_R_NOTFOUND; + if (cview != NULL) + result = dns_c_view_getcleaninterval(cview, + &cleaning_interval); + if (result != ISC_R_SUCCESS) + result = dns_c_ctx_getcleaninterval(cctx, &cleaning_interval); + if (result != ISC_R_SUCCESS) + cleaning_interval = 3600; /* Default is 1 hour. */ dns_cache_setcleaninginterval(cache, cleaning_interval); + dns_cache_detach(&cache); /* @@ -195,14 +445,26 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, isc_mem_t *mctx, * * XXXRTH Hardwired number of tasks. */ + CHECK(get_view_querysource_dispatch(cctx, cview, AF_INET, + &dispatch4)); + CHECK(get_view_querysource_dispatch(cctx, cview, AF_INET6, + &dispatch6)); CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31, ns_g_socketmgr, ns_g_timermgr, - 0, dispatchv4, dispatchv6)); + 0, ns_g_dispatchmgr, + dispatch4, dispatch6)); + if (dispatch4 != NULL) + dns_dispatch_detach(&dispatch4); + if (dispatch6 != NULL) + dns_dispatch_detach(&dispatch6); /* * Set resolver forwarding policy. */ - if (dns_c_ctx_getforwarders(cctx, &forwarders) == ISC_R_SUCCESS) { + if ((cview != NULL && + dns_c_view_getforwarders(cview, &forwarders) == ISC_R_SUCCESS) || + (dns_c_ctx_getforwarders(cctx, &forwarders) == ISC_R_SUCCESS)) + { fwdpolicy = dns_fwdpolicy_first; /* * Ugh. Convert between list formats. @@ -225,7 +487,9 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, isc_mem_t *mctx, * XXXRTH The configuration type 'dns_c_forw_t' should be * elminated. */ - if (dns_c_ctx_getforward(cctx, &forward) == ISC_R_SUCCESS) { + if ((cview != NULL && + dns_c_view_getforward(cview, &forward) == ISC_R_SUCCESS) || + (dns_c_ctx_getforward(cctx, &forward) == ISC_R_SUCCESS)) { INSIST(forward == dns_c_forw_first || forward == dns_c_forw_only); if (forward == dns_c_forw_only) @@ -238,9 +502,22 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, isc_mem_t *mctx, * We have default hints for class IN if we need them. */ if (view->rdclass == dns_rdataclass_in && view->hints == NULL) - dns_view_sethints(view, ns_g_server->roothints); + dns_view_sethints(view, ns_g_server->in_roothints); /* + * If we still have no hints, this is a non-IN view with no + * "hints zone" configured. That's an error. + */ + if (view->hints == NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "no root hints for view '%s'", + cview == NULL ? "<default>" : cview->name); + result = ISC_R_FAILURE; + goto cleanup; + } + + /* * Configure the view's TSIG keys. */ ring = NULL; @@ -260,7 +537,69 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, isc_mem_t *mctx, dns_peerlist_detach(&view->peers); view->peers = newpeers; /* Transfer ownership. */ } + + /* + * Configure the "match-clients" ACL. + */ + CHECK(configure_view_acl(cview, cctx, actx, ns_g_mctx, + dns_c_view_getmatchclients, NULL, + &view->matchclients)); + + /* + * Configure other configurable data. + */ + view->recursion = ISC_TRUE; + (void) dns_c_ctx_getrecursion(cctx, &view->recursion); + if (cview != NULL) + (void) dns_c_view_getrecursion(cview, &view->recursion); + + view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */ + (void) dns_c_ctx_getauthnxdomain(cctx, &view->auth_nxdomain); + if (cview != NULL) + (void) dns_c_view_getauthnxdomain(cview, &view->auth_nxdomain); + + view->transfer_format = dns_one_answer; + (void) dns_c_ctx_gettransferformat(cctx, &view->transfer_format); + if (cview != NULL) + (void) dns_c_view_gettransferformat(cview, + &view->transfer_format); + + CHECK(configure_view_acl(cview, cctx, actx, ns_g_mctx, + dns_c_view_getallowquery, + dns_c_ctx_getallowquery, + &view->queryacl)); + CHECK(configure_view_acl(cview, cctx, actx, ns_g_mctx, + dns_c_view_getrecursionacl, + dns_c_ctx_getallowrecursion, + &view->recursionacl)); + + result = ISC_R_NOTFOUND; + if (cview != NULL) + result = dns_c_view_getrequestixfr(cview, &view->requestixfr); + if (result != ISC_R_SUCCESS) + result = dns_c_ctx_getrequestixfr(cctx, &view->requestixfr); + if (result != ISC_R_SUCCESS) + view->requestixfr = ISC_TRUE; + + result = ISC_R_NOTFOUND; + if (cview != NULL) + result = dns_c_view_getprovideixfr(cview, &view->provideixfr); + if (result != ISC_R_SUCCESS) + result = dns_c_ctx_getprovideixfr(cctx, &view->provideixfr); + if (result != ISC_R_SUCCESS) + view->provideixfr = ISC_TRUE; + + /* + * For now, there is only one kind of trusted keys, the + * "security roots". + */ + CHECK(configure_view_dnsseckeys(cctx, cview, mctx, + dns_c_ctx_gettrustedkeys, + &view->secroots)); + + result = ISC_R_SUCCESS; + cleanup: RWUNLOCK(&view->conflock, isc_rwlocktype_write); @@ -271,17 +610,21 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, isc_mem_t *mctx, isc_mem_put(view->mctx, sa, sizeof *sa); } + if (cmctx != NULL) + isc_mem_detach(&cmctx); + return (result); } /* * Create the special view that handles queries for * "version.bind. CH". The version string returned is that - * configured in 'configctx', or a compiled-in default if + * configured in 'cctx', or a compiled-in default if * there is no "version" configuration option. */ static isc_result_t -create_version_view(dns_c_ctx_t *configctx, dns_view_t **viewp) { +create_version_view(dns_c_ctx_t *cctx, dns_zonemgr_t *zmgr, dns_view_t **viewp) +{ isc_result_t result; dns_db_t *db = NULL; dns_zone_t *zone = NULL; @@ -299,6 +642,9 @@ create_version_view(dns_c_ctx_t *configctx, dns_view_t **viewp) { REQUIRE(viewp != NULL && *viewp == NULL); + CHECK(dns_view_create(ns_g_mctx, dns_rdataclass_ch, "_version", + &view)); + dns_diff_init(ns_g_mctx, &diff); dns_name_init(&origin, NULL); @@ -306,8 +652,8 @@ create_version_view(dns_c_ctx_t *configctx, dns_view_t **viewp) { r.length = sizeof(origindata); dns_name_fromregion(&origin, &r); - (void) dns_c_ctx_getversion(configctx, &versiontext); - if (versiontext == NULL) + result = dns_c_ctx_getversion(cctx, &versiontext); + if (result != ISC_R_SUCCESS) versiontext = ns_g_version; len = strlen(versiontext); if (len > 255) @@ -321,6 +667,10 @@ create_version_view(dns_c_ctx_t *configctx, dns_view_t **viewp) { CHECK(dns_zone_create(&zone, ns_g_mctx)); CHECK(dns_zone_setorigin(zone, &origin)); + dns_zone_setclass(zone, dns_rdataclass_ch); + dns_zone_setview(zone, view); + + CHECK(dns_zonemgr_managezone(zmgr, zone)); CHECK(dns_db_create(ns_g_mctx, "rbt", &origin, ISC_FALSE, dns_rdataclass_ch, 0, NULL, &db)); @@ -334,9 +684,6 @@ create_version_view(dns_c_ctx_t *configctx, dns_view_t **viewp) { dns_db_closeversion(db, &dbver, ISC_TRUE); - CHECK(dns_view_create(ns_g_mctx, dns_rdataclass_ch, "_version", - &view)); - CHECK(dns_zone_replacedb(zone, db, ISC_FALSE)); CHECK(dns_view_addzone(view, zone)); @@ -379,6 +726,51 @@ configure_hints(dns_view_t *view, const char *filename) { } /* + * Find an existing view matching the name and class of 'cview' + * in 'viewlist', or create a new one and add it to the list. + * + * If 'cview' is NULL, find or create the default view. + * + * The view found or created is attached to '*viewp'. + */ +static isc_result_t +find_or_create_view(dns_c_view_t *cview, dns_viewlist_t *viewlist, + dns_view_t **viewp) +{ + isc_result_t result; + char *viewname; + dns_rdataclass_t viewclass; + dns_view_t *view = NULL; + + if (cview != NULL) { + viewname = cview->name; + result = dns_c_view_getviewclass(cview, &viewclass); + if (result != ISC_R_SUCCESS) + return (result); + } else { + viewname = "_default"; + viewclass = dns_rdataclass_in; + } + result = dns_viewlist_find(viewlist, viewname, + viewclass, &view); + if (result == ISC_R_SUCCESS) { + *viewp = view; + return (ISC_R_SUCCESS); + } + if (result != ISC_R_NOTFOUND) + return (result); + INSIST(view == NULL); + + result = dns_view_create(ns_g_mctx, viewclass, viewname, &view); + if (result != ISC_R_SUCCESS) + return (result); + + ISC_LIST_APPEND(*viewlist, view, link); + dns_view_attach(view, viewp); + return (ISC_R_SUCCESS); +} + +/* * Configure or reconfigure a zone. This callback function * is called after parsing each "zone" statement in named.conf. */ @@ -390,8 +782,7 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, dns_view_t *view = NULL; /* New view */ dns_view_t *pview = NULL; /* Production view */ dns_zone_t *zone = NULL; /* New or reused zone */ - dns_zone_t *tzone = NULL; /* Temporary zone */ - char *viewname; + dns_zone_t *dupzone = NULL; isc_result_t result; @@ -406,8 +797,7 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, corigin = NULL; /* XXX casting away const */ CHECK(dns_c_zone_getname(czone, (const char **) &corigin)); - isc_buffer_init(&buffer, corigin, strlen(corigin), - ISC_BUFFERTYPE_TEXT); + isc_buffer_init(&buffer, corigin, strlen(corigin)); isc_buffer_add(&buffer, strlen(corigin)); dns_fixedname_init(&fixorigin); CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), @@ -418,22 +808,17 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, * Find or create the view in the new view list. */ view = NULL; - if (cview != NULL) - viewname = cview->name; - else - viewname = "_default"; - result = dns_viewlist_find(&lctx->viewlist, viewname, - czone->zclass, &view); - if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) + CHECK(find_or_create_view(cview, &lctx->viewlist, &view)); + + if (czone->zclass != view->rdclass) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "zone '%s': wrong class for view '%s'", + corigin, cview ? cview->name : "<default view>"); + result = ISC_R_FAILURE; goto cleanup; - if (view == NULL) { - dns_view_t *tview = NULL; - CHECK(dns_view_create(ns_g_mctx, czone->zclass, - viewname, &view)); - dns_view_attach(view, &tview); - ISC_LIST_APPEND(lctx->viewlist, tview, link); } - + /* * Master zones must have 'file' set. */ @@ -503,14 +888,16 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, /* * Check for duplicates in the new zone table. */ - result = dns_view_findzone(view, origin, &tzone); + result = dns_view_findzone(view, origin, &dupzone); if (result == ISC_R_SUCCESS) { /* * We already have this zone! */ + dns_zone_detach(&dupzone); result = ISC_R_EXISTS; goto cleanup; } + INSIST(dupzone == NULL); /* * See if we can reuse an existing zone. This is @@ -535,21 +922,27 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, dns_zone_detach(&zone); } - /* - * If we cannot reuse an existing zone, we will have to - * create a new one. - */ - if (zone == NULL) { + if (zone != NULL) { + /* + * We found a reusable zone. Make it use the + * new view. + */ + dns_zone_setview(zone, view); + } else { + /* + * We cannot reuse an existing zone, we have + * to create a new one. + */ CHECK(dns_zone_create(&zone, lctx->mctx)); CHECK(dns_zone_setorigin(zone, origin)); - CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, - zone)); + dns_zone_setview(zone, view); + CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); } /* * Configure the zone. */ - CHECK(dns_zone_configure(cctx, lctx->aclconf, czone, zone)); + CHECK(dns_zone_configure(cctx, cview, czone, lctx->aclconf, zone)); /* * Add the zone to its view in the new view list. @@ -557,8 +950,6 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, CHECK(dns_view_addzone(view, zone)); cleanup: - if (tzone != NULL) - dns_zone_detach(&tzone); if (zone != NULL) dns_zone_detach(&zone); if (pview != NULL) @@ -570,27 +961,6 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview, } /* - * Configure a single server ACL at '*aclp'. Get its configuration by - * calling 'getacl'. - */ -static isc_result_t -configure_server_acl(dns_c_ctx_t *cctx, dns_aclconfctx_t *actx, isc_mem_t *mctx, - isc_result_t (*getcacl)(dns_c_ctx_t *, dns_c_ipmatchlist_t **), - dns_acl_t **aclp) -{ - isc_result_t result = ISC_R_SUCCESS; - dns_c_ipmatchlist_t *cacl = NULL; - if (*aclp != NULL) - dns_acl_detach(aclp); - (void) (*getcacl)(cctx, &cacl); - if (cacl != NULL) { - result = dns_acl_fromconfig(cacl, cctx, actx, mctx, aclp); - dns_c_ipmatchlist_detach(&cacl); - } - return (result); -} - -/* * Configure a single server quota. */ static void @@ -603,150 +973,6 @@ configure_server_quota(dns_c_ctx_t *cctx, quota->max = val; } -static isc_result_t -configure_server_querysource(dns_c_ctx_t *cctx, ns_server_t *server, int af, - dns_dispatch_t **dispatchp) { - isc_result_t result; - struct in_addr ina; - isc_sockaddr_t sa, any4, any6, *any; - isc_socket_t *socket; - dns_dispatch_t **server_dispatchp; - isc_sockaddr_t *server_dispatchaddr; - - /* - * Make compiler happy. - */ - result = ISC_R_FAILURE; - any = NULL; - server_dispatchp = NULL; - server_dispatchaddr = NULL; - - ina.s_addr = htonl(INADDR_ANY); - isc_sockaddr_fromin(&any4, &ina, 0); - isc_sockaddr_fromin6(&any6, &in6addr_any, 0); - - *dispatchp = NULL; - - switch (af) { - case AF_INET: - any = &any4; - result = dns_c_ctx_getquerysource(cctx, &sa); - break; - case AF_INET6: - any = &any6; - result = dns_c_ctx_getquerysourcev6(cctx, &sa); - break; - default: - INSIST(0); - } - if (result != ISC_R_SUCCESS) - sa = *any; - - INSIST(isc_sockaddr_pf(&sa) == af); - - /* - * If we don't support this address family, we're done! - */ - switch (af) { - case AF_INET: - result = isc_net_probeipv4(); - break; - case AF_INET6: - result = isc_net_probeipv6(); - break; - default: - INSIST(0); - } - if (result != ISC_R_SUCCESS) - return (ISC_R_SUCCESS); - - if (isc_sockaddr_equal(&sa, any)) { - /* - * The query source is fully wild. No special dispatcher - * work needs to be done. - */ - return (ISC_R_SUCCESS); - } - - /* - * If the interface manager has a dispatcher for this address, - * use it. - */ - switch (af) { - case AF_INET: - server_dispatchp = &server->querysrc_dispatchv4; - server_dispatchaddr = &server->querysrc_addressv4; - break; - case AF_INET6: - server_dispatchp = &server->querysrc_dispatchv6; - server_dispatchaddr = &server->querysrc_addressv6; - break; - default: - INSIST(0); - } - if (ns_interfacemgr_findudpdispatcher(server->interfacemgr, &sa, - dispatchp) != - ISC_R_SUCCESS) { - /* - * The interface manager doesn't have a matching dispatcher. - */ - if (*server_dispatchp != NULL) { - /* - * We've already got a custom dispatcher. If it is - * compatible with the new configuration, use it. - */ - if (isc_sockaddr_equal(server_dispatchaddr, - &sa)) { - dns_dispatch_attach(*server_dispatchp, - dispatchp); - return (ISC_R_SUCCESS); - } - /* - * The existing custom dispatcher is not compatible. - * We don't need it anymore. - */ - dns_dispatch_detach(server_dispatchp); - } - /* - * Create a custom dispatcher. - */ - INSIST(*server_dispatchp == NULL); - *server_dispatchaddr = sa; - socket = NULL; - result = isc_socket_create(ns_g_socketmgr, af, - isc_sockettype_udp, - &socket); - if (result != ISC_R_SUCCESS) - return (result); - result = isc_socket_bind(socket, &sa); - if (result != ISC_R_SUCCESS) { - isc_socket_detach(&socket); - return (result); - } - result = dns_dispatch_create(ns_g_mctx, socket, - server->task, 4096, - 1000, 32768, 16411, 16433, NULL, - server_dispatchp); - /* - * Regardless of whether dns_dispatch_create() succeeded or - * failed, we don't need to keep the reference to the socket. - */ - isc_socket_detach(&socket); - if (result != ISC_R_SUCCESS) - return (result); - dns_dispatch_attach(*server_dispatchp, dispatchp); - } else { - /* - * We're sharing a UDP dispatcher with the interface manager - * now. Any prior custom dispatcher can be discarded. - */ - if (*server_dispatchp != NULL) - dns_dispatch_detach(server_dispatchp); - } - - return (ISC_R_SUCCESS); -} - /* * This function is called as soon as the 'options' statement has been * parsed. @@ -791,7 +1017,7 @@ scan_interfaces(ns_server_t *server) { */ static void interface_timer_tick(isc_task_t *task, isc_event_t *event) { - ns_server_t *server = (ns_server_t *) event->arg; + ns_server_t *server = (ns_server_t *) event->ev_arg; UNUSED(task); isc_event_free(&event); RWLOCK(&server->conflock, isc_rwlocktype_write); @@ -806,8 +1032,9 @@ load_configuration(const char *filename, ns_server_t *server, isc_result_t result; ns_load_t lctx; dns_c_cbks_t callbacks; - dns_c_ctx_t *configctx; - dns_view_t *view, *view_next; + dns_c_ctx_t *cctx; + dns_view_t *view = NULL; + dns_view_t *view_next; dns_viewlist_t tmpviewlist; dns_aclconfctx_t aclconfctx; dns_dispatch_t *dispatchv4 = NULL; @@ -838,54 +1065,33 @@ load_configuration(const char *filename, ns_server_t *server, * 'zone' statements are handled immediately by calling * configure_zone() through 'callbacks'. */ - configctx = NULL; - CHECK(dns_c_parse_namedconf(filename, ns_g_mctx, &configctx, + cctx = NULL; + CHECK(dns_c_parse_namedconf(filename, ns_g_mctx, &cctx, &callbacks)); /* * Configure various server options. */ - (void) dns_c_ctx_getrecursion(configctx, &server->recursion); - (void) dns_c_ctx_getauthnxdomain(configctx, &server->auth_nxdomain); - (void) dns_c_ctx_gettransferformat(configctx, - &server->transfer_format); - - CHECK(configure_server_acl(configctx, &aclconfctx, ns_g_mctx, - dns_c_ctx_getqueryacl, &server->queryacl)); - - CHECK(configure_server_acl(configctx, &aclconfctx, ns_g_mctx, - dns_c_ctx_getrecursionacl, - &server->recursionacl)); - - configure_server_quota(configctx, dns_c_ctx_gettransfersout, + configure_server_quota(cctx, dns_c_ctx_gettransfersout, &server->xfroutquota, 10); - configure_server_quota(configctx, dns_c_ctx_gettcpclients, + configure_server_quota(cctx, dns_c_ctx_gettcpclients, &server->tcpquota, 100); - configure_server_quota(configctx, dns_c_ctx_getrecursiveclients, + configure_server_quota(cctx, dns_c_ctx_getrecursiveclients, &server->recursionquota, 100); - (void) dns_c_ctx_getprovideixfr(configctx, &server->provide_ixfr); - - /* * Configure the zone manager. */ { isc_int32_t transfersin = 10; - (void) dns_c_ctx_gettransfersin(configctx, &transfersin); + (void) dns_c_ctx_gettransfersin(cctx, &transfersin); dns_zonemgr_settransfersin(server->zonemgr, transfersin); } { isc_int32_t transfersperns = 2; - (void) dns_c_ctx_gettransfersperns(configctx, &transfersperns); + (void) dns_c_ctx_gettransfersperns(cctx, &transfersperns); dns_zonemgr_settransfersperns(server->zonemgr, transfersperns); } - { - isc_boolean_t requestixfr = ISC_TRUE; - (void) dns_c_ctx_getrequestixfr(configctx, &requestixfr); - dns_zonemgr_setrequestixfr(server->zonemgr, requestixfr); - } - /* * Configure the interface manager according to the "listen-on" @@ -895,10 +1101,10 @@ load_configuration(const char *filename, ns_server_t *server, dns_c_lstnlist_t *clistenon = NULL; ns_listenlist_t *listenon = NULL; - (void) dns_c_ctx_getlistenlist(configctx, &clistenon); + (void) dns_c_ctx_getlistenlist(cctx, &clistenon); if (clistenon != NULL) { result = ns_listenlist_fromconfig(clistenon, - configctx, + cctx, &aclconfctx, ns_g_mctx, &listenon); @@ -924,9 +1130,10 @@ load_configuration(const char *filename, ns_server_t *server, * as specified by the "interface-interval" option. */ interface_interval = 3600; /* Default is 1 hour. */ - (void) dns_c_ctx_getinterfaceinterval(configctx, &interface_interval); + (void) dns_c_ctx_getinterfaceinterval(cctx, &interface_interval); if (interface_interval == 0) { - isc_timer_reset(server->interface_timer, isc_timertype_inactive, + isc_timer_reset(server->interface_timer, + isc_timertype_inactive, NULL, NULL, ISC_TRUE); } else { isc_interval_t interval; @@ -935,42 +1142,68 @@ load_configuration(const char *filename, ns_server_t *server, NULL, &interval, ISC_FALSE); } - CHECK(configure_server_querysource(configctx, server, - AF_INET, &dispatchv4)); - CHECK(configure_server_querysource(configctx, server, - AF_INET6, &dispatchv6)); - /* - * If we haven't created any views, create a default view for class - * IN. (We're a caching-only server.) + * Configure and freeze all explicit views. Explicit + * views that have zones were already created at parsing + * time, but views with no zones must be created here. */ - if (ISC_LIST_EMPTY(lctx.viewlist)) { - view = NULL; - CHECKM(dns_view_create(ns_g_mctx, dns_rdataclass_in, - "_default", &view), - "creating default view"); - ISC_LIST_APPEND(lctx.viewlist, view, link); + if (cctx->views != NULL) { + dns_c_view_t *cview; + for (cview = ISC_LIST_HEAD(cctx->views->views); + cview != NULL; + cview = ISC_LIST_NEXT(cview, next)) + { + view = NULL; + CHECK(find_or_create_view(cview, + &lctx.viewlist, &view)); + INSIST(view != NULL); + CHECK(configure_view(view, cctx, cview, ns_g_mctx, + &aclconfctx)); + dns_view_freeze(view); + dns_view_detach(&view); + } } - + INSIST(view == NULL); + /* - * Configure and freeze the views. Their zone tables have - * already been filled in at parsing time, but other stuff - * like the resolvers are still unconfigured. + * Make sure we have a default view if and only if there + * were no explicit views. */ - for (view = ISC_LIST_HEAD(lctx.viewlist); - view != NULL; - view = ISC_LIST_NEXT(view, link)) - { - CHECK(configure_view(view, configctx, ns_g_mctx, - dispatchv4, dispatchv6)); + if (cctx->views == NULL || ISC_LIST_EMPTY(cctx->views->views)) { + /* + * No explicit views; there ought to be a default view. + * There may already be one created as a size effect + * of zone statements, or we may have to create one. + * In either case, we need to configure and freeze it. + */ + CHECK(find_or_create_view(NULL, &lctx.viewlist, &view)); + CHECK(configure_view(view, cctx, NULL, + ns_g_mctx, &aclconfctx)); dns_view_freeze(view); + dns_view_detach(&view); + } else { + /* + * There are explicit views. There should not be + * a default view. If there is one, complain. + */ + result = dns_viewlist_find(&lctx.viewlist, "_default", + dns_rdataclass_in, &view); + if (result == ISC_R_SUCCESS) { + dns_view_detach(&view); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "when using 'view' statements, " + "all zones must be in views"); + result = ISC_R_FAILURE; + goto cleanup; + } } - + /* * Create (or recreate) the version view. */ view = NULL; - CHECK(create_version_view(configctx, &view)); + CHECK(create_version_view(cctx, server->zonemgr, &view)); ISC_LIST_APPEND(lctx.viewlist, view, link); view = NULL; @@ -986,7 +1219,7 @@ load_configuration(const char *filename, ns_server_t *server, */ { dns_tkey_ctx_t *t = NULL; - CHECKM(dns_tkeyctx_fromconfig(configctx, ns_g_mctx, &t), + CHECKM(dns_tkeyctx_fromconfig(cctx, ns_g_mctx, &t), "configuring TKEY"); if (server->tkeyctx != NULL) dns_tkeyctx_destroy(&server->tkeyctx); @@ -994,13 +1227,23 @@ load_configuration(const char *filename, ns_server_t *server, } /* + * Relinquish root privileges. + */ + if (first_time) + ns_os_changeuser(ns_g_username); + + /* * Configure the logging system. + * + * Do this after changing UID to make sure that any log + * files specified in named.conf get created by the + * unprivileged user, not root. */ if (ns_g_logstderr) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, - "ignoring named.conf logging statement " - "due to -g option"); + "ignoring config file logging " + "statement due to -g option"); } else { dns_c_logginglist_t *clog = NULL; isc_logconfig_t *logc = NULL; @@ -1008,32 +1251,37 @@ load_configuration(const char *filename, ns_server_t *server, CHECKM(isc_logconfig_create(ns_g_lctx, &logc), "creating new logging configuration"); - (void) dns_c_ctx_getlogging(configctx, &clog); - if (clog != NULL) + (void) dns_c_ctx_getlogging(cctx, &clog); + if (clog != NULL) { CHECKM(ns_log_configure(logc, clog), "configuring logging"); - else - CHECKM(ns_log_setdefaults(logc), - "setting up default logging defaults"); + } else { + CHECKM(ns_log_setdefaultchannels(logc), + "setting up default logging channels"); + CHECKM(ns_log_setdefaultcategory(logc), + "setting up default 'category default'"); + } result = isc_logconfig_use(ns_g_lctx, logc); if (result != ISC_R_SUCCESS) { isc_logconfig_destroy(&logc); - CHECKM(result, "intalling logging configuration"); + CHECKM(result, "installing logging configuration"); } } - if (first_time) - ns_os_changeuser(ns_g_username); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), + "now using logging configuration from " + "config file"); - if (dns_c_ctx_getpidfilename(configctx, &pidfilename) == + if (dns_c_ctx_getpidfilename(cctx, &pidfilename) == ISC_R_NOTFOUND) pidfilename = ns_g_defaultpidfile; ns_os_writepidfile(pidfilename); dns_aclconfctx_destroy(&aclconfctx); - dns_c_ctx_delete(&configctx); + dns_c_ctx_delete(&cctx); cleanup: /* @@ -1091,18 +1339,22 @@ load_zones(ns_server_t *server, isc_boolean_t stop) { static void run_server(isc_task_t *task, isc_event_t *event) { isc_result_t result; - ns_server_t *server = (ns_server_t *) event->arg; + ns_server_t *server = (ns_server_t *)event->ev_arg; UNUSED(task); isc_event_free(&event); + CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, &ns_g_dispatchmgr), + "creating dispatch manager"); + CHECKFATAL(ns_clientmgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr, &server->clientmgr), "creating client manager"); CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr, - ns_g_socketmgr, server->clientmgr, + ns_g_socketmgr, ns_g_dispatchmgr, + server->clientmgr, &server->interfacemgr), "creating interface manager"); @@ -1125,7 +1377,7 @@ run_server(isc_task_t *task, isc_event_t *event) { static void shutdown_server(isc_task_t *task, isc_event_t *event) { dns_view_t *view, *view_next; - ns_server_t *server = (ns_server_t *) event->arg; + ns_server_t *server = (ns_server_t *)event->ev_arg; UNUSED(task); @@ -1142,16 +1394,17 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { dns_view_detach(&view); } - if (server->querysrc_dispatchv4 != NULL) - dns_dispatch_detach(&server->querysrc_dispatchv4); - if (server->querysrc_dispatchv6 != NULL) - dns_dispatch_detach(&server->querysrc_dispatchv6); ns_clientmgr_destroy(&server->clientmgr); isc_timer_detach(&server->interface_timer); + ns_interfacemgr_shutdown(server->interfacemgr); ns_interfacemgr_detach(&server->interfacemgr); - dns_zonemgr_shutdown(server->zonemgr); + + dns_dispatchmgr_destroy(&ns_g_dispatchmgr); + dns_zonemgr_shutdown(server->zonemgr); + dns_zonemgr_detach(&server->zonemgr); + isc_task_detach(&server->task); isc_event_free(&event); @@ -1174,12 +1427,6 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { "initializing server configuration lock"); /* Initialize configuration data with default values. */ - server->recursion = ISC_TRUE; - server->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */ - server->transfer_format = dns_one_answer; - - server->queryacl = NULL; - server->recursionacl = NULL; result = isc_quota_init(&server->xfroutquota, 10); RUNTIME_CHECK(result == ISC_R_SUCCESS); @@ -1188,8 +1435,6 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { result = isc_quota_init(&server->recursionquota, 100); RUNTIME_CHECK(result == ISC_R_SUCCESS); - server->provide_ixfr = ISC_TRUE; - result = dns_aclenv_init(mctx, &server->aclenv); RUNTIME_CHECK(result == ISC_R_SUCCESS); @@ -1198,10 +1443,10 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { server->clientmgr = NULL; server->interfacemgr = NULL; ISC_LIST_INIT(server->viewlist); - server->roothints = NULL; + server->in_roothints = NULL; CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, - &server->roothints), + &server->in_roothints), "setting up root hints"); CHECKFATAL(isc_mutex_init(&server->reload_event_lock), @@ -1219,14 +1464,12 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { server->tkeyctx = NULL; CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, &server->tkeyctx), "creating TKEY context"); - server->querysrc_dispatchv4 = NULL; - server->querysrc_dispatchv6 = NULL; /* * Setup the server task, which is responsible for coordinating * startup and shutdown of the server. */ - CHECKFATAL(isc_task_create(ns_g_taskmgr, ns_g_mctx, 0, &server->task), + CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task), "creating server task"); isc_task_setname(server->task, "server", server); CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server), @@ -1251,8 +1494,6 @@ ns_server_destroy(ns_server_t **serverp) { ns_server_t *server = *serverp; REQUIRE(NS_SERVER_VALID(server)); - REQUIRE(server->querysrc_dispatchv4 == NULL); - REQUIRE(server->querysrc_dispatchv6 == NULL); if (server->tkeyctx != NULL) dns_tkeyctx_destroy(&server->tkeyctx); @@ -1260,16 +1501,8 @@ ns_server_destroy(ns_server_t **serverp) { INSIST(ISC_LIST_EMPTY(server->viewlist)); - dns_zonemgr_destroy(&server->zonemgr); - server->zonemgr = NULL; - - dns_db_detach(&server->roothints); + dns_db_detach(&server->in_roothints); - if (server->queryacl != NULL) - dns_acl_detach(&server->queryacl); - if (server->recursionacl != NULL) - dns_acl_detach(&server->recursionacl); - dns_aclenv_destroy(&server->aclenv); isc_quota_destroy(&server->recursionquota); @@ -1294,18 +1527,18 @@ fatal(char *msg, isc_result_t result) { static void ns_server_reload(isc_task_t *task, isc_event_t *event) { isc_result_t result; - ns_server_t *server = (ns_server_t *)event->arg; + ns_server_t *server = (ns_server_t *)event->ev_arg; UNUSED(task); result = load_configuration(ns_g_conffile, server, ISC_FALSE); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "reloading configuration failed: %s", isc_result_totext(result)); } result = load_zones(server, ISC_FALSE); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "reloading zones failed: %s", @@ -1346,7 +1579,7 @@ ns_listenlist_fromconfig(dns_c_lstnlist_t *clist, dns_c_ctx_t *cctx, { ns_listenelt_t *delt = NULL; result = ns_listenelt_fromconfig(ce, cctx, actx, mctx, &delt); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto cleanup; ISC_LIST_APPEND(dlist->elts, delt, link); } @@ -1375,7 +1608,7 @@ ns_listenelt_fromconfig(dns_c_lstnon_t *celt, dns_c_ctx_t *cctx, return (result); result = dns_acl_fromconfig(celt->iml, cctx, actx, mctx, &delt->acl); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { ns_listenelt_destroy(delt); return (result); } diff --git a/bin/named/unix/include/named/os.h b/bin/named/unix/include/named/os.h index 95cdbe7f..f29fb9d4 100644 --- a/bin/named/unix/include/named/os.h +++ b/bin/named/unix/include/named/os.h @@ -33,6 +33,9 @@ void ns_os_changeuser(const char *username); void +ns_os_minprivs(const char *username); + +void ns_os_writepidfile(const char *filename); void diff --git a/bin/named/unix/os.c b/bin/named/unix/os.c index 05452e3f..6f0a0291 100644 --- a/bin/named/unix/os.c +++ b/bin/named/unix/os.c @@ -17,22 +17,19 @@ #include <config.h> -#include <sys/types.h> #include <sys/stat.h> #include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> #include <errno.h> -#include <syslog.h> #include <fcntl.h> +#include <grp.h> /* Required for initgroups() on IRIX. */ #include <pwd.h> -#include <grp.h> +#include <stdio.h> +#include <stdlib.h> +#include <syslog.h> +#include <unistd.h> -#include <isc/result.h> -#include <isc/boolean.h> +#include <isc/string.h> #include <named/main.h> #include <named/os.h> @@ -40,12 +37,25 @@ static char *pidfile = NULL; #ifdef HAVE_LINUXTHREADS static pid_t mainpid = 0; +static isc_boolean_t non_root_caps = ISC_FALSE; #endif #ifdef HAVE_LINUX_CAPABILITY_H -#include <sys/syscall.h> -#include <linux/capability.h> +/* + * We define _LINUX_FS_H to prevent it from being included. We don't need + * anything from it, and the files it includes cause warnings with 2.2 + * kernels, and compilation failures (due to conflicts between <linux/string.h> + * and <string.h>) on 2.3 kernels. + */ +#define _LINUX_FS_H + +#include <sys/syscall.h> /* Required for syscall(). */ +#include <linux/capability.h> /* Required for _LINUX_CAPABILITY_VERSION. */ + +#ifdef HAVE_LINUX_PRCTL_H +#include <sys/prctl.h> /* Required for prctl(). */ +#endif #ifndef SYS_capset #define SYS_capset __NR_capset @@ -56,7 +66,7 @@ linux_setcaps(unsigned int caps) { struct __user_cap_header_struct caphead; struct __user_cap_data_struct cap; - if (getuid() != 0) + if (getuid() != 0 && !non_root_caps) return; memset(&caphead, 0, sizeof caphead); @@ -75,17 +85,41 @@ linux_initialprivs(void) { unsigned int caps; /* - * Drop all privileges except the abilities to bind() to privileged - * ports and chroot(). + * We don't need most privileges, so we drop them right away. + * Later on linux_minprivs() will be called, which will drop our + * capabilities to the minimum needed to run the server. */ caps = 0; + + /* + * We need to be able to bind() to privileged ports, notably port 53! + */ caps |= (1 << CAP_NET_BIND_SERVICE); + + /* + * We need chroot() initially too. + */ caps |= (1 << CAP_SYS_CHROOT); + +#if defined(HAVE_LINUX_PRCTL_H) && defined(PR_SET_KEEPCAPS) + /* + * If the kernel supports keeping capabilities after setuid(), we + * also want the setuid and setgid capabilities. + * + * There's no point turning these on if we don't have PR_SET_KEEPCAPS, + * because changing user ids only works right with linuxthreads if + * we can do it early (before creating threads). + */ + caps |= (1 << CAP_SETGID); + caps |= (1 << CAP_SETUID); +#endif + /* * XXX We might want to add CAP_SYS_RESOURCE, though it's not * clear it would work right given the way linuxthreads work. */ + linux_setcaps(caps); } @@ -94,8 +128,11 @@ linux_minprivs(void) { unsigned int caps; /* - * Drop all privileges except the abilities to bind() to privileged + * Drop all privileges except the ability to bind() to privileged * ports. + * + * It's important that we drop CAP_SYS_CHROOT. If we didn't, it + * chroot() could be used to escape from the chrooted area. */ caps = 0; @@ -104,6 +141,23 @@ linux_minprivs(void) { linux_setcaps(caps); } +#if defined(HAVE_LINUX_PRCTL_H) && defined(PR_SET_KEEPCAPS) +static void +linux_keepcaps(void) { + /* + * Ask the kernel to allow us to keep our capabilities after we + * setuid(). + */ + + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { + if (errno != EINVAL) + ns_main_earlyfatal("prctl() failed: %s", + strerror(errno)); + } else + non_root_caps = ISC_TRUE; +} +#endif + #endif /* HAVE_LINUX_CAPABILITY_H */ @@ -139,7 +193,7 @@ ns_os_daemonize(void) { if (pid == -1) ns_main_earlyfatal("fork(): %s", strerror(errno)); if (pid != 0) - _exit(0); + _exit(0); /* * We're the child. @@ -188,13 +242,6 @@ ns_os_chroot(const char *root) { if (chdir("/") < 0) ns_main_earlyfatal("chdir(/): %s", strerror(errno)); } -#ifdef HAVE_LINUX_CAPABILITY_H - /* - * We must drop the chroot() capability, otherwise it could be used - * to escape. - */ - linux_minprivs(); -#endif } void @@ -204,6 +251,12 @@ ns_os_changeuser(const char *username) { if (username == NULL || getuid() != 0) return; +#ifdef HAVE_LINUXTHREADS + if (!non_root_caps) + ns_main_earlyfatal( + "-u not supported on Linux kernels older than 2.3.99-pre3"); +#endif + if (all_digits(username)) pw = getpwuid((uid_t)atoi(username)); else @@ -219,6 +272,21 @@ ns_os_changeuser(const char *username) { ns_main_earlyfatal("setuid(): %s", strerror(errno)); } +void +ns_os_minprivs(const char *username) { +#ifdef HAVE_LINUX_CAPABILITY_H +#if defined(HAVE_LINUX_PRCTL_H) && defined(PR_SET_KEEPCAPS) + linux_keepcaps(); + ns_os_changeuser(username); +#else + (void)username; +#endif + linux_minprivs(); +#else + (void)username; +#endif /* HAVE_LINUX_CAPABILITY_H */ +} + static int safe_open(const char *filename) { struct stat sb; diff --git a/bin/named/update.c b/bin/named/update.c index 67054c55..77f19b39 100644 --- a/bin/named/update.c +++ b/bin/named/update.c @@ -17,45 +17,26 @@ #include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> - -#include <isc/assertions.h> -#include <isc/error.h> -#include <isc/mem.h> -#include <isc/result.h> +#include <isc/string.h> #include <isc/taskpool.h> #include <isc/util.h> -#include <dns/acl.h> #include <dns/db.h> #include <dns/dbiterator.h> -#include <dns/dbtable.h> #include <dns/dnssec.h> #include <dns/events.h> -#include <dns/fixedname.h> #include <dns/journal.h> #include <dns/message.h> -#include <dns/name.h> #include <dns/nxt.h> -#include <dns/rdata.h> -#include <dns/rdatalist.h> #include <dns/rdataset.h> #include <dns/rdatasetiter.h> -#include <dns/rdatastruct.h> -#include <dns/result.h> #include <dns/ssu.h> -#include <dns/types.h> #include <dns/view.h> #include <dns/zone.h> #include <dns/zt.h> #include <named/client.h> -#include <named/globals.h> #include <named/log.h> -#include <named/server.h> #include <named/update.h> /* @@ -101,23 +82,28 @@ */ #define CHECK(op) \ do { result = (op); \ - if (result != DNS_R_SUCCESS) goto failure; \ + if (result != ISC_R_SUCCESS) goto failure; \ } while (0) /* * Fail unconditionally with result 'code', which must not - * be DNS_R_SUCCESS. The reason for failure presumably has + * be ISC_R_SUCCESS. The reason for failure presumably has * been logged already. + * + * The test against ISC_R_SUCCESS is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". */ #define FAIL(code) \ do { \ result = (code); \ - goto failure; \ + if (code != ISC_R_SUCCESS) goto failure; \ } while (0) /* * Fail unconditionally and log as a client error. + * The test against ISC_R_SUCCESS is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". */ #define FAILC(code, msg) \ do { \ @@ -125,11 +111,13 @@ isc_log_write(UPDATE_PROTOCOL_LOGARGS, \ "dynamic update failed: %s (%s)", \ msg, isc_result_totext(code)); \ - goto failure; \ + if (code != ISC_R_SUCCESS) goto failure; \ } while (0) /* * Fail unconditionally and log as a server error. + * The test against ISC_R_SUCCESS is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". */ #define FAILS(code, msg) \ do { \ @@ -137,7 +125,7 @@ isc_log_write(UPDATE_PROTOCOL_LOGARGS, \ "dynamic update error: %s: %s", \ msg, isc_result_totext(code)); \ - goto failure; \ + if (code != ISC_R_SUCCESS) goto failure; \ } while (0) /**************************************************************************/ @@ -191,7 +179,7 @@ do_one_tuple(dns_difftuple_t **tuple, /* Apply it to the database. */ result = dns_diff_apply(&temp_diff, db, ver); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { dns_difftuple_free(tuple); return (result); } @@ -201,7 +189,7 @@ do_one_tuple(dns_difftuple_t **tuple, /* Do not clear temp_diff. */ - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } static isc_result_t @@ -213,7 +201,7 @@ update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, isc_result_t result; result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) return (result); return (do_one_tuple(&tuple, db, ver, diff)); } @@ -257,19 +245,19 @@ foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) isc_result_t result; foreach_node_rr_ctx_t *ctx = data; for (result = dns_rdataset_first(rdataset); - result == DNS_R_SUCCESS; + result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { rr_t rr; dns_rdataset_current(rdataset, &rr.rdata); rr.ttl = rdataset->ttl; result = (*ctx->rr_action)(ctx->rr_action_data, &rr); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) return (result); } - if (result != DNS_R_NOMORE) + if (result != ISC_R_NOMORE) return (result); - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } /* @@ -292,19 +280,19 @@ foreach_rrset(dns_db_t *db, node = NULL; result = dns_db_findnode(db, name, ISC_FALSE, &node); - if (result == DNS_R_NOTFOUND) - return (DNS_R_SUCCESS); - if (result != DNS_R_SUCCESS) + if (result == ISC_R_NOTFOUND) + return (ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) return (result); iter = NULL; result = dns_db_allrdatasets(db, node, ver, (isc_stdtime_t) 0, &iter); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto cleanup_node; for (result = dns_rdatasetiter_first(iter); - result == DNS_R_SUCCESS; + result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(iter)) { dns_rdataset_t rdataset; @@ -315,11 +303,11 @@ foreach_rrset(dns_db_t *db, result = (*action)(action_data, &rdataset); dns_rdataset_disassociate(&rdataset); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto cleanup_iterator; } - if (result == DNS_R_NOMORE) - result = DNS_R_SUCCESS; + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; cleanup_iterator: dns_rdatasetiter_destroy(&iter); @@ -382,35 +370,35 @@ foreach_rr(dns_db_t *db, node = NULL; result = dns_db_findnode(db, name, ISC_FALSE, &node); - if (result == DNS_R_NOTFOUND) - return (DNS_R_SUCCESS); - if (result != DNS_R_SUCCESS) + if (result == ISC_R_NOTFOUND) + return (ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) return (result); dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, ver, type, covers, (isc_stdtime_t) 0, &rdataset, NULL); - if (result == DNS_R_NOTFOUND) { - result = DNS_R_SUCCESS; + if (result == ISC_R_NOTFOUND) { + result = ISC_R_SUCCESS; goto cleanup_node; } - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto cleanup_node; for (result = dns_rdataset_first(&rdataset); - result == DNS_R_SUCCESS; + result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { rr_t rr; dns_rdataset_current(&rdataset, &rr.rdata); rr.ttl = rdataset.ttl; result = (*rr_action)(rr_action_data, &rr); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto cleanup_rdataset; } - if (result != DNS_R_NOMORE) + if (result != ISC_R_NOMORE) goto cleanup_rdataset; - result = DNS_R_SUCCESS; + result = ISC_R_SUCCESS; cleanup_rdataset: dns_rdataset_disassociate(&rdataset); @@ -438,14 +426,14 @@ rrset_exists_action(void *data, rr_t *rr) /*ARGSUSED*/ { UNUSED(data); UNUSED(rr); - return (DNS_R_EXISTS); + return (ISC_R_EXISTS); } /* * Utility macro for RR existence checking functions. * - * If the variable 'result' has the value DNS_R_EXISTS or - * DNS_R_SUCCESS, set *exists to ISC_TRUE or ISC_FALSE, + * If the variable 'result' has the value ISC_R_EXISTS or + * ISC_R_SUCCESS, set *exists to ISC_TRUE or ISC_FALSE, * respectively, and return success. * * If 'result' has any other value, there was a failure. @@ -455,10 +443,10 @@ rrset_exists_action(void *data, rr_t *rr) /*ARGSUSED*/ * but that form generates tons of warnings on Solaris 2.6. */ #define RETURN_EXISTENCE_FLAG \ - return ((result == DNS_R_EXISTS) ? \ - (*exists = ISC_TRUE, DNS_R_SUCCESS) : \ - ((result == DNS_R_SUCCESS) ? \ - (*exists = ISC_FALSE, DNS_R_SUCCESS) : \ + return ((result == ISC_R_EXISTS) ? \ + (*exists = ISC_TRUE, ISC_R_SUCCESS) : \ + ((result == ISC_R_SUCCESS) ? \ + (*exists = ISC_FALSE, ISC_R_SUCCESS) : \ result)); /* @@ -484,8 +472,8 @@ cname_compatibility_action(void *data, dns_rdataset_t *rrset) UNUSED(data); if (rrset->type != dns_rdatatype_cname && ! dns_rdatatype_isdnssec(rrset->type)) - return (DNS_R_EXISTS); - return (DNS_R_SUCCESS); + return (ISC_R_EXISTS); + return (ISC_R_SUCCESS); } /* @@ -511,7 +499,7 @@ count_rr_action(void *data, rr_t *rr) /*ARGSUSED*/ { int *countp = data; UNUSED(rr); (*countp)++; - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } /* @@ -542,8 +530,8 @@ static isc_result_t matching_rr_exists_action(void *data, rr_t *rr) { matching_rr_exists_ctx_t *ctx = data; if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) - return (DNS_R_EXISTS); - return (DNS_R_SUCCESS); + return (ISC_R_EXISTS); + return (ISC_R_SUCCESS); } /* @@ -582,7 +570,7 @@ name_exists_action(void *data, dns_rdataset_t *rrset) /*ARGSUSED*/ { UNUSED(data); UNUSED(rrset); - return (DNS_R_EXISTS); + return (ISC_R_EXISTS); } /* @@ -668,7 +656,7 @@ temp_append(dns_diff_t *diff, dns_name_t *name, dns_rdata_t *rdata) /* * Compare two rdatasets represented as sorted lists of tuples. * All list elements must have the same owner name and type. - * Return DNS_R_SUCCESS if the rdatasets are equal, rcode(dns_rcode_nxrrset) + * Return ISC_R_SUCCESS if the rdatasets are equal, rcode(dns_rcode_nxrrset) * if not. */ static isc_result_t @@ -686,7 +674,7 @@ temp_check_rrset(dns_difftuple_t *a, dns_difftuple_t *b) { } if (a != NULL || b != NULL) return (DNS_R_NXRRSET); - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } /* @@ -716,7 +704,7 @@ temp_order(const void *av, const void *bv) * Check the "RRset exists (value dependent)" prerequisite information * in 'temp' against the contents of the database 'db'. * - * Return DNS_R_SUCCESS if the prerequisites are satisfied, + * Return ISC_R_SUCCESS if the prerequisites are satisfied, * rcode(dns_rcode_nxrrset) if not. */ @@ -732,14 +720,14 @@ temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db, /* Exit early if the list is empty (for efficiency only). */ if (ISC_LIST_HEAD(temp->tuples) == NULL) - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); /* * Sort the prerequisite records by owner name, * type, and rdata. */ result = dns_diff_sort(temp, temp_order); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) return (result); dns_diff_init(mctx, &trash); @@ -756,9 +744,9 @@ temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db, /* A new unique name begins here. */ node = NULL; result = dns_db_findnode(db, name, ISC_FALSE, &node); - if (result == DNS_R_NOTFOUND) + if (result == ISC_R_NOTFOUND) return (DNS_R_NXRRSET); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) return (result); /* A new unique type begins here. */ @@ -784,7 +772,7 @@ temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db, result = dns_db_findrdataset(db, node, ver, type, covers, (isc_stdtime_t) 0, &rdataset, NULL); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { dns_db_detachnode(db, &node); return (DNS_R_NXRRSET); } @@ -793,19 +781,19 @@ temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db, dns_diff_init(mctx, &u_rrs); for (result = dns_rdataset_first(&rdataset); - result == DNS_R_SUCCESS; + result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdata_t rdata; dns_rdataset_current(&rdataset, &rdata); result = temp_append(&d_rrs, name, &rdata); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto failure; } - if (result != DNS_R_NOMORE) + if (result != ISC_R_NOMORE) goto failure; result = dns_diff_sort(&d_rrs, temp_order); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto failure; /* @@ -827,7 +815,7 @@ temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db, /* Compare the two sorted lists. */ result = temp_check_rrset(ISC_LIST_HEAD(u_rrs.tuples), ISC_LIST_HEAD(d_rrs.tuples)); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto failure; /* @@ -854,7 +842,7 @@ temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db, } dns_diff_clear(&trash); - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } /**************************************************************************/ @@ -950,7 +938,7 @@ delete_if_action(void *data, rr_t *rr) { rr->ttl, &rr->rdata); return (result); } else { - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } } @@ -1010,9 +998,9 @@ get_current_rr(dns_message_t *msg, dns_section_t section, *covers = rdataset->covers; *ttl = rdataset->ttl; result = dns_rdataset_first(rdataset); - INSIST(result == DNS_R_SUCCESS); + INSIST(result == ISC_R_SUCCESS); dns_rdataset_current(rdataset, rdata); - INSIST(dns_rdataset_next(rdataset) == DNS_R_NOMORE); + INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE); *update_class = rdata->rdclass; rdata->rdclass = zoneclass; } @@ -1052,7 +1040,7 @@ increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_soa_setserial(serial, &addtuple->rdata); CHECK(do_one_tuple(&addtuple, db, ver, diff)); CHECK(do_one_tuple(&deltuple, db, ver, diff)); - result = DNS_R_SUCCESS; + result = ISC_R_SUCCESS; failure: if (addtuple != NULL) @@ -1094,7 +1082,7 @@ check_soa_increment(dns_db_t *db, dns_dbversion_t *ver, update_serial = dns_soa_getserial(update_rdata); result = dns_db_getsoaserial(db, ver, &db_serial); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) return (result); if (DNS_SERIAL_GE(db_serial, update_serial)) { @@ -1103,7 +1091,7 @@ check_soa_increment(dns_db_t *db, dns_dbversion_t *ver, *ok = ISC_TRUE; } - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } @@ -1144,7 +1132,7 @@ namelist_append_subdomain(dns_db_t *db, dns_name_t *name, dns_diff_t *affected) CHECK(dns_db_createiterator(db, ISC_FALSE, &dbit)); for (result = dns_dbiterator_seek(dbit, name); - result == DNS_R_SUCCESS; + result == ISC_R_SUCCESS; result = dns_dbiterator_next(dbit)) { dns_dbnode_t *node = NULL; @@ -1172,8 +1160,8 @@ is_non_nxt_action(void *data, dns_rdataset_t *rrset) if (!(rrset->type == dns_rdatatype_nxt || (rrset->type == dns_rdatatype_sig && rrset->covers == dns_rdatatype_nxt))) - return (DNS_R_EXISTS); - return (DNS_R_SUCCESS); + return (ISC_R_EXISTS); + return (ISC_R_SUCCESS); } /* @@ -1241,16 +1229,16 @@ is_glue(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, (isc_stdtime_t) 0, NULL, dns_fixedname_name(&foundname), NULL, NULL); - if (result == DNS_R_SUCCESS) { + if (result == ISC_R_SUCCESS) { *flag = ISC_FALSE; - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } else if (result == DNS_R_ZONECUT) { /* XXX should omit non-delegation types from NXT */ *flag = ISC_FALSE; - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } else if (result == DNS_R_GLUE) { *flag = ISC_TRUE; - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } else { return (result); } @@ -1280,7 +1268,7 @@ next_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *oldname, result = dns_dbiterator_next(dbit); else result = dns_dbiterator_prev(dbit); - if (result == DNS_R_NOMORE) { + if (result == ISC_R_NOMORE) { /* Wrap around. */ if (forward) CHECK(dns_dbiterator_first(dbit)); @@ -1401,7 +1389,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, unsigned int i; dns_rdataset_init(&rdataset); - isc_buffer_init(&buffer, data, sizeof data, ISC_BUFFERTYPE_BINARY); + isc_buffer_init(&buffer, data, sizeof(data)); /* Get the rdataset to sign. */ CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); @@ -1465,7 +1453,7 @@ update_signatures(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *oldver, result = find_zone_keys(db, newver, mctx, MAXZONEKEYS, zone_keys, &nkeys); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE, ISC_LOG_ERROR, "could not get zone keys for secure " @@ -1724,7 +1712,7 @@ update_signatures(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *oldver, dns_diff_clear(&diffnames); for (i = 0; i < nkeys; i++) - dst_key_free(zone_keys[i]); + dst_key_free(&zone_keys[i]); return (result); } @@ -1738,7 +1726,7 @@ update_signatures(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *oldver, static isc_result_t send_update_event(ns_client_t *client, dns_zone_t *zone) { - isc_result_t result = DNS_R_SUCCESS; + isc_result_t result = ISC_R_SUCCESS; update_event_t *event = NULL; isc_task_t *zonetask = NULL; ns_client_t *evclient; @@ -1747,20 +1735,20 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) { isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE, update_action, NULL, sizeof(*event)); if (event == NULL) - FAIL(DNS_R_NOMEMORY); + FAIL(ISC_R_NOMEMORY); event->zone = zone; - event->result = DNS_R_SUCCESS; + event->result = ISC_R_SUCCESS; evclient = NULL; ns_client_attach(client, &evclient); - event->arg = evclient; + event->ev_arg = evclient; dns_zone_gettask(zone, &zonetask); - isc_task_send(zonetask, (isc_event_t **) &event); + isc_task_send(zonetask, (isc_event_t **)&event); failure: if (event != NULL) - isc_event_free((isc_event_t **) &event); + isc_event_free((isc_event_t **)&event); return (result); } @@ -1769,7 +1757,7 @@ respond(ns_client_t *client, isc_result_t result) { isc_result_t msg_result; msg_result = dns_message_reply(client->message, ISC_TRUE); - if (msg_result != DNS_R_SUCCESS) + if (msg_result != ISC_R_SUCCESS) goto msg_failure; client->message->rcode = dns_result_torcode(result); @@ -1798,7 +1786,7 @@ ns_update_start(ns_client_t *client) * Interpret the zone section. */ result = dns_message_firstname(request, DNS_SECTION_ZONE); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) FAILC(DNS_R_FORMERR, "update zone section empty"); @@ -1819,12 +1807,13 @@ ns_update_start(ns_client_t *client) /* The zone section must have exactly one name. */ result = dns_message_nextname(request, DNS_SECTION_ZONE); - if (result != DNS_R_NOMORE) + if (result != ISC_R_NOMORE) FAILC(DNS_R_FORMERR, "update zone section contains multiple RRs"); - result = dns_zt_find(client->view->zonetable, zonename, NULL, &zone); - if (result != DNS_R_SUCCESS) + result = dns_zt_find(client->view->zonetable, zonename, 0, NULL, + &zone); + if (result != ISC_R_SUCCESS) FAILC(DNS_R_NOTAUTH, "not authoritative for update zone"); @@ -1855,7 +1844,7 @@ update_action(isc_task_t *task, isc_event_t *event) { update_event_t *uev = (update_event_t *) event; dns_zone_t *zone = uev->zone; - ns_client_t *client = (ns_client_t *) event->arg; + ns_client_t *client = (ns_client_t *)event->ev_arg; isc_result_t result; dns_db_t *db = NULL; @@ -1871,7 +1860,7 @@ update_action(isc_task_t *task, isc_event_t *event) dns_name_t *zonename; dns_ssutable_t *ssutable = NULL; - INSIST(event->type == DNS_EVENT_UPDATE); + INSIST(event->ev_type == DNS_EVENT_UPDATE); dns_diff_init(mctx, &diff); dns_diff_init(mctx, &temp); @@ -1886,7 +1875,7 @@ update_action(isc_task_t *task, isc_event_t *event) /* Check prerequisites. */ for (result = dns_message_firstname(request, DNS_SECTION_PREREQUISITE); - result == DNS_R_SUCCESS; + result == ISC_R_SUCCESS; result = dns_message_nextname(request, DNS_SECTION_PREREQUISITE)) { dns_name_t *name = NULL; @@ -1952,17 +1941,17 @@ update_action(isc_task_t *task, isc_event_t *event) } else if (update_class == zoneclass) { /* "temp<rr.name, rr.type> += rr;" */ result = temp_append(&temp, name, &rdata); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "temp entry creation failed: %s", dns_result_totext(result)); - FAIL(DNS_R_UNEXPECTED); + FAIL(ISC_R_UNEXPECTED); } } else { FAILC(DNS_R_FORMERR, "malformed prerequisite"); } } - if (result != DNS_R_NOMORE) + if (result != ISC_R_NOMORE) FAIL(result); /* @@ -1970,7 +1959,7 @@ update_action(isc_task_t *task, isc_event_t *event) * prerequisites. */ result = temp_check(mctx, &temp, db, ver); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) FAILC(result, "'RRset exists (value dependent)' " "prerequisite not satisfied"); @@ -1992,7 +1981,7 @@ update_action(isc_task_t *task, isc_event_t *event) /* Perform the Update Section Prescan. */ for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); - result == DNS_R_SUCCESS; + result == ISC_R_SUCCESS; result = dns_message_nextname(request, DNS_SECTION_UPDATE)) { dns_name_t *name = NULL; @@ -2060,7 +2049,7 @@ update_action(isc_task_t *task, isc_event_t *event) } } } - if (result != DNS_R_NOMORE) + if (result != ISC_R_NOMORE) FAIL(result); isc_log_write(UPDATE_DEBUG_LOGARGS, "update section prescan OK"); @@ -2068,7 +2057,7 @@ update_action(isc_task_t *task, isc_event_t *event) /* Process the Update Section. */ for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); - result == DNS_R_SUCCESS; + result == ISC_R_SUCCESS; result = dns_message_nextname(request, DNS_SECTION_UPDATE)) { dns_name_t *name = NULL; @@ -2144,7 +2133,7 @@ update_action(isc_task_t *task, isc_event_t *event) result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, name, ttl, &rdata); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) FAIL(result); } else { isc_log_write(UPDATE_PROTOCOL_LOGARGS, @@ -2211,7 +2200,7 @@ update_action(isc_task_t *task, isc_event_t *event) rdata.type, covers, &rdata, &diff)); } } - if (result != DNS_R_NOMORE) + if (result != ISC_R_NOMORE) FAIL(result); /* @@ -2233,7 +2222,7 @@ update_action(isc_task_t *task, isc_event_t *event) if (dns_db_issecure(db)) { result = update_signatures(mctx, db, oldver, ver, &diff); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE, ISC_LOG_ERROR, @@ -2249,11 +2238,11 @@ update_action(isc_task_t *task, isc_event_t *event) journal = NULL; result = dns_journal_open(mctx, dns_zone_getjournal(zone), ISC_TRUE, &journal); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) FAILS(result, "journal open failed"); result = dns_journal_write_transaction(journal, &diff); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { dns_journal_destroy(&journal); FAILS(result, "journal write failed"); } @@ -2268,7 +2257,14 @@ update_action(isc_task_t *task, isc_event_t *event) */ isc_log_write(UPDATE_DEBUG_LOGARGS, "committing update transaction"); dns_db_closeversion(db, &ver, ISC_TRUE); - result = DNS_R_SUCCESS; + + + /* + * Notify slaves of the change we just made. + */ + dns_zone_notify(zone); + + result = ISC_R_SUCCESS; goto common; failure: @@ -2294,8 +2290,8 @@ update_action(isc_task_t *task, isc_event_t *event) isc_task_detach(&task); uev->result = result; - uev->type = DNS_EVENT_UPDATEDONE; - uev->action = updatedone_action; + uev->ev_type = DNS_EVENT_UPDATEDONE; + uev->ev_action = updatedone_action; isc_task_send(client->task, &event); INSIST(event == NULL); } @@ -2304,9 +2300,11 @@ static void updatedone_action(isc_task_t *task, isc_event_t *event) { update_event_t *uev = (update_event_t *) event; - ns_client_t *client = (ns_client_t *) event->arg; + ns_client_t *client = (ns_client_t *) event->ev_arg; - INSIST(event->type == DNS_EVENT_UPDATEDONE); + UNUSED(task); + + INSIST(event->ev_type == DNS_EVENT_UPDATEDONE); INSIST(task == client->task); respond(client, uev->result); diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c index 91800a30..452a8156 100644 --- a/bin/named/xfrout.c +++ b/bin/named/xfrout.c @@ -15,44 +15,29 @@ * SOFTWARE. */ -/* $Id: xfrout.c,v 1.49 2000/03/23 00:54:44 gson Exp $ */ +/* $Id: xfrout.c,v 1.62 2000/05/15 21:14:01 tale Exp $ */ #include <config.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> - -#include <sys/types.h> - -#include <isc/assertions.h> -#include <isc/error.h> #include <isc/mem.h> -#include <isc/result.h> #include <isc/timer.h> +#include <isc/print.h> #include <isc/util.h> -#include <dns/acl.h> #include <dns/db.h> #include <dns/dbiterator.h> -#include <dns/fixedname.h> #include <dns/journal.h> #include <dns/message.h> -#include <dns/name.h> #include <dns/peer.h> -#include <dns/rdata.h> #include <dns/rdatalist.h> #include <dns/rdataset.h> #include <dns/rdatasetiter.h> -#include <dns/rdatastruct.h> #include <dns/result.h> -#include <dns/types.h> #include <dns/view.h> #include <dns/zone.h> #include <dns/zt.h> #include <named/client.h> -#include <named/globals.h> #include <named/log.h> #include <named/server.h> #include <named/xfrout.h> @@ -77,19 +62,22 @@ /* * Fail unconditionally and log as a client error. + * The test against ISC_R_SUCCESS is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". */ #define FAILC(code, msg) \ do { \ result = (code); \ - isc_log_write(XFROUT_PROTOCOL_LOGARGS, \ - "bad zone transfer request: %s (%s)", \ - msg, isc_result_totext(code)); \ - goto failure; \ + ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \ + NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \ + "bad zone transfer request: %s (%s)", \ + msg, isc_result_totext(code)); \ + if (result != ISC_R_SUCCESS) goto failure; \ } while (0) #define CHECK(op) \ do { result = (op); \ - if (result != DNS_R_SUCCESS) goto failure; \ + if (result != ISC_R_SUCCESS) goto failure; \ } while (0) /**************************************************************************/ @@ -113,17 +101,22 @@ struct db_rr_iterator { dns_rdata_t rdata; }; -isc_result_t db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, - dns_dbversion_t *ver, isc_stdtime_t now); +isc_result_t +db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver, + isc_stdtime_t now); -isc_result_t db_rr_iterator_first(db_rr_iterator_t *it); +isc_result_t +db_rr_iterator_first(db_rr_iterator_t *it); -isc_result_t db_rr_iterator_next(db_rr_iterator_t *it); +isc_result_t +db_rr_iterator_next(db_rr_iterator_t *it); -void db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name, - isc_uint32_t *ttl, dns_rdata_t **rdata); +void +db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name, + isc_uint32_t *ttl, dns_rdata_t **rdata); -void db_rr_iterator_destroy(db_rr_iterator_t *it); +void +db_rr_iterator_destroy(db_rr_iterator_t *it); isc_result_t db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver, @@ -136,34 +129,34 @@ db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver, it->now = now; it->node = NULL; result = dns_db_createiterator(it->db, ISC_FALSE, &it->dbit); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) return (result); it->rdatasetit = NULL; dns_rdataset_init(&it->rdataset); dns_fixedname_init(&it->fixedname); INSIST(! dns_rdataset_isassociated(&it->rdataset)); - it->result = DNS_R_SUCCESS; + it->result = ISC_R_SUCCESS; return (it->result); } isc_result_t db_rr_iterator_first(db_rr_iterator_t *it) { it->result = dns_dbiterator_first(it->dbit); - if (it->result != DNS_R_SUCCESS) + if (it->result != ISC_R_SUCCESS) return (it->result); it->result = dns_dbiterator_current(it->dbit, &it->node, dns_fixedname_name(&it->fixedname)); - if (it->result != DNS_R_SUCCESS) + if (it->result != ISC_R_SUCCESS) return (it->result); it->result = dns_db_allrdatasets(it->db, it->node, it->ver, it->now, &it->rdatasetit); - if (it->result != DNS_R_SUCCESS) + if (it->result != ISC_R_SUCCESS) return (it->result); it->result = dns_rdatasetiter_first(it->rdatasetit); - if (it->result != DNS_R_SUCCESS) + if (it->result != ISC_R_SUCCESS) return (it->result); dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); @@ -175,7 +168,7 @@ db_rr_iterator_first(db_rr_iterator_t *it) { isc_result_t db_rr_iterator_next(db_rr_iterator_t *it) { - if (it->result != DNS_R_SUCCESS) + if (it->result != ISC_R_SUCCESS) return (it->result); INSIST(it->dbit != NULL); @@ -183,32 +176,32 @@ db_rr_iterator_next(db_rr_iterator_t *it) { INSIST(it->rdatasetit != NULL); it->result = dns_rdataset_next(&it->rdataset); - if (it->result == DNS_R_NOMORE) { + if (it->result == ISC_R_NOMORE) { dns_rdataset_disassociate(&it->rdataset); it->result = dns_rdatasetiter_next(it->rdatasetit); - while (it->result == DNS_R_NOMORE) { + while (it->result == ISC_R_NOMORE) { dns_rdatasetiter_destroy(&it->rdatasetit); dns_db_detachnode(it->db, &it->node); it->result = dns_dbiterator_next(it->dbit); - if (it->result == DNS_R_NOMORE) { + if (it->result == ISC_R_NOMORE) { /* We are at the end of the entire database. */ return (it->result); } - if (it->result != DNS_R_SUCCESS) + if (it->result != ISC_R_SUCCESS) return (it->result); it->result = dns_dbiterator_current(it->dbit, &it->node, dns_fixedname_name(&it->fixedname)); - if (it->result != DNS_R_SUCCESS) + if (it->result != ISC_R_SUCCESS) return (it->result); it->result = dns_db_allrdatasets(it->db, it->node, it->ver, it->now, &it->rdatasetit); - if (it->result != DNS_R_SUCCESS) + if (it->result != ISC_R_SUCCESS) return (it->result); it->result = dns_rdatasetiter_first(it->rdatasetit); } - if (it->result != DNS_R_SUCCESS) + if (it->result != ISC_R_SUCCESS) return (it->result); dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); } @@ -231,7 +224,7 @@ db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name, isc_uint32_t *ttl, dns_rdata_t **rdata) { REQUIRE(name != NULL && *name == NULL); - REQUIRE(it->result == DNS_R_SUCCESS); + REQUIRE(it->result == ISC_R_SUCCESS); *name = dns_fixedname_name(&it->fixedname); *ttl = it->rdataset.ttl; dns_rdataset_current(&it->rdataset, &it->rdata); @@ -259,18 +252,22 @@ log_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) { ISC_LINK_INIT(&rdl, link); dns_rdataset_init(&rds); ISC_LIST_APPEND(rdl.rdata, rdata, link); - RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == DNS_R_SUCCESS); + RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS); - isc_buffer_init(&buf, mem, sizeof(mem), ISC_BUFFERTYPE_TEXT); + isc_buffer_init(&buf, mem, sizeof(mem)); result = dns_rdataset_totext(&rds, name, ISC_FALSE, ISC_FALSE, &buf); /* Get rid of final newline. */ INSIST(buf.used >= 1 && ((char *) buf.base)[buf.used-1] == '\n'); buf.used--; - - if (result == DNS_R_SUCCESS) { - isc_buffer_used(&buf, &r); + + /* + * We could use xfrout_log(), but that would produce + * very long lines with a repetitive prefix. + */ + if (result == ISC_R_SUCCESS) { + isc_buffer_usedregion(&buf, &r); isc_log_write(XFROUT_DEBUG_LOGARGS(8), "%.*s", (int) r.length, (char *) r.base); } else { @@ -320,7 +317,9 @@ typedef struct ixfr_rrstream { } ixfr_rrstream_t; /* Forward declarations. */ -static void ixfr_rrstream_destroy(rrstream_t **sp); +static void +ixfr_rrstream_destroy(rrstream_t **sp); + static rrstream_methods_t ixfr_rrstream_methods; /* @@ -342,7 +341,7 @@ ixfr_rrstream_create(isc_mem_t *mctx, s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) - return (DNS_R_NOMEMORY); + return (ISC_R_NOMEMORY); s->common.mctx = mctx; s->common.methods = &ixfr_rrstream_methods; s->journal = NULL; @@ -352,7 +351,7 @@ ixfr_rrstream_create(isc_mem_t *mctx, CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial)); *sp = (rrstream_t *) s; - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); failure: ixfr_rrstream_destroy((rrstream_t **) &s); @@ -360,20 +359,17 @@ ixfr_rrstream_create(isc_mem_t *mctx, } static isc_result_t -ixfr_rrstream_first(rrstream_t *rs) -{ +ixfr_rrstream_first(rrstream_t *rs) { ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs; return (dns_journal_first_rr(s->journal)); } static isc_result_t -ixfr_rrstream_next(rrstream_t *rs) -{ +ixfr_rrstream_next(rrstream_t *rs) { ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs; return (dns_journal_next_rr(s->journal)); } - static void ixfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, @@ -391,8 +387,7 @@ ixfr_rrstream_destroy(rrstream_t **rsp) { isc_mem_put(s->common.mctx, s, sizeof(*s)); } -static rrstream_methods_t ixfr_rrstream_methods = -{ +static rrstream_methods_t ixfr_rrstream_methods = { ixfr_rrstream_first, ixfr_rrstream_next, ixfr_rrstream_current, @@ -415,15 +410,17 @@ typedef struct axfr_rrstream { isc_boolean_t it_valid; } axfr_rrstream_t; -/* Forward declarations. */ -static void axfr_rrstream_destroy(rrstream_t **rsp); +/* + * Forward declarations. + */ +static void +axfr_rrstream_destroy(rrstream_t **rsp); + static rrstream_methods_t axfr_rrstream_methods; static isc_result_t -axfr_rrstream_create(isc_mem_t *mctx, - dns_db_t *db, - dns_dbversion_t *ver, - rrstream_t **sp) +axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver, + rrstream_t **sp) { axfr_rrstream_t *s; isc_result_t result; @@ -432,7 +429,7 @@ axfr_rrstream_create(isc_mem_t *mctx, s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) - return (DNS_R_NOMEMORY); + return (ISC_R_NOMEMORY); s->common.mctx = mctx; s->common.methods = &axfr_rrstream_methods; s->it_valid = ISC_FALSE; @@ -441,7 +438,7 @@ axfr_rrstream_create(isc_mem_t *mctx, s->it_valid = ISC_TRUE; *sp = (rrstream_t *) s; - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); failure: axfr_rrstream_destroy((rrstream_t **) &s); @@ -449,11 +446,12 @@ axfr_rrstream_create(isc_mem_t *mctx, } static isc_result_t -axfr_rrstream_first(rrstream_t *rs) -{ +axfr_rrstream_first(rrstream_t *rs) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; isc_result_t result; result = db_rr_iterator_first(&s->it); + if (result != ISC_R_SUCCESS) + return (result); /* Skip SOA records. */ for (;;) { dns_name_t *name_dummy = NULL; @@ -464,15 +462,14 @@ axfr_rrstream_first(rrstream_t *rs) if (rdata->type != dns_rdatatype_soa) break; result = db_rr_iterator_next(&s->it); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) break; } return (result); } static isc_result_t -axfr_rrstream_next(rrstream_t *rs) -{ +axfr_rrstream_next(rrstream_t *rs) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; isc_result_t result; @@ -482,7 +479,7 @@ axfr_rrstream_next(rrstream_t *rs) isc_uint32_t ttl_dummy; dns_rdata_t *rdata = NULL; result = db_rr_iterator_next(&s->it); - if (result != DNS_R_SUCCESS) + if (result != ISC_R_SUCCESS) break; db_rr_iterator_current(&s->it, &name_dummy, &ttl_dummy, &rdata); @@ -493,9 +490,8 @@ axfr_rrstream_next(rrstream_t *rs) } static void -axfr_rrstream_current(rrstream_t *rs, - dns_name_t **name, isc_uint32_t *ttl, - dns_rdata_t **rdata) +axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, + dns_rdata_t **rdata) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; db_rr_iterator_current(&s->it, name, ttl, rdata); @@ -509,8 +505,7 @@ axfr_rrstream_destroy(rrstream_t **rsp) { isc_mem_put(s->common.mctx, s, sizeof(*s)); } -static rrstream_methods_t axfr_rrstream_methods = -{ +static rrstream_methods_t axfr_rrstream_methods = { axfr_rrstream_first, axfr_rrstream_next, axfr_rrstream_current, @@ -528,14 +523,16 @@ typedef struct soa_rrstream { dns_difftuple_t *soa_tuple; } soa_rrstream_t; -/* Forward declarations. */ -static void soa_rrstream_destroy(rrstream_t **rsp); +/* + * Forward declarations. + */ +static void +soa_rrstream_destroy(rrstream_t **rsp); + static rrstream_methods_t soa_rrstream_methods; static isc_result_t -soa_rrstream_create(isc_mem_t *mctx, - dns_db_t *db, - dns_dbversion_t *ver, +soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver, rrstream_t **sp) { soa_rrstream_t *s; @@ -545,7 +542,7 @@ soa_rrstream_create(isc_mem_t *mctx, s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) - return (DNS_R_NOMEMORY); + return (ISC_R_NOMEMORY); s->common.mctx = mctx; s->common.methods = &soa_rrstream_methods; s->soa_tuple = NULL; @@ -554,7 +551,7 @@ soa_rrstream_create(isc_mem_t *mctx, &s->soa_tuple)); *sp = (rrstream_t *) s; - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); failure: soa_rrstream_destroy((rrstream_t **) &s); @@ -564,18 +561,17 @@ soa_rrstream_create(isc_mem_t *mctx, static isc_result_t soa_rrstream_first(rrstream_t *rs) { UNUSED(rs); - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } static isc_result_t soa_rrstream_next(rrstream_t *rs) { UNUSED(rs); - return (DNS_R_NOMORE); + return (ISC_R_NOMORE); } static void -soa_rrstream_current(rrstream_t *rs, - dns_name_t **name, isc_uint32_t *ttl, +soa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, dns_rdata_t **rdata) { soa_rrstream_t *s = (soa_rrstream_t *) rs; @@ -592,8 +588,7 @@ soa_rrstream_destroy(rrstream_t **rsp) { isc_mem_put(s->common.mctx, s, sizeof(*s)); } -static rrstream_methods_t soa_rrstream_methods = -{ +static rrstream_methods_t soa_rrstream_methods = { soa_rrstream_first, soa_rrstream_next, soa_rrstream_current, @@ -618,9 +613,15 @@ typedef struct compound_rrstream { isc_result_t result; } compound_rrstream_t; -/* Forward declarations. */ -static void compound_rrstream_destroy(rrstream_t **rsp); -static isc_result_t compound_rrstream_next(rrstream_t *rs); +/* + * Forward declarations. + */ +static void +compound_rrstream_destroy(rrstream_t **rsp); + +static isc_result_t +compound_rrstream_next(rrstream_t *rs); + static rrstream_methods_t compound_rrstream_methods; /* @@ -637,10 +638,8 @@ static rrstream_methods_t compound_rrstream_methods; * when the compound_rrstream_t is destroyed. */ static isc_result_t -compound_rrstream_create(isc_mem_t *mctx, - rrstream_t **soa_stream, - rrstream_t **data_stream, - rrstream_t **sp) +compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream, + rrstream_t **data_stream, rrstream_t **sp) { compound_rrstream_t *s; @@ -648,7 +647,7 @@ compound_rrstream_create(isc_mem_t *mctx, s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) - return (DNS_R_NOMEMORY); + return (ISC_R_NOMEMORY); s->common.mctx = mctx; s->common.methods = &compound_rrstream_methods; s->components[0] = *soa_stream; @@ -660,7 +659,7 @@ compound_rrstream_create(isc_mem_t *mctx, *soa_stream = NULL; *data_stream = NULL; *sp = (rrstream_t *) s; - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); } static isc_result_t @@ -670,7 +669,7 @@ compound_rrstream_first(rrstream_t *rs) { do { rrstream_t *curstream = s->components[s->state]; s->result = curstream->methods->first(curstream); - } while (s->result == DNS_R_NOMORE && s->state < 2) ; + } while (s->result == ISC_R_NOMORE && s->state < 2) ; return (s->result); } @@ -679,9 +678,9 @@ compound_rrstream_next(rrstream_t *rs) { compound_rrstream_t *s = (compound_rrstream_t *) rs; rrstream_t *curstream = s->components[s->state]; s->result = curstream->methods->next(curstream); - while (s->result == DNS_R_NOMORE) { + while (s->result == ISC_R_NOMORE) { if (s->state == 2) - return (DNS_R_NOMORE); + return (ISC_R_NOMORE); s->state++; curstream = s->components[s->state]; s->result = curstream->methods->first(curstream); @@ -690,14 +689,13 @@ compound_rrstream_next(rrstream_t *rs) { } static void -compound_rrstream_current(rrstream_t *rs, - dns_name_t **name, isc_uint32_t *ttl, - dns_rdata_t **rdata) +compound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, + dns_rdata_t **rdata) { compound_rrstream_t *s = (compound_rrstream_t *) rs; rrstream_t *curstream; INSIST(0 <= s->state && s->state < 3); - INSIST(s->result == DNS_R_SUCCESS); + INSIST(s->result == ISC_R_SUCCESS); curstream = s->components[s->state]; curstream->methods->current(curstream, name, ttl, rdata); } @@ -711,8 +709,7 @@ compound_rrstream_destroy(rrstream_t **rsp) { isc_mem_put(s->common.mctx, s, sizeof(*s)); } -static rrstream_methods_t compound_rrstream_methods = -{ +static rrstream_methods_t compound_rrstream_methods = { compound_rrstream_first, compound_rrstream_next, compound_rrstream_current, @@ -761,19 +758,35 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, isc_boolean_t many_answers, xfrout_ctx_t **xfrp); -static void sendstream(xfrout_ctx_t *xfr); +static void +sendstream(xfrout_ctx_t *xfr); + +static void +xfrout_senddone(isc_task_t *task, isc_event_t *event); + +static void +xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, char *msg); + +static void +xfrout_maybe_destroy(xfrout_ctx_t *xfr); + +static void +xfrout_ctx_destroy(xfrout_ctx_t **xfrp); + +static void +xfrout_client_shutdown(void *arg, isc_result_t result); -static void xfrout_senddone(isc_task_t *task, isc_event_t *event); -static void xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, char *msg); -static void xfrout_maybe_destroy(xfrout_ctx_t *xfr); -static void xfrout_ctx_destroy(xfrout_ctx_t **xfrp); -static void xfrout_client_shutdown(void *arg, isc_result_t result); +static void +xfrout_log1(ns_client_t *client, dns_name_t *zonename, int level, + const char *fmt, ...); + +static void +xfrout_log(xfrout_ctx_t *xfr, unsigned int level, const char *fmt, ...); /**************************************************************************/ void -ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) -{ +ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { isc_result_t result; dns_name_t *question_name; dns_rdataset_t *question_rdataset; @@ -794,7 +807,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) dns_message_t *request = client->message; xfrout_ctx_t *xfr = NULL; isc_quota_t *quota = NULL; - dns_transfer_format_t format = ns_g_server->transfer_format; + dns_transfer_format_t format = client->view->transfer_format; isc_netaddr_t na; dns_peer_t *peer = NULL; @@ -810,15 +823,16 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) break; } - isc_log_write(XFROUT_DEBUG_LOGARGS(6), "got %s request", mnemonic); - + ns_client_log(client, + DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, + ISC_LOG_DEBUG(6), "%s request", mnemonic); /* * Apply quota. */ result = isc_quota_attach(&ns_g_server->xfroutquota, "a); - if (result != DNS_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING, - "zone transfer request denied: %s", + "%s request denied: %s", mnemonic, isc_result_totext(result)); goto failure; } @@ -827,7 +841,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) * Interpret the question section. */ result = dns_message_firstname(request, DNS_SECTION_QUESTION); - INSIST(result == DNS_R_SUCCESS); + INSIST(result == ISC_R_SUCCESS); /* * The question section must contain exactly one question, and @@ -839,44 +853,43 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) question_class = question_rdataset->rdclass; INSIST(question_rdataset->type == reqtype); if (ISC_LIST_NEXT(question_rdataset, link) != NULL) - FAILC(DNS_R_FORMERR, - "multiple questions in AXFR/IXFR request"); + FAILC(DNS_R_FORMERR, "multiple questions"); result = dns_message_nextname(request, DNS_SECTION_QUESTION); - if (result != DNS_R_NOMORE) - FAILC(DNS_R_FORMERR, - "multiple questions in AXFR/IXFR request"); - - result = dns_zt_find(client->view->zonetable, question_name, NULL, &zone); - if (result != DNS_R_SUCCESS) - FAILC(DNS_R_NOTAUTH, - "AXFR/IXFR requested for non-authoritative zone"); + if (result != ISC_R_NOMORE) + FAILC(DNS_R_FORMERR, "multiple questions"); + + result = dns_zt_find(client->view->zonetable, question_name, 0, NULL, + &zone); + if (result != ISC_R_SUCCESS) + FAILC(DNS_R_NOTAUTH, "non-authoritative zone"); switch(dns_zone_gettype(zone)) { case dns_zone_master: case dns_zone_slave: break; /* Master and slave zones are OK for transfer. */ default: - FAILC(DNS_R_NOTAUTH, - "AXFR/IXFR requested for non-authoritative zone"); + FAILC(DNS_R_NOTAUTH, "non-authoritative zone"); } CHECK(dns_zone_getdb(zone, &db)); dns_db_currentversion(db, &ver); - isc_log_write(XFROUT_DEBUG_LOGARGS(6), "%s question section OK", - mnemonic); + xfrout_log1(client, question_name, ISC_LOG_DEBUG(6), + "%s question section OK", mnemonic); /* * Check the authority section. Look for a SOA record with * the same name and class as the question. */ for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY); - result == DNS_R_SUCCESS; + result == ISC_R_SUCCESS; result = dns_message_nextname(request, DNS_SECTION_AUTHORITY)) { soa_name = NULL; dns_message_currentname(request, DNS_SECTION_AUTHORITY, &soa_name); - /* Ignore data whose owner name is not the zone apex. */ + /* + * Ignore data whose owner name is not the zone apex. + */ if (! dns_name_equal(soa_name, question_name)) continue; @@ -884,7 +897,9 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) soa_rdataset != NULL; soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link)) { - /* Ignore non-SOA data. */ + /* + * Ignore non-SOA data. + */ if (soa_rdataset->type != dns_rdatatype_soa) continue; if (soa_rdataset->rdclass != question_class) @@ -893,7 +908,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) CHECK(dns_rdataset_first(soa_rdataset)); dns_rdataset_current(soa_rdataset, &soa_rdata); result = dns_rdataset_next(soa_rdataset); - if (result == DNS_R_SUCCESS) + if (result == ISC_R_SUCCESS) FAILC(DNS_R_FORMERR, "IXFR authority section " "has multiple SOAs"); @@ -902,36 +917,44 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) } } got_soa: - if (result != DNS_R_NOMORE) + if (result != ISC_R_NOMORE) CHECK(result); - isc_log_write(XFROUT_DEBUG_LOGARGS(6), "%s authority section OK", - mnemonic); + xfrout_log1(client, question_name, ISC_LOG_DEBUG(6), + "%s authority section OK", mnemonic); - /* Decide whether to allow this transfer. */ - CHECK(ns_client_checkacl(client, "zone transfer", - dns_zone_getxfracl(zone), - ISC_TRUE)); + /* + * Decide whether to allow this transfer. + */ + CHECK(ns_client_checkacl(client, "zone transfer", + dns_zone_getxfracl(zone), ISC_TRUE)); - /* AXFR over UDP is not possible. */ + /* + * AXFR over UDP is not possible. + */ if (reqtype == dns_rdatatype_axfr && (client->attributes & NS_CLIENTATTR_TCP) == 0) { FAILC(DNS_R_FORMERR, "attempted AXFR over UDP"); } - /* Look up the requesting server in the peer table. */ + /* + * Look up the requesting server in the peer table. + */ isc_netaddr_fromsockaddr(&na, &client->peeraddr); - (void) dns_peerlist_peerbyaddr(client->view->peers, - &na, &peer); + (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer); - /* Decide on the transfer format (one-answer or many-answers). */ + /* + * Decide on the transfer format (one-answer or many-answers). + */ if (peer != NULL) - (void) dns_peer_gettransferformat(peer, &format); + (void)dns_peer_gettransferformat(peer, &format); - /* Get a dynamically allocated copy of the current SOA. */ + /* + * Get a dynamically allocated copy of the current SOA. + */ CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS, ¤t_soa_tuple)); - + if (reqtype == dns_rdatatype_ixfr) { isc_uint32_t begin_serial, current_serial; isc_boolean_t provide_ixfr; @@ -940,7 +963,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) * Outgoing IXFR may have been disabled for this peer * or globally. */ - provide_ixfr = ns_g_server->provide_ixfr; + provide_ixfr = client->view->provideixfr; if (peer != NULL) (void) dns_peer_getprovideixfr(peer, &provide_ixfr); if (provide_ixfr == ISC_FALSE) @@ -976,10 +999,10 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) current_serial, &data_stream); if (result == ISC_R_NOTFOUND || - result == DNS_R_RANGE) { - isc_log_write(XFROUT_DEBUG_LOGARGS(4), - "IXFR version not in journal, " - "falling back to AXFR"); + result == ISC_R_RANGE) { + xfrout_log1(client, question_name, ISC_LOG_DEBUG(4), + "IXFR version not in journal, " + "falling back to AXFR"); goto axfr_fallback; } CHECK(result); @@ -989,7 +1012,9 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) &data_stream)); } - /* Bracket the the data stream with SOAs. */ + /* + * Bracket the the data stream with SOAs. + */ CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream)); CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream, &stream)); @@ -1024,7 +1049,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) sendstream(xfr); xfr = NULL; - result = DNS_R_SUCCESS; + result = ISC_R_SUCCESS; failure: if (quota != NULL) @@ -1046,16 +1071,14 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) /* XXX kludge */ if (xfr != NULL) { xfrout_fail(xfr, result, "setting up zone transfer"); - } else if (result != DNS_R_SUCCESS) { - isc_log_write(XFROUT_DEBUG_LOGARGS(3), - "zone transfer setup failed"); + } else if (result != ISC_R_SUCCESS) { + ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, + NS_LOGMODULE_XFER_OUT, + ISC_LOG_DEBUG(3), "zone transfer setup failed"); ns_client_error(client, result); } } - - - static isc_result_t xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype, @@ -1075,7 +1098,7 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, INSIST(xfrp != NULL && *xfrp == NULL); xfr = isc_mem_get(mctx, sizeof(*xfr)); if (xfr == NULL) - return (DNS_R_NOMEMORY); + return (ISC_R_NOMEMORY); xfr->mctx = mctx; xfr->client = NULL; ns_client_attach(client, &xfr->client); @@ -1109,10 +1132,10 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, len = 65535; mem = isc_mem_get(mctx, len); if (mem == NULL) { - result = DNS_R_NOMEMORY; + result = ISC_R_NOMEMORY; goto failure; } - isc_buffer_init(&xfr->buf, mem, len, ISC_BUFFERTYPE_BINARY); + isc_buffer_init(&xfr->buf, mem, len); /* * Allocate another temporary buffer for the compressed @@ -1121,12 +1144,11 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, len = 2 + 65535; mem = isc_mem_get(mctx, len); if (mem == NULL) { - result = DNS_R_NOMEMORY; + result = ISC_R_NOMEMORY; goto failure; } - isc_buffer_init(&xfr->txlenbuf, mem, 2, ISC_BUFFERTYPE_BINARY); - isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2, - ISC_BUFFERTYPE_BINARY); + isc_buffer_init(&xfr->txlenbuf, mem, 2); + isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2); xfr->txmem = mem; xfr->txmemlen = len; @@ -1148,7 +1170,7 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, xfr->client->shutdown_arg = xfr; *xfrp = xfr; - return (DNS_R_SUCCESS); + return (ISC_R_SUCCESS); failure: xfrout_ctx_destroy(&xfr); @@ -1165,8 +1187,7 @@ failure: * _first method of the iterator has been called). */ static void -sendstream(xfrout_ctx_t *xfr) -{ +sendstream(xfrout_ctx_t *xfr) { dns_message_t *msg = NULL; isc_result_t result; isc_region_t used; @@ -1224,7 +1245,7 @@ sendstream(xfrout_ctx_t *xfr) if (result != ISC_R_SUCCESS) goto failure; dns_name_init(qname, NULL); - isc_buffer_available(&xfr->buf, &r); + isc_buffer_availableregion(&xfr->buf, &r); INSIST(r.length >= xfr->qname->length); r.length = xfr->qname->length; isc_buffer_putmem(&xfr->buf, xfr->qname->ndata, @@ -1258,7 +1279,7 @@ sendstream(xfrout_ctx_t *xfr) xfr->stream->methods->current(xfr->stream, &name, &ttl, &rdata); size = name->length + 10 + rdata->length; - isc_buffer_available(&xfr->buf, &r); + isc_buffer_availableregion(&xfr->buf, &r); if (size >= r.length) { /* * RR would not fit. If there are other RRs in the @@ -1273,10 +1294,9 @@ sendstream(xfrout_ctx_t *xfr) * slave. */ if (n_rrs == 0) { - isc_log_write(XFROUT_COMMON_LOGARGS, - ISC_LOG_WARNING, - "RR too large for zone transfer " - "(%d bytes)", size); + xfrout_log(xfr, ISC_LOG_WARNING, + "RR too large for zone transfer " + "(%d bytes)", size); /* XXX DNS_R_RRTOOLARGE? */ result = ISC_R_NOSPACE; goto failure; @@ -1288,7 +1308,7 @@ sendstream(xfrout_ctx_t *xfr) dns_message_gettempname(msg, &msgname); dns_name_init(msgname, NULL); - isc_buffer_available(&xfr->buf, &r); + isc_buffer_availableregion(&xfr->buf, &r); INSIST(r.length >= name->length); r.length = name->length; isc_buffer_putmem(&xfr->buf, name->ndata, name->length); @@ -1298,7 +1318,7 @@ sendstream(xfrout_ctx_t *xfr) isc_buffer_add(&xfr->buf, 10); dns_message_gettemprdata(msg, &msgrdata); - isc_buffer_available(&xfr->buf, &r); + isc_buffer_availableregion(&xfr->buf, &r); r.length = rdata->length; isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length); dns_rdata_init(msgrdata); @@ -1316,14 +1336,14 @@ sendstream(xfrout_ctx_t *xfr) dns_message_gettemprdataset(msg, &msgrds); dns_rdataset_init(msgrds); result = dns_rdatalist_tordataset(msgrdl, msgrds); - INSIST(result == DNS_R_SUCCESS); + INSIST(result == ISC_R_SUCCESS); ISC_LIST_APPEND(msgname->list, msgrds, link); dns_message_addname(msg, msgname, DNS_SECTION_ANSWER); result = xfr->stream->methods->next(xfr->stream); - if (result == DNS_R_NOMORE) { + if (result == ISC_R_NOMORE) { xfr->end_of_stream = ISC_TRUE; break; } @@ -1339,21 +1359,21 @@ sendstream(xfrout_ctx_t *xfr) CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0)); CHECK(dns_message_renderend(msg)); - isc_buffer_used(&xfr->txbuf, &used); + isc_buffer_usedregion(&xfr->txbuf, &used); isc_buffer_putuint16(&xfr->txlenbuf, used.length); region.base = xfr->txlenbuf.base; region.length = 2 + used.length; - isc_log_write(XFROUT_DEBUG_LOGARGS(8), - "sending zone transfer TCP message of %d bytes", - used.length); + xfrout_log(xfr, ISC_LOG_DEBUG(8), + "sending TCP message of %d bytes", + used.length); CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */ ®ion, xfr->client->task, xfrout_senddone, xfr)); xfr->sends++; } else { - isc_log_write(XFROUT_DEBUG_LOGARGS(8), - "sending IXFR UDP response"); + xfrout_log(xfr, ISC_LOG_DEBUG(8), + "sending IXFR UDP response"); /* XXX kludge */ dns_message_destroy(&xfr->client->message); xfr->client->message = msg; @@ -1385,7 +1405,7 @@ sendstream(xfrout_ctx_t *xfr) if (msg != NULL) { dns_message_destroy(&msg); } - if (result == DNS_R_SUCCESS) + if (result == ISC_R_SUCCESS) return; xfrout_fail(xfr, result, "sending zone data"); @@ -1426,15 +1446,19 @@ xfrout_ctx_destroy(xfrout_ctx_t **xfrp) { static void xfrout_senddone(isc_task_t *task, isc_event_t *event) { - isc_socketevent_t *sev = (isc_socketevent_t *) event; - xfrout_ctx_t *xfr = (xfrout_ctx_t *) event->arg; + isc_socketevent_t *sev = (isc_socketevent_t *)event; + xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg; isc_result_t evresult = sev->result; + UNUSED(task); - INSIST(event->type == ISC_SOCKEVENT_SENDDONE); + + INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE); + isc_event_free(&event); xfr->sends--; INSIST(xfr->sends == 0); - (void) isc_timer_touch(xfr->client->timer); + + (void)isc_timer_touch(xfr->client->timer); if (xfr->shuttingdown == ISC_TRUE) { xfrout_maybe_destroy(xfr); } else if (evresult != ISC_R_SUCCESS) { @@ -1443,20 +1467,18 @@ xfrout_senddone(isc_task_t *task, isc_event_t *event) { sendstream(xfr); } else { /* End of zone transfer stream. */ - isc_log_write(XFROUT_DEBUG_LOGARGS(6), - "end of outgoing zone transfer"); - ns_client_next(xfr->client, DNS_R_SUCCESS); + xfrout_log(xfr, ISC_LOG_DEBUG(6), + "end of transfer"); + ns_client_next(xfr->client, ISC_R_SUCCESS); xfrout_ctx_destroy(&xfr); } } static void -xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, char *msg) -{ +xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, char *msg) { xfr->shuttingdown = ISC_TRUE; - isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_ERROR, - "outgoing zone transfer: %s: %s", - msg, isc_result_totext(result)); + xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s", + msg, isc_result_totext(result)); xfrout_maybe_destroy(xfr); } @@ -1477,8 +1499,49 @@ xfrout_maybe_destroy(xfrout_ctx_t *xfr) { } static void -xfrout_client_shutdown(void *arg, isc_result_t result) -{ +xfrout_client_shutdown(void *arg, isc_result_t result) { xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg; xfrout_fail(xfr, result, "aborted"); } + +/* + * Log outgoing zone transfer messages in a format like + * <client>: transfer of <zone>: <message> + */ +static void +xfrout_logv(ns_client_t *client, dns_name_t *zonename, int level, + const char *fmt, va_list ap) +{ + char msgbuf[2048]; + char namebuf[1024]; + + dns_name_format(zonename, namebuf, sizeof(namebuf)); + vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); + ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, + NS_LOGMODULE_XFER_OUT, level, + "transfer of '%s': %s", namebuf, msgbuf); +} + +/* + * Logging function for use when a xfrout_ctx_t has not yet been created. + */ +static void +xfrout_log1(ns_client_t *client, dns_name_t *zonename, int level, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + xfrout_logv(client, zonename, level, fmt, ap); + va_end(ap); +} + +/* + * Logging function for use when there is a xfrout_ctx_t. + */ +static void +xfrout_log(xfrout_ctx_t *xfr, unsigned int level, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + xfrout_logv(xfr->client, xfr->qname, level, fmt, ap); + va_end(ap); +} |