checkpoint: IPv6 response synthesis implemented for the forward

mapping case but still disabled due to lack of configurability
This commit is contained in:
Andreas Gustafsson
2001-01-07 22:18:00 +00:00
parent b23f160d5b
commit 501f6a2fa5

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.166 2001/01/07 22:06:12 gson Exp $ */
/* $Id: query.c,v 1.167 2001/01/07 22:18:00 gson Exp $ */
#include <config.h>
@@ -24,6 +24,7 @@
#include <isc/mem.h>
#include <isc/util.h>
#include <dns/adb.h>
#include <dns/db.h>
#include <dns/events.h>
#include <dns/message.h>
@@ -97,6 +98,21 @@ query_adda6rrset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset,
static void
query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype);
static void
synth_fwd_start(ns_client_t *client);
static void
synth_fwd_startfind(ns_client_t *client);
static void
synth_fwd_respond(ns_client_t *client, dns_adbfind_t *find);
static void
synth_fwd_finddone(isc_task_t *task, isc_event_t *ev);
static void
synth_fwd_finish(ns_client_t *client, isc_result_t result);
/*
* Increment query statistics counters.
*/
@@ -3353,8 +3369,242 @@ ns_query_start(ns_client_t *client) {
*/
if (WANTDNSSEC(client))
message->flags |= DNS_MESSAGEFLAG_AD;
if (RECURSIONOK(client) &&
ISC_FALSE && /* XXX configurable via option allow-v6-synthesis */
client->message->rdclass == dns_rdataclass_in) {
if (qtype == dns_rdatatype_aaaa) {
qclient = NULL;
ns_client_attach(client, &qclient);
synth_fwd_start(qclient);
return;
}
#ifdef notyet
else if (qtype == dns_rdatatype_ptr &&
dns_name_issubdomain(query->qname, &inaddrintname)) {
qclient = NULL;
ns_client_attach(client, &qclient);
synth_rev_start(qclient);
return;
}
#endif
}
qclient = NULL;
ns_client_attach(client, &qclient);
query_find(qclient, NULL, qtype);
}
/*
* Generate a synthetic IPv6 forward mapping response for the current
* query of 'client'.
*/
static void
synth_fwd_start(ns_client_t *client) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY,
ISC_LOG_DEBUG(5), "generating synthetic AAAA response");
synth_fwd_startfind(client);
}
/*
* Start an ADB find to get addresses, or more addresses, for
* a synthetic IPv6 forward mapping response.
*/
static void
synth_fwd_startfind(ns_client_t *client) {
dns_adbfind_t *find = NULL;
isc_result_t result;
dns_fixedname_t target_fixed;
dns_name_t *target;
dns_fixedname_init(&target_fixed);
target = dns_fixedname_name(&target_fixed);
find_again:
result = dns_adb_createfind(client->view->adb, client->task,
synth_fwd_finddone, client, client->query.qname,
dns_rootname,
DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_RETURNLAME |
DNS_ADBFIND_INET6, client->now,
target, 0, &find);
ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY,
ISC_LOG_DEBUG(5), "find returned %s",
isc_result_totext(result));
if (result == DNS_R_ALIAS) {
dns_name_t *ptarget = NULL;
dns_name_t *tname = NULL;
isc_buffer_t *dbuf;
isc_buffer_t b;
/*
* Make a persistent copy of the 'target' name data in 'ptarget';
* it will become the new query name.
*/
dbuf = query_getnamebuf(client);
if (dbuf == NULL)
goto fail;
ptarget = query_newname(client, dbuf, &b);
if (ptarget == NULL)
goto fail;
dns_name_copy(target, ptarget, NULL);
dns_adb_destroyfind(&find);
/*
* Get another temporary name 'tname' for insertion into the
* response message.
*/
result = dns_message_gettempname(client->message, &tname);
if (result != ISC_R_SUCCESS)
goto fail;
dns_name_init(tname, NULL);
result = query_addcname(client, client->query.qname, ptarget,
0 /* XXX ttl */, &tname);
if (tname != NULL)
dns_message_puttempname(client->message, &tname);
if (result != ISC_R_SUCCESS)
goto fail;
query_maybeputqname(client);
client->query.qname = ptarget;
query_keepname(client, ptarget, dbuf);
ptarget = NULL;
client->query.restarts++;
goto find_again;
} else if (result != ISC_R_SUCCESS) {
if (find != NULL)
dns_adb_destroyfind(&find);
goto fail;
}
if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY,
ISC_LOG_DEBUG(5), "find will send event");
} else {
synth_fwd_respond(client, find);
dns_adb_destroyfind(&find);
}
return;
fail:
synth_fwd_finish(client, DNS_R_SERVFAIL);
return;
}
/*
* Handle an ADB finddone event generated as part of synthetic IPv6
* forward mapping processing.
*/
static void
synth_fwd_finddone(isc_task_t *task, isc_event_t *ev) {
ns_client_t *client = ev->ev_arg;
dns_adbfind_t *find = ev->ev_sender;
isc_eventtype_t evtype = ev->ev_type;
UNUSED(task);
ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY,
ISC_LOG_DEBUG(5), "got find event");
if (evtype == DNS_EVENT_ADBNOMOREADDRESSES)
synth_fwd_respond(client, find);
else if (evtype == DNS_EVENT_ADBMOREADDRESSES)
synth_fwd_startfind(client);
else
synth_fwd_finish(client, DNS_R_SERVFAIL);
isc_event_free(&ev);
dns_adb_destroyfind(&find);
}
/*
* Generate a synthetic IPv6 forward mapping response based on
* a completed ADB lookup.
*/
static void
synth_fwd_respond(ns_client_t *client, dns_adbfind_t *find) {
dns_adbaddrinfo_t *ai;
dns_name_t *tname = NULL;
dns_rdataset_t *rdataset = NULL;
dns_rdatalist_t *rdatalist = NULL;
isc_result_t result;
result = dns_message_gettempname(client->message, &tname);
if (result != ISC_R_SUCCESS)
goto cleanup;
dns_name_init(tname, NULL);
result = dns_message_gettemprdatalist(client->message, &rdatalist);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_message_gettemprdataset(client->message, &rdataset);
if (result != ISC_R_SUCCESS)
goto cleanup;
dns_rdataset_init(rdataset);
ISC_LIST_INIT(rdatalist->rdata);
rdatalist->type = dns_rdatatype_aaaa;
rdatalist->covers = 0;
rdatalist->rdclass = client->message->rdclass;
rdatalist->ttl = 0;
dns_name_clone(client->query.qname, tname);
for (ai = ISC_LIST_HEAD(find->list);
ai != NULL;
ai = ISC_LIST_NEXT(ai, publink)) {
dns_rdata_t *rdata = NULL;
struct sockaddr_in6 *sin6 = &ai->sockaddr.type.sin6;
/*
* Could it be useful to return IPv4 addresses as A records?
*/
if (sin6->sin6_family != AF_INET6)
continue;
result = dns_message_gettemprdata(client->message, &rdata);
if (result != ISC_R_SUCCESS)
goto cleanup;
rdata->data = (unsigned char *) &sin6->sin6_addr;
rdata->length = 16;
rdata->rdclass = client->message->rdclass;
rdata->type = dns_rdatatype_aaaa;
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
}
dns_rdatalist_tordataset(rdatalist, rdataset);
query_addrrset(client, &tname, &rdataset, NULL, NULL,
DNS_SECTION_ANSWER);
cleanup:
if (tname != NULL)
dns_message_puttempname(client->message, &tname);
if (rdataset != NULL) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
dns_message_puttemprdataset(client->message, &rdataset);
}
synth_fwd_finish(client, result);
}
/*
* Finish synthetic IPv6 forward mapping processing.
*/
static void
synth_fwd_finish(ns_client_t *client, isc_result_t result) {
if (result == ISC_R_SUCCESS)
ns_client_send(client);
else
ns_client_error(client, result);
ns_client_detach(&client);
}