diff --git a/CHANGES b/CHANGES index c1a5363971..2cf052c588 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,7 @@ + 352. [bug] Race condition in dns_client_t startup could cause + an assertion failure. + 351. [bug] Constructing a response with rcode SERVFAIL to a TSIG signed query could crash the server. diff --git a/bin/named/client.c b/bin/named/client.c index 3df33b3bec..65958be8cd 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -15,7 +15,7 @@ * SOFTWARE. */ -/* $Id: client.c,v 1.102 2000/07/17 23:19:14 gson Exp $ */ +/* $Id: client.c,v 1.103 2000/07/26 17:39:09 gson Exp $ */ #include @@ -163,6 +163,8 @@ static void clientmgr_destroy(ns_clientmgr_t *manager); static isc_boolean_t exit_check(ns_client_t *client); static void ns_client_endrequest(ns_client_t *client); static void ns_client_checkactive(ns_client_t *client); +static void client_start(isc_task_t *task, isc_event_t *event); +static void client_request(isc_task_t *task, isc_event_t *event); /* * Enter the inactive state. @@ -431,6 +433,45 @@ exit_check(ns_client_t *client) { return (ISC_TRUE); } +/* + * The client's task has received the client's control event + * as part of the startup process. + */ +static void +client_start(isc_task_t *task, isc_event_t *event) { + ns_client_t *client = (ns_client_t *) event->ev_arg; + isc_result_t result; + + INSIST(task == client->task); + + UNUSED(task); + + if (TCP_CLIENT(client)) { + client_accept(client); + } else { + result = dns_dispatch_addrequest(client->dispatch, + client->task, + client_request, + client, + &client->dispentry); + + if (result != ISC_R_SUCCESS) { + ns_client_log(client, + DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_CLIENT, + ISC_LOG_DEBUG(3), + "dns_dispatch_addrequest() " + "failed: %s", + isc_result_totext(result)); + /* + * Not much we can do here but log the failure; + * the client will effectively go idle. + */ + } + } +} + + /* * The client's task has received a shutdown event. */ @@ -565,14 +606,14 @@ 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->ev_type == ISC_SOCKEVENT_SENDDONE); client = sevent->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); + UNUSED(task); + CTRACE("senddone"); if (sevent->result != ISC_R_SUCCESS) @@ -1195,6 +1236,9 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) client->recursionquota = NULL; client->interface = NULL; client->peeraddr_valid = ISC_FALSE; + ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL, + DNS_EVENT_CLIENTCONTROL, client_start, client, client, + NULL, NULL); ISC_LINK_INIT(client, link); client->list = NULL; @@ -1272,7 +1316,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { UNUSED(task); INSIST(client->state == NS_CLIENTSTATE_READY); - + INSIST(client->naccepts == 1); client->naccepts--; @@ -1529,6 +1573,7 @@ ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n, LOCK(&manager->lock); for (i = 0; i < n; i++) { + isc_event_t *ev; /* * Allocate a client. First try to get a recycled one; * if that fails, make a new one. @@ -1553,30 +1598,16 @@ ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n, client->attributes |= NS_CLIENTATTR_TCP; isc_socket_attach(ifp->tcpsocket, &client->tcplistener); - client_accept(client); } else { dns_dispatch_attach(ifp->udpdispatch, &client->dispatch); - result = dns_dispatch_addrequest(client->dispatch, - client->task, - client_request, - client, - &client->dispentry); - if (result != ISC_R_SUCCESS) { - ns_client_log(client, - DNS_LOGCATEGORY_SECURITY, - NS_LOGMODULE_CLIENT, - ISC_LOG_DEBUG(3), - "dns_dispatch_addrequest() " - "failed: %s", - isc_result_totext(result)); - isc_task_shutdown(client->task); - break; - } } client->manager = manager; ISC_LIST_APPEND(manager->active, client, link); client->list = &manager->active; + + ev = &client->ctlevent; + isc_task_send(client->task, &ev); } if (i != 0) { /* diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index 922ce2ad3c..d1cb7750ec 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -15,7 +15,7 @@ * SOFTWARE. */ -/* $Id: client.h,v 1.37 2000/06/22 21:49:38 tale Exp $ */ +/* $Id: client.h,v 1.38 2000/07/26 17:39:11 gson Exp $ */ #ifndef NAMED_CLIENT_H #define NAMED_CLIENT_H 1 @@ -122,6 +122,7 @@ struct ns_client { isc_sockaddr_t peeraddr; isc_boolean_t peeraddr_valid; struct in6_pktinfo pktinfo; + isc_event_t ctlevent; ISC_LINK(ns_client_t) link; /* * The list 'link' is part of, or NULL if not on any list. diff --git a/lib/dns/include/dns/events.h b/lib/dns/include/dns/events.h index d49dc5cbed..da179433f2 100644 --- a/lib/dns/include/dns/events.h +++ b/lib/dns/include/dns/events.h @@ -15,7 +15,7 @@ * SOFTWARE. */ -/* $Id: events.h,v 1.24 2000/06/22 21:55:38 tale Exp $ */ +/* $Id: events.h,v 1.25 2000/07/26 17:39:12 gson Exp $ */ #ifndef DNS_EVENTS_H #define DNS_EVENTS_H 1 @@ -52,6 +52,7 @@ #define DNS_EVENT_NOTIFYSENDTOADDR (ISC_EVENTCLASS_DNS + 23) #define DNS_EVENT_ZONE (ISC_EVENTCLASS_DNS + 24) #define DNS_EVENT_ZONESTARTXFRIN (ISC_EVENTCLASS_DNS + 25) +#define DNS_EVENT_CLIENTCONTROL (ISC_EVENTCLASS_DNS + 26) #define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0) #define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)