451 [func] Update forwarding implememted.
450. [func] New function ns_client_sendraw().
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
/*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user