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:
@@ -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;
|
||||
|
Reference in New Issue
Block a user