2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 05:28:00 +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

@ -1,3 +1,10 @@
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]
2352. [bug] Various GSS_API fixups. [RT #17729]
2351. [bug] convertxsl.pl generated very long lines. [RT #17906]

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dig.c,v 1.220 2008/02/05 23:47:08 tbox Exp $ */
/* $Id: dig.c,v 1.221 2008/04/03 02:01:08 marka Exp $ */
/*! \file */
@ -194,6 +194,7 @@ help(void) {
" +[no]identify (ID responders in short answers)\n"
" +[no]trace (Trace delegation down from root)\n"
" +[no]dnssec (Request DNSSEC records)\n"
" +[no]nsid (Request Name Server ID)\n"
#ifdef DIG_SIGCHASE
" +[no]sigchase (Chase DNSSEC signatures)\n"
" +trusted-key=#### (Trusted Key when chasing DNSSEC sigs)\n"
@ -860,21 +861,33 @@ plus_option(char *option, isc_boolean_t is_batchfile,
goto invalid_option;
ndots = parse_uint(value, "ndots", MAXNDOTS);
break;
case 's': /* nssearch */
FULLCHECK("nssearch");
lookup->ns_search_only = state;
if (state) {
lookup->trace_root = ISC_TRUE;
lookup->recurse = ISC_TRUE;
lookup->identify = ISC_TRUE;
lookup->stats = ISC_FALSE;
lookup->comments = ISC_FALSE;
lookup->section_additional = ISC_FALSE;
lookup->section_authority = ISC_FALSE;
lookup->section_question = ISC_FALSE;
lookup->rdtype = dns_rdatatype_ns;
lookup->rdtypeset = ISC_TRUE;
short_form = ISC_TRUE;
case 's':
switch (cmd[2]) {
case 'i': /* nsid */
FULLCHECK("nsid");
if (state && lookup->edns == -1)
lookup->edns = 0;
lookup->nsid = state;
break;
case 's': /* nssearch */
FULLCHECK("nssearch");
lookup->ns_search_only = state;
if (state) {
lookup->trace_root = ISC_TRUE;
lookup->recurse = ISC_TRUE;
lookup->identify = ISC_TRUE;
lookup->stats = ISC_FALSE;
lookup->comments = ISC_FALSE;
lookup->section_additional = ISC_FALSE;
lookup->section_authority = ISC_FALSE;
lookup->section_question = ISC_FALSE;
lookup->rdtype = dns_rdatatype_ns;
lookup->rdtypeset = ISC_TRUE;
short_form = ISC_TRUE;
}
break;
default:
goto invalid_option;
}
break;
default:

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dighost.c,v 1.308 2008/01/18 23:46:57 tbox Exp $ */
/* $Id: dighost.c,v 1.309 2008/04/03 02:01:08 marka Exp $ */
/*! \file
* \note
@ -724,6 +724,7 @@ make_empty_lookup(void) {
looknew->servfail_stops = ISC_TRUE;
looknew->besteffort = ISC_TRUE;
looknew->dnssec = ISC_FALSE;
looknew->nsid = ISC_FALSE;
#ifdef DIG_SIGCHASE
looknew->sigchase = ISC_FALSE;
#if DIG_SIGCHASE_TD
@ -803,6 +804,7 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
looknew->servfail_stops = lookold->servfail_stops;
looknew->besteffort = lookold->besteffort;
looknew->dnssec = lookold->dnssec;
looknew->nsid = lookold->nsid;
#ifdef DIG_SIGCHASE
looknew->sigchase = lookold->sigchase;
#if DIG_SIGCHASE_TD
@ -1155,11 +1157,11 @@ setup_libs(void) {
/*%
* Add EDNS0 option record to a message. Currently, the only supported
* options are UDP buffer size and the DO bit.
* options are UDP buffer size, the DO bit, and NSID request.
*/
static void
add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
isc_boolean_t dnssec)
isc_boolean_t dnssec, isc_boolean_t nsid)
{
dns_rdataset_t *rdataset = NULL;
dns_rdatalist_t *rdatalist = NULL;
@ -1182,8 +1184,19 @@ add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
rdatalist->ttl = edns << 16;
if (dnssec)
rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
rdata->data = NULL;
rdata->length = 0;
if (nsid) {
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;
}
ISC_LIST_INIT(rdatalist->rdata);
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
dns_rdatalist_tordataset(rdatalist, rdataset);
@ -1998,7 +2011,7 @@ setup_lookup(dig_lookup_t *lookup) {
if (lookup->edns < 0)
lookup->edns = 0;
add_opt(lookup->sendmsg, lookup->udpsize,
lookup->edns, lookup->dnssec);
lookup->edns, lookup->dnssec, lookup->nsid);
}
result = dns_message_rendersection(lookup->sendmsg,

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dig.h,v 1.105 2007/06/18 23:47:17 tbox Exp $ */
/* $Id: dig.h,v 1.106 2008/04/03 02:01:08 marka Exp $ */
#ifndef DIG_H
#define DIG_H
@ -102,7 +102,7 @@ typedef struct dig_searchlist dig_searchlist_t;
/*% The dig_lookup structure */
struct dig_lookup {
isc_boolean_t
pending, /*%< Pending a successful answer */
pending, /*%< Pending a successful answer */
waiting_connect,
doing_xfr,
ns_search_only, /*%< dig +nssearch, host -C */
@ -129,27 +129,28 @@ struct dig_lookup {
need_search,
done_as_is,
besteffort,
dnssec;
dnssec,
nsid; /*% Name Server ID (RFC 5001) */
#ifdef DIG_SIGCHASE
isc_boolean_t sigchase;
#if DIG_SIGCHASE_TD
isc_boolean_t do_topdown,
trace_root_sigchase,
rdtype_sigchaseset,
rdclass_sigchaseset;
isc_boolean_t do_topdown,
trace_root_sigchase,
rdtype_sigchaseset,
rdclass_sigchaseset;
/* Name we are going to validate RRset */
char textnamesigchase[MXNAME];
char textnamesigchase[MXNAME];
#endif
#endif
char textname[MXNAME]; /*% Name we're going to be looking up */
char cmdline[MXNAME];
dns_rdatatype_t rdtype;
dns_rdatatype_t qrdtype;
#if DIG_SIGCHASE_TD
dns_rdatatype_t rdtype_sigchase;
dns_rdatatype_t qrdtype_sigchase;
dns_rdataclass_t rdclass_sigchase;
dns_rdatatype_t rdtype_sigchase;
dns_rdatatype_t qrdtype_sigchase;
dns_rdataclass_t rdclass_sigchase;
#endif
dns_rdataclass_t rdclass;
isc_boolean_t rdtypeset;
@ -231,7 +232,7 @@ struct dig_searchlist {
};
#ifdef DIG_SIGCHASE
struct dig_message {
dns_message_t *msg;
dns_message_t *msg;
ISC_LINK(dig_message_t) link;
};
#endif
@ -249,7 +250,7 @@ extern dig_searchlistlist_t search_list;
extern unsigned int extrabytes;
extern isc_boolean_t check_ra, have_ipv4, have_ipv6, specified_source,
usesearch, showsearch, qr;
usesearch, showsearch, qr;
extern in_port_t port;
extern unsigned int timeout;
extern isc_mem_t *mctx;

View File

@ -1,5 +1,5 @@
/*
* Generated by convertxsl.pl 1.10 2008/04/02 03:35:13 marka Exp
* Generated by convertxsl.pl 1.11 2008/04/02 23:46:57 tbox Exp
* From bind9.xsl 1.15 2008/04/01 23:47:10 tbox Exp
*/
static char msg[] =

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: client.c,v 1.254 2008/03/31 05:00:29 marka Exp $ */
/* $Id: client.c,v 1.255 2008/04/03 02:01:08 marka Exp $ */
#include <config.h>
@ -48,6 +48,7 @@
#include <named/interfacemgr.h>
#include <named/log.h>
#include <named/notify.h>
#include <named/os.h>
#include <named/server.h>
#include <named/update.h>
@ -954,11 +955,9 @@ ns_client_send(ns_client_t *client) {
result = dns_message_renderbegin(client->message, &cctx, &buffer);
if (result != ISC_R_SUCCESS)
goto done;
if (client->opt != NULL) {
result = dns_message_setopt(client->message, client->opt);
/*
* XXXRTH dns_message_setopt() should probably do this...
*/
client->opt = NULL;
if (result != ISC_R_SUCCESS)
goto done;
@ -1190,11 +1189,46 @@ client_addopt(ns_client_t *client) {
*/
rdatalist->ttl = (client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE);
/*
* No EDNS options in the default case.
*/
rdata->data = NULL;
rdata->length = 0;
/* Set EDNS options if applicable */
if (client->attributes & NS_CLIENTATTR_WANTNSID &&
(ns_g_server->server_id != NULL ||
ns_g_server->server_usehostname)) {
/*
* Space required for NSID data:
* 2 bytes for opt code
* + 2 bytes for NSID length
* + NSID itself
*/
char nsid[BUFSIZ];
isc_buffer_t *buffer = NULL;
if (ns_g_server->server_usehostname) {
isc_result_t result;
result = ns_os_gethostname(nsid, sizeof(nsid));
if (result != ISC_R_SUCCESS) {
goto no_nsid;
}
} else {
strncpy(nsid, ns_g_server->server_id, sizeof(nsid));
}
rdata->length = strlen(nsid) + 4;
result = isc_buffer_allocate(client->mctx, &buffer,
rdata->length);
if (result != ISC_R_SUCCESS)
goto no_nsid;
isc_buffer_putuint16(buffer, DNS_OPT_NSID);
isc_buffer_putuint16(buffer, strlen(nsid));
isc_buffer_putstr(buffer, nsid);
rdata->data = buffer->base;
dns_message_takebuffer(client->message, &buffer);
} else {
no_nsid:
rdata->data = NULL;
rdata->length = 0;
}
rdata->rdclass = rdatalist->rdclass;
rdata->type = rdatalist->type;
rdata->flags = 0;
@ -1302,6 +1336,8 @@ client_request(isc_task_t *task, isc_event_t *event) {
dns_messageid_t id;
unsigned int flags;
isc_boolean_t notimp;
dns_rdata_t rdata;
isc_uint16_t optcode;
REQUIRE(event != NULL);
client = event->ev_arg;
@ -1524,6 +1560,24 @@ client_request(isc_task_t *task, isc_event_t *event) {
ns_client_error(client, result);
goto cleanup;
}
/* Check for NSID request */
result = dns_rdataset_first(opt);
if (result == ISC_R_SUCCESS) {
dns_rdata_init(&rdata);
dns_rdataset_current(opt, &rdata);
if (rdata.length >= 2) {
isc_buffer_t nsidbuf;
isc_buffer_init(&nsidbuf,
rdata.data, rdata.length);
isc_buffer_add(&nsidbuf, rdata.length);
optcode = isc_buffer_getuint16(&nsidbuf);
if (optcode == DNS_OPT_NSID)
client->attributes |=
NS_CLIENTATTR_WANTNSID;
}
}
/*
* Create an OPT for our reply.
*/

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: config.c,v 1.85 2008/04/02 02:37:41 marka Exp $ */
/* $Id: config.c,v 1.86 2008/04/03 02:01:08 marka Exp $ */
/*! \file */
@ -99,6 +99,7 @@ options {\n\
use-ixfr true;\n\
edns-udp-size 4096;\n\
max-udp-size 4096;\n\
request-nsid false;\n\
\n\
/* view */\n\
allow-notify {none;};\n\

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: client.h,v 1.85 2008/01/18 23:46:57 tbox Exp $ */
/* $Id: client.h,v 1.86 2008/04/03 02:01:08 marka Exp $ */
#ifndef NAMED_CLIENT_H
#define NAMED_CLIENT_H 1
@ -166,6 +166,7 @@ struct ns_client {
#define NS_CLIENTATTR_PKTINFO 0x04 /*%< pktinfo is valid */
#define NS_CLIENTATTR_MULTICAST 0x08 /*%< recv'd from multicast */
#define NS_CLIENTATTR_WANTDNSSEC 0x10 /*%< include dnssec records */
#define NS_CLIENTATTR_WANTNSID 0x20 /*%< include nameserver ID */
extern unsigned int ns_client_requests;

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.503 2008/03/31 05:00:29 marka Exp $ */
/* $Id: server.c,v 1.504 2008/04/03 02:01:08 marka Exp $ */
/*! \file */
@ -729,6 +729,11 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
if (obj != NULL)
CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)));
obj = NULL;
(void)cfg_map_get(cpeer, "request-nsid", &obj);
if (obj != NULL)
CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj)));
obj = NULL;
(void)cfg_map_get(cpeer, "edns", &obj);
if (obj != NULL)
@ -1656,6 +1661,11 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
INSIST(result == ISC_R_SUCCESS);
view->provideixfr = cfg_obj_asboolean(obj);
obj = NULL;
result = ns_config_get(maps, "request-nsid", &obj);
INSIST(result == ISC_R_SUCCESS);
view->requestnsid = cfg_obj_asboolean(obj);
obj = NULL;
result = ns_config_get(maps, "max-clients-per-query", &obj);
INSIST(result == ISC_R_SUCCESS);
@ -3465,8 +3475,12 @@ load_configuration(const char *filename, ns_server_t *server,
result = ns_config_get(maps, "server-id", &obj);
server->server_usehostname = ISC_FALSE;
if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
server->server_usehostname = ISC_TRUE;
/* The parser translates "hostname" to ISC_TRUE */
server->server_usehostname = cfg_obj_asboolean(obj);
result = setstring(server, &server->server_id, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
} else if (result == ISC_R_SUCCESS) {
/* Found a quoted string */
CHECKM(setoptstring(server, &server->server_id, obj), "strdup");
} else {
result = setstring(server, &server->server_id, NULL);

View File

@ -18,7 +18,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
<!-- File: $Id: Bv9ARM-book.xml,v 1.348 2008/04/02 02:37:42 marka Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.349 2008/04/03 02:01:08 marka Exp $ -->
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<title>BIND 9 Administrator Reference Manual</title>
@ -7533,9 +7533,10 @@ query-source-v6 address * port *;
<term><command>server-id</command></term>
<listitem>
<para>
The ID of the server should report via a query of
the name <filename>ID.SERVER</filename>
with type <command>TXT</command>, class <command>CHAOS</command>.
The ID the server should report when receiving a Name
Server Identifier (NSID) query, or a query of the name
<filename>ID.SERVER</filename> with type
<command>TXT</command>, class <command>CHAOS</command>.
The primary purpose of such queries is to
identify which of a group of anycast servers is actually
answering your queries. Specifying <command>server-id none;</command>

View File

@ -49,7 +49,7 @@
*/
/*
* $Id: nameser.h,v 1.8 2005/04/27 04:56:16 sra Exp $
* $Id: nameser.h,v 1.9 2008/04/03 02:01:08 marka Exp $
*/
#ifndef _ARPA_NAMESER_H_
@ -427,9 +427,10 @@ typedef enum __ns_cert_types {
#define NS_NXT_MAX 127
/*%
* EDNS0 extended flags, host order.
* EDNS0 extended flags and option codes, host order.
*/
#define NS_OPT_DNSSEC_OK 0x8000U
#define NS_OPT_NSID 3
/*%
* Inline versions of get/put short/long. Pointer is advanced.

View File

@ -50,7 +50,7 @@
/*%
* @(#)resolv.h 8.1 (Berkeley) 6/2/93
* $Id: resolv.h,v 1.23 2005/08/25 04:41:46 marka Exp $
* $Id: resolv.h,v 1.24 2008/04/03 02:01:08 marka Exp $
*/
#ifndef _RESOLV_H_
@ -250,6 +250,7 @@ union res_sockaddr_union {
#define RES_NOCHECKNAME 0x00008000 /*%< do not check names for sanity. */
#define RES_KEEPTSIG 0x00010000 /*%< do not strip TSIG records */
#define RES_BLAST 0x00020000 /*%< blast all recursive servers */
#define RES_NSID 0x00040000 /*%< request name server ID */
#define RES_NOTLDQUERY 0x00100000 /*%< don't unqualified name as a tld */
#define RES_USE_DNSSEC 0x00200000 /*%< use DNSSEC using OK bit in OPT */
/* #define RES_DEBUG2 0x00400000 */ /* nslookup internal */
@ -396,6 +397,7 @@ extern const struct res_sym __p_rcode_syms[];
#define sym_ntos __sym_ntos
#define sym_ston __sym_ston
#define res_nopt __res_nopt
#define res_nopt_rdata __res_nopt_rdata
#define res_ndestroy __res_ndestroy
#define res_nametoclass __res_nametoclass
#define res_nametotype __res_nametotype
@ -482,6 +484,8 @@ int res_findzonecut2 __P((res_state, const char *, ns_class, int,
union res_sockaddr_union *, int));
void res_nclose __P((res_state));
int res_nopt __P((res_state, int, u_char *, int, int));
int res_nopt_rdata __P((res_state, int, u_char *, int, u_char *,
u_short, u_short, u_char *));
void res_send_setqhook __P((res_send_qhook));
void res_send_setrhook __P((res_send_rhook));
int __res_vinit __P((res_state, int));

View File

@ -95,7 +95,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
static const char rcsid[] = "$Id: res_debug.c,v 1.15 2005/07/28 06:51:50 marka Exp $";
static const char rcsid[] = "$Id: res_debug.c,v 1.16 2008/04/03 02:01:08 marka Exp $";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
@ -189,10 +189,56 @@ do_section(const res_state statp,
p_type(ns_rr_type(rr)),
p_class(ns_rr_class(rr)));
else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) {
u_int16_t optcode, optlen, rdatalen = ns_rr_rdlen(rr);
u_int32_t ttl = ns_rr_ttl(rr);
fprintf(file,
"; EDNS: version: %u, udp=%u, flags=%04x\n",
(ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff);
while (rdatalen >= 4) {
const u_char *cp = ns_rr_rdata(rr);
int i;
GETSHORT(optcode, cp);
GETSHORT(optlen, cp);
if (optcode == NS_OPT_NSID) {
fputs("; NSID: ", file);
if (optlen == 0) {
fputs("; NSID\n", file);
} else {
fputs("; NSID: ", file);
for (i = 0; i < optlen; i++)
fprintf(file, "%02x ",
cp[i]);
fputs(" (",file);
for (i = 0; i < optlen; i++)
fprintf(file, "%c",
isprint(cp[i])?
cp[i] : '.');
fputs(")\n", file);
}
} else {
if (optlen == 0) {
fprintf(file, "; OPT=%u\n",
optcode);
} else {
fprintf(file, "; OPT=%u: ",
optcode);
for (i = 0; i < optlen; i++)
fprintf(file, "%02x ",
cp[i]);
fputs(" (",file);
for (i = 0; i < optlen; i++)
fprintf(file, "%c",
isprint(cp[i]) ?
cp[i] : '.');
fputs(")\n", file);
}
}
rdatalen -= 4 + optlen;
}
} else {
n = ns_sprintrr(handle, &rr, NULL, NULL,
buf, buflen);
@ -204,7 +250,7 @@ do_section(const res_state statp,
buf = malloc(buflen += 1024);
if (buf == NULL) {
fprintf(file,
";; memory allocation failure\n");
";; memory allocation failure\n");
return;
}
continue;
@ -381,7 +427,7 @@ const struct res_sym __p_default_section_syms[] = {
{ns_s_an, "ANSWER", (char *)0},
{ns_s_ns, "AUTHORITY", (char *)0},
{ns_s_ar, "ADDITIONAL", (char *)0},
{0, (char *)0, (char *)0}
{0, (char *)0, (char *)0}
};
const struct res_sym __p_update_section_syms[] = {
@ -389,7 +435,7 @@ const struct res_sym __p_update_section_syms[] = {
{S_PREREQ, "PREREQUISITE", (char *)0},
{S_UPDATE, "UPDATE", (char *)0},
{S_ADDT, "ADDITIONAL", (char *)0},
{0, (char *)0, (char *)0}
{0, (char *)0, (char *)0}
};
const struct res_sym __p_key_syms[] = {
@ -617,6 +663,7 @@ p_option(u_long option) {
case RES_USE_INET6: return "inet6";
#ifdef RES_USE_EDNS0 /*%< KAME extension */
case RES_USE_EDNS0: return "edns0";
case RES_NSID: return "nsid";
#endif
#ifdef RES_USE_DNAME
case RES_USE_DNAME: return "dname";

View File

@ -70,7 +70,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
static const char rcsid[] = "$Id: res_mkquery.c,v 1.6 2005/04/27 04:56:42 sra Exp $";
static const char rcsid[] = "$Id: res_mkquery.c,v 1.7 2008/04/03 02:01:08 marka Exp $";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
@ -203,9 +203,6 @@ res_nmkquery(res_state statp,
#ifdef RES_USE_EDNS0
/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
#ifndef T_OPT
#define T_OPT 41
#endif
int
res_nopt(res_state statp,
@ -230,13 +227,14 @@ res_nopt(res_state statp,
if ((ep - cp) < 1 + RRFIXEDSZ)
return (-1);
*cp++ = 0; /*%< "." */
ns_put16(T_OPT, cp); /*%< TYPE */
*cp++ = 0; /*%< "." */
ns_put16(ns_t_opt, cp); /*%< TYPE */
cp += INT16SZ;
ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */
ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */
cp += INT16SZ;
*cp++ = NOERROR; /*%< extended RCODE */
*cp++ = 0; /*%< EDNS version */
*cp++ = NOERROR; /*%< extended RCODE */
*cp++ = 0; /*%< EDNS version */
if (statp->options & RES_USE_DNSSEC) {
#ifdef DEBUG
if (statp->options & RES_DEBUG)
@ -246,12 +244,60 @@ res_nopt(res_state statp,
}
ns_put16(flags, cp);
cp += INT16SZ;
ns_put16(0, cp); /*%< RDLEN */
ns_put16(0U, cp); /*%< RDLEN */
cp += INT16SZ;
hp->arcount = htons(ntohs(hp->arcount) + 1);
return (cp - buf);
}
/*
* Construct variable data (RDATA) block for OPT psuedo-RR, append it
* to the buffer, then update the RDLEN field (previously set to zero by
* res_nopt()) with the new RDATA length.
*/
int
res_nopt_rdata(res_state statp,
int n0, /*%< current offset in buffer */
u_char *buf, /*%< buffer to put query */
int buflen, /*%< size of buffer */
u_char *rdata, /*%< ptr to start of opt rdata */
u_short code, /*%< OPTION-CODE */
u_short len, /*%< OPTION-LENGTH */
u_char *data) /*%< OPTION_DATA */
{
register u_char *cp, *ep;
#ifdef DEBUG
if ((statp->options & RES_DEBUG) != 0U)
printf(";; res_nopt_rdata()\n");
#endif
cp = buf + n0;
ep = buf + buflen;
if ((ep - cp) < (4 + len))
return (-1);
if (rdata < (buf + 2) || rdata >= ep)
return (-1);
ns_put16(code, cp);
cp += INT16SZ;
ns_put16(len, cp);
cp += INT16SZ;
memcpy(cp, data, len);
cp += len;
len = cp - rdata;
ns_put16(len, rdata - 2); /* Update RDLEN field */
return (cp - buf);
}
#endif
/*! \file */

View File

@ -70,7 +70,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
static const char rcsid[] = "$Id: res_query.c,v 1.8 2005/04/27 04:56:42 sra Exp $";
static const char rcsid[] = "$Id: res_query.c,v 1.9 2008/04/03 02:01:08 marka Exp $";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
@ -116,8 +116,9 @@ res_nquery(res_state statp,
{
u_char buf[MAXPACKET];
HEADER *hp = (HEADER *) answer;
int n;
u_int oflags;
u_char *rdata;
int n;
oflags = statp->_flags;
@ -132,8 +133,14 @@ again:
buf, sizeof(buf));
#ifdef RES_USE_EDNS0
if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 &&
(statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U)
(statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC|RES_NSID))) {
n = res_nopt(statp, n, buf, sizeof(buf), anslen);
rdata = &buf[n];
if (n > 0 && (statp->options & RES_NSID) != 0) {
n = res_nopt_rdata(statp, n, buf, sizeof(buf), rdata,
NS_OPT_NSID, 0, NULL);
}
}
#endif
if (n <= 0) {
#ifdef DEBUG
@ -143,6 +150,7 @@ again:
RES_SET_H_ERRNO(statp, NO_RECOVERY);
return (n);
}
n = res_nsend(statp, buf, n, answer, anslen);
if (n < 0) {
#ifdef RES_USE_EDNS0

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dispatch.c,v 1.137 2007/06/27 04:10:44 marka Exp $ */
/* $Id: dispatch.c,v 1.138 2008/04/03 02:01:08 marka Exp $ */
/*! \file */
@ -45,22 +45,23 @@
typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
typedef struct dns_nsid {
isc_uint16_t nsid_state;
isc_uint16_t *nsid_vtable;
isc_uint16_t *nsid_pool;
isc_uint16_t nsid_a1, nsid_a2, nsid_a3;
isc_uint16_t nsid_c1, nsid_c2, nsid_c3;
isc_uint16_t nsid_state2;
isc_boolean_t nsid_usepool;
} dns_nsid_t;
/* transaction ID */
typedef struct dns_tid {
isc_uint16_t tid_state;
isc_uint16_t *tid_vtable;
isc_uint16_t *tid_pool;
isc_uint16_t tid_a1, tid_a2, tid_a3;
isc_uint16_t tid_c1, tid_c2, tid_c3;
isc_uint16_t tid_state2;
isc_boolean_t tid_usepool;
} dns_tid_t;
typedef struct dns_qid {
unsigned int magic;
unsigned int qid_nbuckets; /*%< hash table size */
unsigned int qid_increment; /*%< id increment on collision */
isc_mutex_t lock;
dns_nsid_t nsid;
dns_tid_t tid;
dns_displist_t *qid_table; /*%< the table itself */
} dns_qid_t;
@ -169,7 +170,7 @@ static void destroy_disp(isc_task_t *task, isc_event_t *event);
static void udp_recv(isc_task_t *, isc_event_t *);
static void tcp_recv(isc_task_t *, isc_event_t *);
static void startrecv(dns_dispatch_t *);
static dns_messageid_t dns_randomid(dns_nsid_t *);
static dns_messageid_t dns_randomid(dns_tid_t *);
static isc_uint32_t dns_hash(dns_qid_t *, isc_sockaddr_t *, dns_messageid_t);
static void free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len);
static void *allocate_udp_buffer(dns_dispatch_t *disp);
@ -193,9 +194,10 @@ static isc_result_t qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
unsigned int increment, isc_boolean_t usepool,
dns_qid_t **qidp);
static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
static isc_uint16_t nsid_next(dns_nsid_t *nsid);
static isc_result_t nsid_init(isc_mem_t *mctx, dns_nsid_t *nsid, isc_boolean_t usepool);
static void nsid_destroy(isc_mem_t *mctx, dns_nsid_t *nsid);
static isc_uint16_t tid_next(dns_tid_t *tid);
static isc_result_t tid_init(isc_mem_t *mctx, dns_tid_t *tid,
isc_boolean_t usepool);
static void tid_destroy(isc_mem_t *mctx, dns_tid_t *tid);
#define LVL(x) ISC_LOG_DEBUG(x)
@ -280,10 +282,10 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
* framework for this purpose.
*/
static in_port_t
get_randomport(dns_nsid_t *nsid) {
get_randomport(dns_tid_t *tid) {
isc_uint16_t p;
p = nsid_next(nsid);
p = tid_next(tid);
/* XXX: should the range be configurable? */
return ((in_port_t)(1024 + (p % (65535 - 1024))));
@ -293,10 +295,10 @@ get_randomport(dns_nsid_t *nsid) {
* Return an unpredictable message ID.
*/
static dns_messageid_t
dns_randomid(dns_nsid_t *nsid) {
dns_randomid(dns_tid_t *tid) {
isc_uint32_t id;
id = nsid_next(nsid);
id = tid_next(tid);
return ((dns_messageid_t)id);
}
@ -596,7 +598,7 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
isc_netaddr_fromsockaddr(&netaddr, &ev->address);
if (disp->mgr->blackhole != NULL &&
dns_acl_match(&netaddr, NULL, disp->mgr->blackhole,
NULL, &match, NULL) == ISC_R_SUCCESS &&
NULL, &match, NULL) == ISC_R_SUCCESS &&
match > 0)
{
if (isc_log_wouldlog(dns_lctx, LVL(10))) {
@ -652,7 +654,7 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
if (resp == NULL) {
free_buffer(disp, ev->region.base, ev->region.length);
goto unlock;
}
}
/*
* Now that we have the original dispatch the query was sent
@ -662,7 +664,7 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
if (disp != resp->disp) {
isc_sockaddr_t a1;
isc_sockaddr_t a2;
/*
* Check that the socket types and ports match.
*/
@ -675,11 +677,11 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
/*
* If both dispatches are bound to an address then fail as
* the addresses can't be equal (enforced by the IP stack).
* the addresses can't be equal (enforced by the IP stack).
*
* Note under Linux a packet can be sent out via IPv4 socket
* and the response be received via a IPv6 socket.
*
*
* Requests sent out via IPv6 should always come back in
* via IPv6.
*/
@ -800,7 +802,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
switch (tcpmsg->result) {
case ISC_R_CANCELED:
break;
case ISC_R_EOF:
dispatch_log(disp, LVL(90), "shutting down on EOF");
do_cancel(disp);
@ -1439,7 +1441,7 @@ qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
return (ISC_R_NOMEMORY);
}
result = nsid_init(mgr->mctx, &qid->nsid, usepool);
result = tid_init(mgr->mctx, &qid->tid, usepool);
if (result != ISC_R_SUCCESS) {
isc_mem_put(mgr->mctx, qid->qid_table,
buckets * sizeof(dns_displist_t));
@ -1449,7 +1451,7 @@ qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
result = isc_mutex_init(&qid->lock);
if (result != ISC_R_SUCCESS) {
nsid_destroy(mgr->mctx, &qid->nsid);
tid_destroy(mgr->mctx, &qid->tid);
isc_mem_put(mgr->mctx, qid->qid_table,
buckets * sizeof(dns_displist_t));
isc_mem_put(mgr->mctx, qid, sizeof(*qid));
@ -1477,7 +1479,7 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) {
*qidp = NULL;
qid->magic = 0;
nsid_destroy(mctx, &qid->nsid);
tid_destroy(mctx, &qid->tid);
isc_mem_put(mctx, qid->qid_table,
qid->qid_nbuckets * sizeof(dns_displist_t));
DESTROYLOCK(&qid->lock);
@ -1795,7 +1797,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
getsocket:
if ((attributes & DNS_DISPATCHATTR_RANDOMPORT) != 0) {
isc_sockaddr_setport(&localaddr_bound,
get_randomport(&mgr->qid->nsid));
get_randomport(&mgr->qid->tid));
if (blacklisted(mgr, NULL, &localaddr_bound)) {
if (++k == 1024)
attributes &= ~DNS_DISPATCHATTR_RANDOMPORT;
@ -1807,7 +1809,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
attributes &= ~DNS_DISPATCHATTR_RANDOMPORT;
goto getsocket;
}
} else
} else
result = create_socket(sockmgr, localaddr, &sock);
if (result != ISC_R_SUCCESS)
goto deallocate_dispatch;
@ -1969,7 +1971,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
*/
qid = DNS_QID(disp);
LOCK(&qid->lock);
id = dns_randomid(&qid->nsid);
id = dns_randomid(&qid->tid);
bucket = dns_hash(qid, dest, id);
ok = ISC_FALSE;
for (i = 0; i < 64; i++) {
@ -2294,7 +2296,7 @@ dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event) {
newsevent->timestamp = sevent->timestamp;
newsevent->pktinfo = sevent->pktinfo;
newsevent->attributes = sevent->attributes;
isc_task_send(disp->task, ISC_EVENT_PTR(&newsevent));
}
@ -2381,26 +2383,26 @@ dns_dispatchmgr_dump(dns_dispatchmgr_t *mgr) {
* the pool.
*/
#define NSID_SHUFFLE_TABLE_SIZE 100 /* Suggested by Knuth */
#define TID_SHUFFLE_TABLE_SIZE 100 /* Suggested by Knuth */
/*
* Pick one of the next 4096 IDs in the pool.
* There is a tradeoff here between randomness and how often and ID is reused.
*/
#define NSID_LOOKAHEAD 4096 /* Must be a power of 2 */
#define NSID_SHUFFLE_ONLY 1 /* algorithm 1 */
#define NSID_USE_POOL 2 /* algorithm 2 */
#define NSID_HASHSHIFT 3
#define NSID_HASHROTATE(v) \
(((v) << NSID_HASHSHIFT) | ((v) >> ((sizeof(v) * 8) - NSID_HASHSHIFT)))
#define TID_LOOKAHEAD 4096 /* Must be a power of 2 */
#define TID_SHUFFLE_ONLY 1 /* algorithm 1 */
#define TID_USE_POOL 2 /* algorithm 2 */
#define TID_HASHSHIFT 3
#define TID_HASHROTATE(v) \
(((v) << TID_HASHSHIFT) | ((v) >> ((sizeof(v) * 8) - TID_HASHSHIFT)))
static isc_uint32_t nsid_hash_state;
static isc_uint32_t tid_hash_state;
/*
* Keep a running hash of various bits of data that we'll use to
* stir the ID pool or perturb the ID generator
*/
static void
nsid_hash(void *data, size_t len) {
tid_hash(void *data, size_t len) {
unsigned char *p = data;
/*
* Hash function similar to the one we use for hashing names.
@ -2412,12 +2414,12 @@ nsid_hash(void *data, size_t len) {
* fast.
*/
/*
* We don't care about locking access to nsid_hash_state.
* We don't care about locking access to tid_hash_state.
* In fact races make the result even more non deteministic.
*/
while (len-- > 0U) {
nsid_hash_state = NSID_HASHROTATE(nsid_hash_state);
nsid_hash_state += *p++;
tid_hash_state = TID_HASHROTATE(tid_hash_state);
tid_hash_state += *p++;
}
}
@ -2426,7 +2428,7 @@ nsid_hash(void *data, size_t len) {
* in order of increasing serial correlation bounds (so trim from
* the end).
*/
static const isc_uint16_t nsid_multiplier_table[] = {
static const isc_uint16_t tid_multiplier_table[] = {
17565, 25013, 11733, 19877, 23989, 23997, 24997, 25421,
26781, 27413, 35901, 35917, 35973, 36229, 38317, 38437,
39941, 40493, 41853, 46317, 50581, 51429, 53453, 53805,
@ -2562,159 +2564,168 @@ static const isc_uint16_t nsid_multiplier_table[] = {
10853, 1453, 18069, 21693, 30573, 36261, 37421, 42533
};
#define NSID_MULT_TABLE_SIZE \
((sizeof nsid_multiplier_table)/(sizeof nsid_multiplier_table[0]))
#define NSID_RANGE_MASK (NSID_LOOKAHEAD - 1)
#define NSID_POOL_MASK 0xFFFF /* used to wrap the pool index */
#define NSID_SHUFFLE_ONLY 1
#define NSID_USE_POOL 2
#define TID_MULT_TABLE_SIZE \
((sizeof tid_multiplier_table) / \
(sizeof tid_multiplier_table[0]))
#define TID_RANGE_MASK (TID_LOOKAHEAD - 1)
#define TID_POOL_MASK 0xFFFF /* used to wrap the pool index */
#define TID_SHUFFLE_ONLY 1
#define TID_USE_POOL 2
static isc_uint16_t
nsid_next(dns_nsid_t *nsid) {
isc_uint16_t id, compressed_hash;
tid_next(dns_tid_t *tid) {
isc_uint16_t id, compressed_hash;
isc_uint16_t j;
compressed_hash = ((nsid_hash_state >> 16) ^
(nsid_hash_state)) & 0xFFFF;
compressed_hash = ((tid_hash_state >> 16) ^
(tid_hash_state)) & 0xFFFF;
if (nsid->nsid_usepool) {
isc_uint16_t pick;
if (tid->tid_usepool) {
isc_uint16_t pick;
pick = compressed_hash & NSID_RANGE_MASK;
pick = (nsid->nsid_state + pick) & NSID_POOL_MASK;
id = nsid->nsid_pool[pick];
if (pick != 0) {
/* Swap two IDs to stir the pool */
nsid->nsid_pool[pick] =
nsid->nsid_pool[nsid->nsid_state];
nsid->nsid_pool[nsid->nsid_state] = id;
}
pick = compressed_hash & TID_RANGE_MASK;
pick = (tid->tid_state + pick) & TID_POOL_MASK;
id = tid->tid_pool[pick];
if (pick != 0) {
/* Swap two IDs to stir the pool */
tid->tid_pool[pick] =
tid->tid_pool[tid->tid_state];
tid->tid_pool[tid->tid_state] = id;
}
/* increment the base pointer into the pool */
if (nsid->nsid_state == 65535)
nsid->nsid_state = 0;
else
nsid->nsid_state++;
/* increment the base pointer into the pool */
if (tid->tid_state == 65535)
tid->tid_state = 0;
else
tid->tid_state++;
} else {
/*
* This is the original Algorithm B
* j = ((u_long) NSID_SHUFFLE_TABLE_SIZE * nsid_state2) >> 16;
* j = ((u_long)
* QUERID_SHUFFLE_TABLE_SIZE * tid_state2) >> 16;
*
* We'll perturb it with some random stuff ...
*/
j = ((isc_uint32_t) NSID_SHUFFLE_TABLE_SIZE *
(nsid->nsid_state2 ^ compressed_hash)) >> 16;
nsid->nsid_state2 = id = nsid->nsid_vtable[j];
nsid->nsid_state = (((isc_uint32_t) nsid->nsid_a1 * nsid->nsid_state) +
nsid->nsid_c1) & 0xFFFF;
nsid->nsid_vtable[j] = nsid->nsid_state;
j = ((isc_uint32_t) TID_SHUFFLE_TABLE_SIZE *
(tid->tid_state2 ^ compressed_hash)) >> 16;
tid->tid_state2 = id = tid->tid_vtable[j];
tid->tid_state = (((isc_uint32_t) tid->tid_a1 *
tid->tid_state) +
tid->tid_c1) & 0xFFFF;
tid->tid_vtable[j] = tid->tid_state;
}
/* Now lets obfuscate ... */
id = (((isc_uint32_t) nsid->nsid_a2 * id) + nsid->nsid_c2) & 0xFFFF;
id = (((isc_uint32_t) nsid->nsid_a3 * id) + nsid->nsid_c3) & 0xFFFF;
/* Now lets obfuscate ... */
id = (((isc_uint32_t) tid->tid_a2 * id) +
tid->tid_c2) & 0xFFFF;
id = (((isc_uint32_t) tid->tid_a3 * id) +
tid->tid_c3) & 0xFFFF;
return (id);
return (id);
}
static isc_result_t
nsid_init(isc_mem_t *mctx, dns_nsid_t *nsid, isc_boolean_t usepool) {
isc_time_t now;
pid_t mypid;
isc_uint16_t a1ndx, a2ndx, a3ndx, c1ndx, c2ndx, c3ndx;
int i;
tid_init(isc_mem_t *mctx, dns_tid_t *tid, isc_boolean_t usepool) {
isc_time_t now;
pid_t mypid;
isc_uint16_t a1ndx, a2ndx, a3ndx, c1ndx, c2ndx, c3ndx;
int i;
isc_time_now(&now);
mypid = getpid();
mypid = getpid();
/* Initialize the state */
memset(nsid, 0, sizeof(*nsid));
nsid_hash(&now, sizeof now);
nsid_hash(&mypid, sizeof mypid);
/* Initialize the state */
memset(tid, 0, sizeof(*tid));
tid_hash(&now, sizeof now);
tid_hash(&mypid, sizeof mypid);
/*
* Select our random number generators and initial seed.
* We could really use more random bits at this point,
* but we'll try to make a silk purse out of a sows ear ...
*/
/* generator 1 */
a1ndx = ((isc_uint32_t) NSID_MULT_TABLE_SIZE *
(nsid_hash_state & 0xFFFF)) >> 16;
nsid->nsid_a1 = nsid_multiplier_table[a1ndx];
c1ndx = (nsid_hash_state >> 9) & 0x7FFF;
nsid->nsid_c1 = 2 * c1ndx + 1;
/*
* Select our random number generators and initial seed.
* We could really use more random bits at this point,
* but we'll try to make a silk purse out of a sows ear ...
*/
/* generator 1 */
a1ndx = ((isc_uint32_t) TID_MULT_TABLE_SIZE *
(tid_hash_state & 0xFFFF)) >> 16;
tid->tid_a1 = tid_multiplier_table[a1ndx];
c1ndx = (tid_hash_state >> 9) & 0x7FFF;
tid->tid_c1 = 2 * c1ndx + 1;
/* generator 2, distinct from 1 */
a2ndx = ((isc_uint32_t) (NSID_MULT_TABLE_SIZE - 1) *
((nsid_hash_state >> 10) & 0xFFFF)) >> 16;
if (a2ndx >= a1ndx)
a2ndx++;
nsid->nsid_a2 = nsid_multiplier_table[a2ndx];
c2ndx = nsid_hash_state % 32767;
if (c2ndx >= c1ndx)
c2ndx++;
nsid->nsid_c2 = 2*c2ndx + 1;
/* generator 2, distinct from 1 */
a2ndx = ((isc_uint32_t) (TID_MULT_TABLE_SIZE - 1) *
((tid_hash_state >> 10) & 0xFFFF)) >> 16;
if (a2ndx >= a1ndx)
a2ndx++;
tid->tid_a2 = tid_multiplier_table[a2ndx];
c2ndx = tid_hash_state % 32767;
if (c2ndx >= c1ndx)
c2ndx++;
tid->tid_c2 = 2*c2ndx + 1;
/* generator 3, distinct from 1 and 2 */
a3ndx = ((isc_uint32_t) (NSID_MULT_TABLE_SIZE - 2) *
((nsid_hash_state >> 20) & 0xFFFF)) >> 16;
if (a3ndx >= a1ndx || a3ndx >= a2ndx)
a3ndx++;
if (a3ndx >= a1ndx && a3ndx >= a2ndx)
a3ndx++;
nsid->nsid_a3 = nsid_multiplier_table[a3ndx];
c3ndx = nsid_hash_state % 32766;
if (c3ndx >= c1ndx || c3ndx >= c2ndx)
c3ndx++;
if (c3ndx >= c1ndx && c3ndx >= c2ndx)
c3ndx++;
nsid->nsid_c3 = 2*c3ndx + 1;
/* generator 3, distinct from 1 and 2 */
a3ndx = ((isc_uint32_t) (TID_MULT_TABLE_SIZE - 2) *
((tid_hash_state >> 20) & 0xFFFF)) >> 16;
if (a3ndx >= a1ndx || a3ndx >= a2ndx)
a3ndx++;
if (a3ndx >= a1ndx && a3ndx >= a2ndx)
a3ndx++;
tid->tid_a3 = tid_multiplier_table[a3ndx];
c3ndx = tid_hash_state % 32766;
if (c3ndx >= c1ndx || c3ndx >= c2ndx)
c3ndx++;
if (c3ndx >= c1ndx && c3ndx >= c2ndx)
c3ndx++;
tid->tid_c3 = 2*c3ndx + 1;
nsid->nsid_state =
((nsid_hash_state >> 16) ^ (nsid_hash_state)) & 0xFFFF;
tid->tid_state =
((tid_hash_state >> 16) ^ (tid_hash_state)) & 0xFFFF;
nsid->nsid_usepool = usepool;
if (nsid->nsid_usepool) {
nsid->nsid_pool = isc_mem_get(mctx, 0x10000 * sizeof(isc_uint16_t));
if (nsid->nsid_pool == NULL)
tid->tid_usepool = usepool;
if (tid->tid_usepool) {
tid->tid_pool = isc_mem_get(mctx,
0x10000 * sizeof(isc_uint16_t));
if (tid->tid_pool == NULL)
return (ISC_R_NOMEMORY);
for (i = 0; ; i++) {
nsid->nsid_pool[i] = nsid->nsid_state;
nsid->nsid_state =
(((u_long) nsid->nsid_a1 * nsid->nsid_state) +
nsid->nsid_c1) & 0xFFFF;
if (i == 0xFFFF)
break;
}
} else {
nsid->nsid_vtable = isc_mem_get(mctx, NSID_SHUFFLE_TABLE_SIZE *
(sizeof(isc_uint16_t)) );
if (nsid->nsid_vtable == NULL)
return (ISC_R_NOMEMORY);
for (i = 0; i < NSID_SHUFFLE_TABLE_SIZE; i++) {
nsid->nsid_vtable[i] = nsid->nsid_state;
nsid->nsid_state =
(((isc_uint32_t) nsid->nsid_a1 * nsid->nsid_state) +
nsid->nsid_c1) & 0xFFFF;
for (i = 0; ; i++) {
tid->tid_pool[i] = tid->tid_state;
tid->tid_state =
(((u_long) tid->tid_a1 *
tid->tid_state) +
tid->tid_c1) & 0xFFFF;
if (i == 0xFFFF)
break;
}
nsid->nsid_state2 = nsid->nsid_state;
}
} else {
tid->tid_vtable = isc_mem_get(mctx, TID_SHUFFLE_TABLE_SIZE *
(sizeof(isc_uint16_t)) );
if (tid->tid_vtable == NULL)
return (ISC_R_NOMEMORY);
for (i = 0; i < TID_SHUFFLE_TABLE_SIZE; i++) {
tid->tid_vtable[i] = tid->tid_state;
tid->tid_state =
(((isc_uint32_t) tid->tid_a1 *
tid->tid_state) +
tid->tid_c1) & 0xFFFF;
}
tid->tid_state2 = tid->tid_state;
}
return (ISC_R_SUCCESS);
}
static void
nsid_destroy(isc_mem_t *mctx, dns_nsid_t *nsid) {
if (nsid->nsid_usepool)
isc_mem_put(mctx, nsid->nsid_pool,
tid_destroy(isc_mem_t *mctx, dns_tid_t *tid) {
if (tid->tid_usepool)
isc_mem_put(mctx, tid->tid_pool,
0x10000 * sizeof(isc_uint16_t));
else
isc_mem_put(mctx, nsid->nsid_vtable,
NSID_SHUFFLE_TABLE_SIZE * (sizeof(isc_uint16_t)) );
memset(nsid, 0, sizeof(*nsid));
isc_mem_put(mctx, tid->tid_vtable,
TID_SHUFFLE_TABLE_SIZE *
(sizeof(isc_uint16_t)) );
memset(tid, 0, sizeof(*tid));
}
void
dns_dispatch_hash(void *data, size_t len) {
nsid_hash(data, len);
tid_hash(data, len);
}

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: message.h,v 1.123 2007/06/19 23:47:17 tbox Exp $ */
/* $Id: message.h,v 1.124 2008/04/03 02:01:08 marka Exp $ */
#ifndef DNS_MESSAGE_H
#define DNS_MESSAGE_H 1
@ -101,8 +101,12 @@
#define DNS_MESSAGEFLAG_AD 0x0020U
#define DNS_MESSAGEFLAG_CD 0x0010U
/*%< EDNS0 extended message flags */
#define DNS_MESSAGEEXTFLAG_DO 0x8000U
/*%< EDNS0 extended OPT codes */
#define DNS_OPT_NSID 0x0003 /*%< NSID opt code */
#define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD|DNS_MESSAGEFLAG_CD)
#define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)
@ -771,7 +775,7 @@ dns_message_addname(dns_message_t *msg, dns_name_t *name,
void
dns_message_removename(dns_message_t *msg, dns_name_t *name,
dns_section_t section);
dns_section_t section);
/*%<
* Remove a existing name from a given section.
*
@ -1031,7 +1035,7 @@ dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt);
*\li The OPT record has either been freed or ownership of it has
* been transferred to the message.
*
*\li If ISC_R_SUCCESS was returned, the OPT record will be rendered
*\li If ISC_R_SUCCESS was returned, the OPT record will be rendered
* when dns_message_renderend() is called.
*
* Returns:
@ -1315,7 +1319,7 @@ dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
*\li order_arg is NULL if and only if order is NULL.
*/
void
void
dns_message_settimeadjust(dns_message_t *msg, int timeadjust);
/*%<
* Adjust the time used to sign/verify a message by timeadjust.
@ -1325,7 +1329,7 @@ dns_message_settimeadjust(dns_message_t *msg, int timeadjust);
*\li msg be a valid message.
*/
int
int
dns_message_gettimeadjust(dns_message_t *msg);
/*%<
* Return the current time adjustment.

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: peer.h,v 1.31 2007/06/19 23:47:17 tbox Exp $ */
/* $Id: peer.h,v 1.32 2008/04/03 02:01:08 marka Exp $ */
#ifndef DNS_PEER_H
#define DNS_PEER_H 1
@ -73,10 +73,11 @@ struct dns_peer {
isc_boolean_t provide_ixfr;
isc_boolean_t request_ixfr;
isc_boolean_t support_edns;
isc_boolean_t request_nsid;
dns_name_t *key;
isc_sockaddr_t *transfer_source;
isc_sockaddr_t *notify_source;
isc_sockaddr_t *query_source;
isc_sockaddr_t *notify_source;
isc_sockaddr_t *query_source;
isc_uint16_t udpsize; /* recieve size */
isc_uint16_t maxudp; /* transmit size */
@ -149,6 +150,12 @@ dns_peer_setprovideixfr(dns_peer_t *peer, isc_boolean_t newval);
isc_result_t
dns_peer_getprovideixfr(dns_peer_t *peer, isc_boolean_t *retval);
isc_result_t
dns_peer_setrequestnsid(dns_peer_t *peer, isc_boolean_t newval);
isc_result_t
dns_peer_getrequestnsid(dns_peer_t *peer, isc_boolean_t *retval);
isc_result_t
dns_peer_setsupportedns(dns_peer_t *peer, isc_boolean_t newval);

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdatalist.h,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
/* $Id: rdatalist.h,v 1.21 2008/04/03 02:01:08 marka Exp $ */
#ifndef DNS_RDATALIST_H
#define DNS_RDATALIST_H 1
@ -98,6 +98,27 @@ dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist,
*\li #ISC_R_SUCCESS
*/
isc_result_t
dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
dns_rdatalist_t **rdatalist);
/*%<
* Point 'rdatalist' to the rdatalist in 'rdataset'.
*
* Requires:
*
*\li 'rdatalist' is a pointer to a NULL dns_rdatalist_t pointer.
*
*\li 'rdataset' is a valid rdataset associated with an rdatalist.
*
* Ensures,
* on success,
*
*\li 'rdatalist' is pointed to the rdatalist in rdataset.
*
* Returns:
*\li #ISC_R_SUCCESS
*/
ISC_LANG_ENDDECLS
#endif /* DNS_RDATALIST_H */

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.h,v 1.56 2007/06/18 23:47:42 tbox Exp $ */
/* $Id: resolver.h,v 1.57 2008/04/03 02:01:08 marka Exp $ */
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1
@ -93,7 +93,8 @@ typedef struct dns_fetchevent {
#define DNS_FETCHOPT_FORWARDONLY 0x10 /*%< Only use forwarders. */
#define DNS_FETCHOPT_NOVALIDATE 0x20 /*%< Disable validation. */
#define DNS_FETCHOPT_EDNS512 0x40 /*%< Advertise a 512 byte
UDP buffer. */
UDP buffer. */
#define DNS_FETCHOPT_WANTNSID 0x80 /*%< Request NSID */
#define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000
#define DNS_FETCHOPT_EDNSVERSIONMASK 0xff000000
@ -470,7 +471,7 @@ dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
isc_boolean_t
dns_resolver_getzeronosoattl(dns_resolver_t *resolver);
void
dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state);
@ -491,7 +492,7 @@ dns_resolver_createdispatchpool(dns_resolver_t *res, unsigned int ndisps,
* Requires:
*
*\li 'res' is a valid resolver that has not been frozen. Also it must have
* either the _USEDISPATCHPOOL4 or _USEDISPATCHPOOL6 option.
* either the _USEDISPATCHPOOL4 or _USEDISPATCHPOOL6 option.
*
*\li 'taskmgr' is a valid task manager.
*

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: view.h,v 1.107 2007/06/18 23:47:42 tbox Exp $ */
/* $Id: view.h,v 1.108 2008/04/03 02:01:08 marka Exp $ */
#ifndef DNS_VIEW_H
#define DNS_VIEW_H 1
@ -124,6 +124,7 @@ struct dns_view {
dns_acl_t * sortlist;
isc_boolean_t requestixfr;
isc_boolean_t provideixfr;
isc_boolean_t requestnsid;
dns_ttl_t maxcachettl;
dns_ttl_t maxncachettl;
in_port_t dstport;
@ -596,7 +597,7 @@ dns_viewlist_find(dns_viewlist_t *list, const char *name,
isc_result_t
dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name, isc_boolean_t allclasses,
dns_rdataclass_t rdclass, dns_zone_t **zonep);
dns_rdataclass_t rdclass, dns_zone_t **zonep);
/*%<
* Search zone with 'name' in view with 'rdclass' in viewlist 'list'
@ -632,7 +633,7 @@ dns_view_loadnew(dns_view_t *view, isc_boolean_t stop);
/*%<
* Load zones attached to this view. dns_view_load() loads
* all zones whose master file has changed since the last
* load; dns_view_loadnew() loads only zones that have never
* load; dns_view_loadnew() loads only zones that have never
* been loaded.
*
* If 'stop' is ISC_TRUE, stop on the first error and return it.
@ -708,7 +709,7 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp);
* easily obtainable by other means.
*
* Requires:
*
*
*\li 'view' is valid.
*
*\li 'fp' refers to a file open for writing.
@ -751,7 +752,7 @@ isc_result_t
dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name);
/*%<
* Add the given name to the delegation only table.
*
*
*
* Requires:
*\li 'view' is valid.
@ -766,7 +767,7 @@ isc_result_t
dns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name);
/*%<
* Add the given name to be excluded from the root-delegation-only.
*
*
*
* Requires:
*\li 'view' is valid.

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: message.c,v 1.241 2008/04/02 02:37:42 marka Exp $ */
/* $Id: message.c,v 1.242 2008/04/03 02:01:08 marka Exp $ */
/*! \file */
@ -24,6 +24,7 @@
***/
#include <config.h>
#include <ctype.h>
#include <isc/buffer.h>
#include <isc/mem.h>
@ -1488,14 +1489,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
rdataset->ttl = ttl;
}
/*
* XXXMLG Perform a totally ugly hack here to pull
* the rdatalist out of the private field in the rdataset,
* and append this rdata to the rdatalist's linked list
* of rdata.
*/
rdatalist = (dns_rdatalist_t *)(rdataset->private1);
/* Append this rdata to the rdataset. */
dns_rdatalist_fromrdataset(rdataset, &rdatalist);
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
/*
@ -3128,6 +3123,10 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
isc_result_t result;
char buf[sizeof("1234567890")];
isc_uint32_t mbz;
dns_rdata_t rdata;
isc_buffer_t optbuf;
isc_uint16_t optcode, optlen;
unsigned char *optdata;
REQUIRE(DNS_MESSAGE_VALID(msg));
REQUIRE(target != NULL);
@ -3157,6 +3156,50 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
ADD_STRING(target, "; udp: ");
snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
ADD_STRING(target, buf);
result = dns_rdataset_first(ps);
if (result != ISC_R_SUCCESS)
return (ISC_R_SUCCESS);
/* Print EDNS info, if any */
dns_rdata_init(&rdata);
dns_rdataset_current(ps, &rdata);
if (rdata.length < 4)
return (ISC_R_SUCCESS);
isc_buffer_init(&optbuf, rdata.data, rdata.length);
isc_buffer_add(&optbuf, rdata.length);
optcode = isc_buffer_getuint16(&optbuf);
optlen = isc_buffer_getuint16(&optbuf);
if (optcode == DNS_OPT_NSID) {
ADD_STRING(target, "; NSID");
} else {
ADD_STRING(target, "; OPT=");
sprintf(buf, "%u", optcode);
ADD_STRING(target, buf);
}
if (optlen != 0) {
int i;
ADD_STRING(target, ": ");
optdata = rdata.data + 4;
for (i = 0; i < optlen; i++) {
sprintf(buf, "%02x ", optdata[i]);
ADD_STRING(target, buf);
}
for (i = 0; i < optlen; i++) {
ADD_STRING(target, " (");
if (isprint(optdata[i]))
isc_buffer_putmem(target, &optdata[i],
1);
else
isc_buffer_putmem(target, ".", 1);
ADD_STRING(target, ")");
}
}
ADD_STRING(target, "\n");
return (ISC_R_SUCCESS);
case DNS_PSEUDOSECTION_TSIG:
ps = dns_message_gettsig(msg, &name);

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: peer.c,v 1.29 2007/06/19 23:47:16 tbox Exp $ */
/* $Id: peer.c,v 1.30 2008/04/03 02:01:08 marka Exp $ */
/*! \file */
@ -42,6 +42,7 @@
#define SUPPORT_EDNS_BIT 5
#define SERVER_UDPSIZE_BIT 6
#define SERVER_MAXUDP_BIT 7
#define REQUEST_NSID_BIT 8
static void
peerlist_delete(dns_peerlist_t **list);
@ -146,7 +147,7 @@ dns_peerlist_addpeer(dns_peerlist_t *peers, dns_peer_t *peer) {
ISC_LIST_INSERTBEFORE(peers->elements, p, peer, next);
else
ISC_LIST_APPEND(peers->elements, peer, next);
}
isc_result_t
@ -213,7 +214,7 @@ dns_peer_new(isc_mem_t *mem, isc_netaddr_t *addr, dns_peer_t **peerptr) {
isc_result_t
dns_peer_newprefix(isc_mem_t *mem, isc_netaddr_t *addr, unsigned int prefixlen,
dns_peer_t **peerptr)
{
{
dns_peer_t *peer;
REQUIRE(peerptr != NULL);
@ -415,6 +416,32 @@ dns_peer_getsupportedns(dns_peer_t *peer, isc_boolean_t *retval) {
return (ISC_R_NOTFOUND);
}
isc_result_t
dns_peer_setrequestnsid(dns_peer_t *peer, isc_boolean_t newval) {
isc_boolean_t existed;
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(REQUEST_NSID_BIT, &peer->bitflags);
peer->request_nsid = newval;
DNS_BIT_SET(REQUEST_NSID_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getrequestnsid(dns_peer_t *peer, isc_boolean_t *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(REQUEST_NSID_BIT, &peer->bitflags)) {
*retval = peer->request_nsid;
return (ISC_R_SUCCESS);
} else
return (ISC_R_NOTFOUND);
}
isc_result_t
dns_peer_settransfers(dns_peer_t *peer, isc_uint32_t newval) {
isc_boolean_t existed;
@ -544,7 +571,7 @@ dns_peer_settransfersource(dns_peer_t *peer,
}
if (transfer_source != NULL) {
peer->transfer_source = isc_mem_get(peer->mem,
sizeof(*peer->transfer_source));
sizeof(*peer->transfer_source));
if (peer->transfer_source == NULL)
return (ISC_R_NOMEMORY);
@ -577,7 +604,7 @@ dns_peer_setnotifysource(dns_peer_t *peer,
}
if (notify_source != NULL) {
peer->notify_source = isc_mem_get(peer->mem,
sizeof(*peer->notify_source));
sizeof(*peer->notify_source));
if (peer->notify_source == NULL)
return (ISC_R_NOMEMORY);
@ -608,7 +635,7 @@ dns_peer_setquerysource(dns_peer_t *peer, const isc_sockaddr_t *query_source) {
}
if (query_source != NULL) {
peer->query_source = isc_mem_get(peer->mem,
sizeof(*peer->query_source));
sizeof(*peer->query_source));
if (peer->query_source == NULL)
return (ISC_R_NOMEMORY);
@ -649,11 +676,11 @@ dns_peer_getudpsize(dns_peer_t *peer, isc_uint16_t *udpsize) {
REQUIRE(udpsize != NULL);
if (DNS_BIT_CHECK(SERVER_UDPSIZE_BIT, &peer->bitflags)) {
*udpsize = peer->udpsize;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
*udpsize = peer->udpsize;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}
isc_result_t
@ -677,9 +704,9 @@ dns_peer_getmaxudp(dns_peer_t *peer, isc_uint16_t *maxudp) {
REQUIRE(maxudp != NULL);
if (DNS_BIT_CHECK(SERVER_MAXUDP_BIT, &peer->bitflags)) {
*maxudp = peer->maxudp;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
*maxudp = peer->maxudp;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdatalist.c,v 1.33 2007/06/19 23:47:16 tbox Exp $ */
/* $Id: rdatalist.c,v 1.34 2008/04/03 02:01:08 marka Exp $ */
/*! \file */
@ -88,6 +88,16 @@ dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist,
return (ISC_R_SUCCESS);
}
isc_result_t
dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
dns_rdatalist_t **rdatalist)
{
REQUIRE(rdatalist != NULL && rdataset != NULL);
*rdatalist = rdataset->private1;
return (ISC_R_SUCCESS);
}
void
isc__rdatalist_disassociate(dns_rdataset_t *rdataset) {
UNUSED(rdataset);

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;

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: zone.c,v 1.476 2008/04/02 02:37:42 marka Exp $ */
/* $Id: zone.c,v 1.477 2008/04/03 02:01:08 marka Exp $ */
/*! \file */
@ -6357,7 +6357,7 @@ create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
}
static isc_result_t
add_opt(dns_message_t *message, isc_uint16_t udpsize) {
add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
dns_rdataset_t *rdataset = NULL;
dns_rdatalist_t *rdatalist = NULL;
dns_rdata_t *rdata = NULL;
@ -6387,11 +6387,21 @@ add_opt(dns_message_t *message, isc_uint16_t udpsize) {
*/
rdatalist->ttl = 0;
/*
* No EDNS options.
*/
rdata->data = NULL;
rdata->length = 0;
/* Set EDNS options if applicable */
if (reqnsid) {
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;
@ -6426,7 +6436,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
isc_uint32_t options;
isc_boolean_t cancel = ISC_TRUE;
int timeout;
isc_boolean_t have_xfrsource;
isc_boolean_t have_xfrsource, reqnsid;
isc_uint16_t udpsize = SEND_BUFFER_SIZE;
REQUIRE(DNS_ZONE_VALID(zone));
@ -6495,6 +6505,9 @@ soa_query(isc_task_t *task, isc_event_t *event) {
udpsize =
dns_resolver_getudpsize(zone->view->resolver);
(void)dns_peer_getudpsize(peer, &udpsize);
result = dns_peer_getrequestnsid(peer, &reqnsid);
reqnsid = (result == ISC_R_SUCCESS && reqnsid) ||
zone->view->requestnsid;
}
}
@ -6526,7 +6539,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
DNS_REQUESTOPT_TCP : 0;
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
result = add_opt(message, udpsize);
result = add_opt(message, udpsize, reqnsid);
if (result != ISC_R_SUCCESS)
zone_debuglog(zone, me, 1,
"unable to add opt record: %s",
@ -6590,7 +6603,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
dns_tsigkey_t *key = NULL;
dns_dbnode_t *node = NULL;
int timeout;
isc_boolean_t have_xfrsource = ISC_FALSE;
isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
isc_uint16_t udpsize = SEND_BUFFER_SIZE;
REQUIRE(DNS_ZONE_VALID(zone));
@ -6719,11 +6732,14 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
udpsize =
dns_resolver_getudpsize(zone->view->resolver);
(void)dns_peer_getudpsize(peer, &udpsize);
result = dns_peer_getrequestnsid(peer, &reqnsid);
reqnsid = (result == ISC_R_SUCCESS && reqnsid) ||
zone->view->requestnsid;
}
}
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
result = add_opt(message, udpsize);
result = add_opt(message, udpsize, reqnsid);
if (result != ISC_R_SUCCESS)
zone_debuglog(zone, me, 1,
"unable to add opt record: %s",

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: namedconf.c,v 1.86 2008/04/02 02:37:42 marka Exp $ */
/* $Id: namedconf.c,v 1.87 2008/04/03 02:01:08 marka Exp $ */
/*! \file */
@ -734,67 +734,68 @@ static cfg_type_t cfg_type_lookaside = {
static cfg_clausedef_t
view_clauses[] = {
{ "acache-cleaning-interval", &cfg_type_uint32, 0 },
{ "acache-enable", &cfg_type_boolean, 0 },
{ "additional-from-auth", &cfg_type_boolean, 0 },
{ "additional-from-cache", &cfg_type_boolean, 0 },
{ "allow-query-cache", &cfg_type_bracketed_aml, 0 },
{ "allow-query-cache-on", &cfg_type_bracketed_aml, 0 },
{ "allow-recursion", &cfg_type_bracketed_aml, 0 },
{ "allow-recursion-on", &cfg_type_bracketed_aml, 0 },
{ "allow-v6-synthesis", &cfg_type_bracketed_aml,
CFG_CLAUSEFLAG_OBSOLETE },
{ "sortlist", &cfg_type_bracketed_aml, 0 },
{ "topology", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_NOTIMP },
{ "auth-nxdomain", &cfg_type_boolean, CFG_CLAUSEFLAG_NEWDEFAULT },
{ "minimal-responses", &cfg_type_boolean, 0 },
{ "recursion", &cfg_type_boolean, 0 },
{ "rrset-order", &cfg_type_rrsetorder, 0 },
{ "provide-ixfr", &cfg_type_boolean, 0 },
{ "request-ixfr", &cfg_type_boolean, 0 },
{ "cache-file", &cfg_type_qstring, 0 },
{ "check-names", &cfg_type_checknames, CFG_CLAUSEFLAG_MULTI },
{ "cleaning-interval", &cfg_type_uint32, 0 },
{ "clients-per-query", &cfg_type_uint32, 0 },
{ "disable-algorithms", &cfg_type_disablealgorithm,
CFG_CLAUSEFLAG_MULTI },
{ "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
{ "dnssec-accept-expired", &cfg_type_boolean, 0 },
{ "dnssec-enable", &cfg_type_boolean, 0 },
{ "dnssec-lookaside", &cfg_type_lookaside, CFG_CLAUSEFLAG_MULTI },
{ "dnssec-must-be-secure", &cfg_type_mustbesecure,
CFG_CLAUSEFLAG_MULTI },
{ "dnssec-validation", &cfg_type_boolean, 0 },
{ "dual-stack-servers", &cfg_type_nameportiplist, 0 },
{ "edns-udp-size", &cfg_type_uint32, 0 },
{ "empty-contact", &cfg_type_astring, 0 },
{ "empty-server", &cfg_type_astring, 0 },
{ "empty-zones-enable", &cfg_type_boolean, 0 },
{ "fetch-glue", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
{ "rfc2308-type1", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
{ "additional-from-auth", &cfg_type_boolean, 0 },
{ "additional-from-cache", &cfg_type_boolean, 0 },
{ "ixfr-from-differences", &cfg_type_ixfrdifftype, 0 },
{ "lame-ttl", &cfg_type_uint32, 0 },
{ "max-acache-size", &cfg_type_sizenodefault, 0 },
{ "max-cache-size", &cfg_type_size, 0 },
{ "max-cache-ttl", &cfg_type_uint32, 0 },
{ "max-clients-per-query", &cfg_type_uint32, 0 },
{ "max-ncache-ttl", &cfg_type_uint32, 0 },
{ "max-udp-size", &cfg_type_uint32, 0 },
{ "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
{ "minimal-responses", &cfg_type_boolean, 0 },
{ "preferred-glue", &cfg_type_astring, 0 },
{ "provide-ixfr", &cfg_type_boolean, 0 },
/*
* Note that the query-source option syntax is different
* from the other -source options.
*/
{ "query-source", &cfg_type_querysource4, 0 },
{ "query-source-v6", &cfg_type_querysource6, 0 },
{ "cleaning-interval", &cfg_type_uint32, 0 },
{ "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
{ "lame-ttl", &cfg_type_uint32, 0 },
{ "max-ncache-ttl", &cfg_type_uint32, 0 },
{ "max-cache-ttl", &cfg_type_uint32, 0 },
{ "transfer-format", &cfg_type_transferformat, 0 },
{ "max-cache-size", &cfg_type_size, 0 },
{ "check-names", &cfg_type_checknames, CFG_CLAUSEFLAG_MULTI },
{ "cache-file", &cfg_type_qstring, 0 },
{ "suppress-initial-notify", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
{ "preferred-glue", &cfg_type_astring, 0 },
{ "dual-stack-servers", &cfg_type_nameportiplist, 0 },
{ "edns-udp-size", &cfg_type_uint32, 0 },
{ "max-udp-size", &cfg_type_uint32, 0 },
{ "root-delegation-only", &cfg_type_optional_exclude, 0 },
{ "disable-algorithms", &cfg_type_disablealgorithm,
CFG_CLAUSEFLAG_MULTI },
{ "dnssec-enable", &cfg_type_boolean, 0 },
{ "dnssec-validation", &cfg_type_boolean, 0 },
{ "dnssec-lookaside", &cfg_type_lookaside, CFG_CLAUSEFLAG_MULTI },
{ "dnssec-must-be-secure", &cfg_type_mustbesecure,
CFG_CLAUSEFLAG_MULTI },
{ "dnssec-accept-expired", &cfg_type_boolean, 0 },
{ "ixfr-from-differences", &cfg_type_ixfrdifftype, 0 },
{ "acache-enable", &cfg_type_boolean, 0 },
{ "acache-cleaning-interval", &cfg_type_uint32, 0 },
{ "max-acache-size", &cfg_type_sizenodefault, 0 },
{ "clients-per-query", &cfg_type_uint32, 0 },
{ "max-clients-per-query", &cfg_type_uint32, 0 },
{ "empty-server", &cfg_type_astring, 0 },
{ "empty-contact", &cfg_type_astring, 0 },
{ "empty-zones-enable", &cfg_type_boolean, 0 },
{ "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
{ "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 },
{ "use-queryport-pool", &cfg_type_boolean, 0 },
{ "queryport-pool-ports", &cfg_type_uint32, 0 },
{ "queryport-pool-updateinterval", &cfg_type_uint32, 0 },
{ "recursion", &cfg_type_boolean, 0 },
{ "request-ixfr", &cfg_type_boolean, 0 },
{ "request-nsid", &cfg_type_boolean, 0 },
{ "rfc2308-type1", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
{ "root-delegation-only", &cfg_type_optional_exclude, 0 },
{ "rrset-order", &cfg_type_rrsetorder, 0 },
{ "sortlist", &cfg_type_bracketed_aml, 0 },
{ "suppress-initial-notify", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
{ "topology", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_NOTIMP },
{ "transfer-format", &cfg_type_transferformat, 0 },
{ "use-queryport-pool", &cfg_type_boolean, 0 },
{ "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 },
{ NULL, NULL, 0 }
};