2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 22:15:20 +00:00

2353. [func] Add support for Name Server ID (RFC 5001).

'dig +nsid' requests NSID from server.
                        'request-nsid yes;' causes recursive server to send
                        NSID requests to upstream servers.  Server responds
                        to NSID requests with the string configured by
                        'server-id' option.  [RT #17091]
This commit is contained in:
Mark Andrews
2008-04-03 02:01:08 +00:00
parent aeb7938001
commit db30f4bdcb
27 changed files with 791 additions and 347 deletions

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.c,v 1.363 2008/04/02 02:56:23 marka Exp $ */
/* $Id: resolver.c,v 1.364 2008/04/03 02:01:08 marka Exp $ */
/*! \file */
@@ -223,7 +223,7 @@ struct fetchctx {
/*%
* Look aside state for DS lookups.
*/
dns_name_t nsname;
dns_name_t nsname;
dns_fetch_t * nsfetch;
dns_rdataset_t nsrrset;
@@ -994,7 +994,8 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
}
static inline isc_result_t
fctx_addopt(dns_message_t *message, unsigned int version, isc_uint16_t udpsize)
fctx_addopt(dns_message_t *message, unsigned int version,
isc_uint16_t udpsize, isc_boolean_t request_nsid)
{
dns_rdataset_t *rdataset;
dns_rdatalist_t *rdatalist;
@@ -1030,10 +1031,23 @@ fctx_addopt(dns_message_t *message, unsigned int version, isc_uint16_t udpsize)
rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
/*
* No EDNS options.
* Set EDNS options if applicable
*/
rdata->data = NULL;
rdata->length = 0;
if (request_nsid) {
/* Send empty NSID option (RFC5001) */
unsigned char data[4];
isc_buffer_t buf;
isc_buffer_init(&buf, data, sizeof(data));
isc_buffer_putuint16(&buf, DNS_OPT_NSID);
isc_buffer_putuint16(&buf, 0);
rdata->data = data;
rdata->length = sizeof(data);
} else {
rdata->data = NULL;
rdata->length = 0;
}
rdata->rdclass = rdatalist->rdclass;
rdata->type = rdatalist->type;
rdata->flags = 0;
@@ -1549,6 +1563,7 @@ resquery_send(resquery_t *query) {
unsigned int version = 0; /* Default version. */
unsigned int flags;
isc_uint16_t udpsize = res->udpsize;
isc_boolean_t reqnsid = ISC_FALSE;
flags = query->addrinfo->flags;
if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
@@ -1559,8 +1574,17 @@ resquery_send(resquery_t *query) {
udpsize = 512;
else if (peer != NULL)
(void)dns_peer_getudpsize(peer, &udpsize);
result = fctx_addopt(fctx->qmessage, version, udpsize);
if (result != ISC_R_SUCCESS) {
/* request NSID for current view or peer? */
if (peer != NULL)
(void) dns_peer_getrequestnsid(peer, &reqnsid);
reqnsid = (reqnsid || res->view->requestnsid);
result = fctx_addopt(fctx->qmessage, version,
udpsize, reqnsid);
if (reqnsid && result == ISC_R_SUCCESS) {
query->options |= DNS_FETCHOPT_WANTNSID;
} else {
/*
* We couldn't add the OPT, but we'll press on.
* We're not using EDNS0, so set the NOEDNS0
@@ -5469,6 +5493,65 @@ checknames(dns_message_t *message) {
checknamessection(message, DNS_SECTION_ADDITIONAL);
}
/*
* Log server NSID at log level 'level'
*/
static isc_result_t
log_nsid(dns_rdataset_t *opt, resquery_t *query, int level, isc_mem_t *mctx)
{
static const char hex[17] = "0123456789abcdef";
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
isc_uint16_t optcode, nsid_len, buflen, i;
isc_result_t result;
isc_buffer_t nsidbuf;
dns_rdata_t rdata;
unsigned char *p, *buf, *nsid;
/* Extract rdata from OPT rdataset */
result = dns_rdataset_first(opt);
if (result != ISC_R_SUCCESS)
return (ISC_R_FAILURE);
dns_rdata_init(&rdata);
dns_rdataset_current(opt, &rdata);
if (rdata.length < 4)
return (ISC_R_FAILURE);
/* Check for NSID */
isc_buffer_init(&nsidbuf, rdata.data, rdata.length);
isc_buffer_add(&nsidbuf, rdata.length);
optcode = isc_buffer_getuint16(&nsidbuf);
nsid_len = isc_buffer_getuint16(&nsidbuf);
if (optcode != DNS_OPT_NSID || nsid_len == 0)
return (ISC_R_FAILURE);
/* Allocate buffer for storing hex version of the NSID */
buflen = nsid_len * 2 + 1;
buf = isc_mem_get(mctx, buflen);
if (buf == NULL)
return (ISC_R_NOSPACE);
/* Convert to hex */
p = buf;
nsid = rdata.data + 4;
for (i = 0; i < nsid_len; i++) {
*p++ = hex[(nsid[0] >> 4) & 0xf];
*p++ = hex[nsid[0] & 0xf];
nsid++;
}
*p = '\0';
isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
sizeof(addrbuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, level,
"received NSID '%s' from %s", buf, addrbuf);
/* Clean up */
isc_mem_put(mctx, buf, buflen);
return (ISC_R_SUCCESS);
}
static void
log_packet(dns_message_t *message, int level, isc_mem_t *mctx) {
isc_buffer_t buffer;
@@ -5514,6 +5597,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
isc_boolean_t keep_trying, get_nameservers, resend;
isc_boolean_t truncated;
dns_message_t *message;
dns_rdataset_t *opt;
fetchctx_t *fctx;
dns_name_t *fname;
dns_fixedname_t foundname;
@@ -5674,11 +5758,20 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
}
}
/*
* Log the incoming packet.
*/
log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx);
/*
* Did we request NSID? If so, and if the response contains
* NSID data, log it at INFO level.
*/
opt = dns_message_getopt(message);
if (opt != NULL && (query->options & DNS_FETCHOPT_WANTNSID) != 0)
log_nsid(opt, query, ISC_LOG_INFO, fctx->res->mctx);
/*
* If the message is signed, check the signature. If not, this
* returns success anyway.
@@ -5779,12 +5872,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
result = DNS_R_YXDOMAIN;
} else if (message->rcode == dns_rcode_badvers) {
dns_rdataset_t *opt;
unsigned int flags, mask;
unsigned int version;
resend = ISC_TRUE;
opt = dns_message_getopt(message);
version = (opt->ttl >> 16) & 0xff;
flags = (version << DNS_FETCHOPT_EDNSVERSIONSHIFT) |
DNS_FETCHOPT_EDNSVERSIONSET;