451 [func] Update forwarding implememted.

450.   [func]          New function ns_client_sendraw().
This commit is contained in:
Mark Andrews
2000-09-13 01:30:34 +00:00
parent f267ee3e4f
commit 459e901f90
4 changed files with 200 additions and 16 deletions

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: client.c,v 1.111 2000/09/12 18:45:30 explorer Exp $ */
/* $Id: client.c,v 1.112 2000/09/13 01:30:30 marka Exp $ */
#include <config.h>
@@ -641,6 +641,93 @@ client_senddone(isc_task_t *task, isc_event_t *event) {
ns_client_next(client, ISC_R_SUCCESS);
}
void
ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
isc_result_t result;
unsigned char *data;
isc_buffer_t buffer;
isc_region_t r;
isc_region_t *mr;
isc_socket_t *socket;
isc_sockaddr_t *address;
struct in6_pktinfo *pktinfo;
unsigned int bufsize = 512;
REQUIRE(NS_CLIENT_VALID(client));
CTRACE("sendraw");
mr = dns_message_getrawmessage(message);
if (mr == NULL) {
result = ISC_R_UNEXPECTEDEND;
goto done;
}
if (TCP_CLIENT(client)) {
INSIST(client->tcpbuf == NULL);
if (mr->length + 2 > TCP_BUFFER_SIZE) {
result = ISC_R_NOSPACE;
goto done;
}
client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
if (client->tcpbuf == NULL) {
result = ISC_R_NOMEMORY;
goto done;
}
data = client->tcpbuf;
isc_buffer_init(&buffer, data, TCP_BUFFER_SIZE);
isc_buffer_putuint16(&buffer, mr->length);
} else {
data = client->sendbuf;
if (client->udpsize < SEND_BUFFER_SIZE)
bufsize = client->udpsize;
else
bufsize = SEND_BUFFER_SIZE;
if (mr->length + 2 > bufsize) {
result = ISC_R_NOSPACE;
goto done;
}
isc_buffer_init(&buffer, data, bufsize);
}
/*
* Copy message to buffer and fixup id.
*/
isc_buffer_availableregion(&buffer, &r);
result = isc_buffer_copyregion(&buffer, mr);
if (result != ISC_R_SUCCESS)
goto done;
r.base[0] = (client->message->id >> 8) & 0xff;
r.base[1] = client->message->id & 0xff;
if (TCP_CLIENT(client)) {
socket = client->tcpsocket;
address = NULL;
} else {
socket = dns_dispatch_getsocket(client->dispatch);
address = &client->dispevent->addr;
}
isc_buffer_usedregion(&buffer, &r);
CTRACE("sendto");
if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0)
pktinfo = &client->pktinfo;
else
pktinfo = NULL;
result = isc_socket_sendto(socket, &r, client->task, client_senddone,
client, address, pktinfo);
if (result == ISC_R_SUCCESS) {
client->nsends++;
return;
}
done:
if (client->tcpbuf != NULL) {
isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
client->tcpbuf = NULL;
}
ns_client_next(client, result);
}
void
ns_client_send(ns_client_t *client) {
isc_result_t result;
@@ -861,6 +948,7 @@ client_request(isc_task_t *task, isc_event_t *event) {
ns_client_t *client;
dns_dispatchevent_t *devent;
isc_result_t result;
isc_result_t sigresult;
isc_buffer_t *buffer;
dns_view_t *view;
dns_rdataset_t *opt;
@@ -1064,12 +1152,7 @@ client_request(isc_task_t *task, isc_event_t *event) {
* not. We do not log the lack of a signature unless we are
* debugging.
*/
result = dns_message_checksig(client->message, client->view);
if (result != ISC_R_SUCCESS) {
ns_client_error(client, result);
goto cleanup_viewlock;
}
sigresult = dns_message_checksig(client->message, client->view);
client->signer = NULL;
dns_name_init(&client->signername, NULL);
result = dns_message_signer(client->message, &client->signername);
@@ -1086,12 +1169,22 @@ client_request(isc_task_t *task, isc_event_t *event) {
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
"request is signed by a nonauthoritative key");
if (client->message->tsigstatus != dns_tsigerror_badkey &&
client->message->opcode != dns_opcode_update) {
ns_client_error(client, sigresult);
goto cleanup_viewlock;
}
} else {
/* There is a signature, but it is bad. */
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
"request has invalid signature: %s",
isc_result_totext(result));
if (client->message->tsigstatus != dns_tsigerror_badkey &&
client->message->opcode != dns_opcode_update) {
ns_client_error(client, sigresult);
goto cleanup_viewlock;
}
}
/*
@@ -1122,7 +1215,7 @@ client_request(isc_task_t *task, isc_event_t *event) {
break;
case dns_opcode_update:
CTRACE("update");
ns_update_start(client);
ns_update_start(client, sigresult);
break;
case dns_opcode_notify:
CTRACE("notify");
@@ -1437,6 +1530,9 @@ ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
REQUIRE(targetp != NULL && *targetp == NULL);
source->references++;
ns_client_log(source, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
"ns_client_attach: ref = %d", source->references);
*targetp = source;
}
@@ -1447,6 +1543,9 @@ ns_client_detach(ns_client_t **clientp) {
client->references--;
INSIST(client->references >= 0);
*clientp = NULL;
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
"ns_client_detach: ref = %d", client->references);
(void) exit_check(client);
}

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: client.h,v 1.41 2000/09/12 18:45:39 explorer Exp $ */
/* $Id: client.h,v 1.42 2000/09/13 01:30:33 marka Exp $ */
#ifndef NAMED_CLIENT_H
#define NAMED_CLIENT_H 1
@@ -154,6 +154,13 @@ ns_client_send(ns_client_t *client);
* send client->message as a response.
*/
void
ns_client_sendraw(ns_client_t *client, dns_message_t *msg);
/*
* Finish processing the current client request and
* send client->message as a response.
*/
void
ns_client_error(ns_client_t *client, isc_result_t result);
/*

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: update.h,v 1.6 2000/08/01 01:12:18 tale Exp $ */
/* $Id: update.h,v 1.7 2000/09/13 01:30:34 marka Exp $ */
#ifndef NAMED_UPDATE_H
#define NAMED_UPDATE_H 1
@@ -44,6 +44,6 @@
***/
void
ns_update_start(ns_client_t *client);
ns_update_start(ns_client_t *client, isc_result_t sigresult);
#endif /* NAMED_UPDATE_H */

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: update.c,v 1.62 2000/09/12 18:45:34 explorer Exp $ */
/* $Id: update.c,v 1.63 2000/09/13 01:30:32 marka Exp $ */
#include <config.h>
@@ -48,7 +48,6 @@
/*
XXX TODO:
- forwarding
- document strict minimality
*/
@@ -157,6 +156,7 @@ struct update_event {
static void update_action(isc_task_t *task, isc_event_t *event);
static void updatedone_action(isc_task_t *task, isc_event_t *event);
static isc_result_t send_forward_event(ns_client_t *client, dns_zone_t *zone);
/**************************************************************************/
@@ -1822,7 +1822,7 @@ respond(ns_client_t *client, isc_result_t result) {
}
void
ns_update_start(ns_client_t *client) {
ns_update_start(ns_client_t *client, isc_result_t sigresult) {
dns_message_t *request = client->message;
isc_result_t result;
dns_name_t *zonename;
@@ -1865,11 +1865,20 @@ ns_update_start(ns_client_t *client) {
switch(dns_zone_gettype(zone)) {
case dns_zone_master:
/*
* We can now fail due to a bad signature as we now know
* that we are the master.
*/
if (sigresult != ISC_R_SUCCESS)
FAIL(sigresult);
CHECK(send_update_event(client, zone));
break; /* OK. */
case dns_zone_slave:
FAILS(DNS_R_NOTIMP,
"update forwarding"); /* XXX implement */
if (dns_message_gettsig(client->message, NULL) == NULL)
FAILS(DNS_R_NOTIMP,
"unsigned updates not forwarded");
CHECK(send_forward_event(client, zone));
break; /* OK. */
default:
FAILC(DNS_R_NOTAUTH,
"not authoritative for update zone");
@@ -1883,6 +1892,8 @@ ns_update_start(ns_client_t *client) {
* simply give an error response without switching tasks.
*/
respond(client, result);
if (zone != NULL)
dns_zone_detach(&zone);
}
static void
@@ -2372,3 +2383,70 @@ updatedone_action(isc_task_t *task, isc_event_t *event) {
ns_client_detach(&client);
isc_event_free(&event);
}
/*
* Update forwarding support.
*/
static void
forward_fail(ns_client_t *client, isc_result_t result) {
UNUSED(result);
respond(client, DNS_R_SERVFAIL);
}
static void
forward_callback(void *arg, isc_result_t result, dns_message_t *answer) {
ns_client_t *client = arg;
if (result != ISC_R_SUCCESS)
forward_fail(client, result);
else
ns_client_sendraw(client, answer);
ns_client_detach(&client);
}
static void
forward_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->ev_arg;
isc_result_t result;
result = dns_zone_forwardupdate(zone, client->message,
forward_callback, client);
if (result != ISC_R_SUCCESS) {
forward_fail(client, result);
ns_client_detach(&client);
}
dns_zone_detach(&zone);
isc_event_free(&event);
isc_task_detach(&task);
}
static isc_result_t
send_forward_event(ns_client_t *client, dns_zone_t *zone) {
isc_result_t result = ISC_R_SUCCESS;
update_event_t *event = NULL;
isc_task_t *zonetask = NULL;
ns_client_t *evclient;
event = (update_event_t *)
isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE,
forward_action, NULL, sizeof(*event));
if (event == NULL)
FAIL(ISC_R_NOMEMORY);
event->zone = zone;
event->result = ISC_R_SUCCESS;
evclient = NULL;
ns_client_attach(client, &evclient);
event->ev_arg = evclient;
dns_zone_gettask(zone, &zonetask);
isc_task_send(zonetask, (isc_event_t **)&event);
failure:
if (event != NULL)
isc_event_free((isc_event_t **)&event);
return (result);
}