+3124. [bug] Use an rdataset attribute flag to indicate
+ negative-cache records rather than using rrtype 0;
+ this will prevent problems when that rrtype is
+ used in actual DNS packets. [RT #24777]
+
--- 9.4-ESV-R5rc1 released ---
3121. [security] An authoritative name server sending a negative
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: tests.sh,v 1.23 2004/03/05 05:01:55 marka Exp $
+# $Id: tests.sh,v 1.23.18.1 2011/06/09 00:42:47 each Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
status=0
+n=0
echo "I:fetching first copy of zone before update"
$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
$PERL ../digcomp.pl knowngood.ns1.after dig.out.ns1 || status=1
$PERL ../digcomp.pl knowngood.ns1.after dig.out.ns2 || status=1
+n=`expr $n + 1`
+ret=0
+echo "I:check TYPE=0 update is rejected by nsupdate ($n)"
+$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
+ server 10.53.0.1 5300
+ update add example.nil. 300 in type0 ""
+ send
+END
+grep "unknown class/type" nsupdate.out > /dev/null 2>&1 || ret=1
+if [ $ret -ne 0 ]; then
+ echo "I:failed"
+ status=1
+fi
+
+n=`expr $n + 1`
+ret=0
+echo "I:check TYPE=0 prerequisite is handled ($n)"
+$NSUPDATE <<END > nsupdate.out 2>&1 || ret=1
+ server 10.53.0.1 5300
+ prereq nxrrset example.nil. type0
+ send
+END
+$DIG +tcp version.bind txt ch @10.53.0.1 -p 5300 > dig.out.ns1.$n
+grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then
+ echo "I:failed"
+ status=1
+fi
+
+n=`expr $n + 1`
+ret=0
+echo "I:check that TYPE=0 update is handled ($n)"
+echo "a0e4280000010000000100000000060001c00c000000fe000000000000" |
+$PERL ../packet.pl -a 10.53.0.1 -p 5300 -t tcp > /dev/null
+$DIG +tcp version.bind txt ch @10.53.0.1 -p 5300 > dig.out.ns1.$n
+grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
+if test $ret -ne 0
+then
+ echo "I:failed"
+ status=1
+fi
+
+n=`expr $n + 1`
+echo "I:check that TYPE=0 additional data is handled ($n)"
+echo "a0e4280000010000000000010000060001c00c000000fe000000000000" |
+$PERL ../packet.pl -a 10.53.0.1 -p 5300 -t tcp > /dev/null
+$DIG +tcp version.bind txt ch @10.53.0.1 -p 5300 > dig.out.ns1.$n
+grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
+if test $ret -ne 0
+then
+ echo "I:failed"
+ status=1
+fi
+
if $PERL -e 'use Net::DNS;' 2>/dev/null
then
echo "I:running update.pl test"
--- /dev/null
+#!/usr/bin/perl
+#
+# Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# $Id: packet.pl,v 1.2.36.2 2011/06/09 00:42:47 each Exp $
+
+# This is a tool for sending an arbitrary packet via UDP or TCP to an
+# arbitrary address and port. The packet is specified in a file or on
+# the standard input, in the form of a series of bytes in hexidecimal.
+# Whitespace is ignored, as is anything following a '#' symbol.
+#
+# For example, the following input would generate normal query for
+# isc.org/NS/IN":
+#
+# # QID:
+# 0c d8
+# # header:
+# 01 00 00 01 00 00 00 00 00 00
+# # qname isc.org:
+# 03 69 73 63 03 6f 72 67 00
+# # qtype NS:
+# 00 02
+# # qclass IN:
+# 00 01
+#
+# Note that we do not wait for a response for the server. This is simply
+# a way of injecting arbitrary packets to test server resposnes.
+#
+# Usage: packet.pl [-a <address>] [-p <port>] [-t (udp|tcp)] [filename]
+#
+# If not specified, address defaults to 127.0.0.1, port to 53, protocol
+# to udp, and file to stdin.
+#
+# XXX: Doesn't support IPv6 yet
+
+require 5.006.001;
+
+use strict;
+use Getopt::Std;
+use IO::File;
+use IO::Socket;
+
+sub usage {
+ print ("Usage: packet.pl [-a address] [-p port] [-t (tcp|udp)] [file]\n");
+ exit 1;
+}
+
+my %options={};
+getopts("a:p:t:", \%options);
+
+my $addr = "127.0.0.1";
+$addr = $options{a} if defined $options{a};
+
+my $port = 53;
+$port = $options{p} if defined $options{p};
+
+my $proto = "udp";
+$proto = lc $options{t} if defined $options{t};
+usage if ($proto !~ /^(udp|tcp)$/);
+
+my $file = "STDIN";
+if (@ARGV >= 1) {
+ my $filename = shift @ARGV;
+ open FH, "<$filename" or die "$filename: $!";
+ $file = "FH";
+}
+
+my $input = "";
+while (defined(my $line = <$file>) ) {
+ chomp $line;
+ $line =~ s/#.*$//;
+ $input .= $line;
+}
+
+$input =~ s/\s+//g;
+my $data = pack("H*", $input);
+my $len = length $data;
+
+my $output = unpack("H*", $data);
+print ("sending: $output\n");
+
+my $sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port,
+ Proto => $proto,) or die "$!";
+
+my $bytes;
+if ($proto eq "udp") {
+ $bytes = $sock->send($data);
+} else {
+ $bytes = $sock->syswrite(pack("n", $len), 2);
+ $bytes += $sock->syswrite($data, $len);
+}
+
+print ("sent $bytes bytes to $addr:$port\n");
+$sock->close;
+close $file;
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataset.h,v 1.51.18.13 2011/05/27 23:49:08 tbox Exp $ */
+/* $Id: rdataset.h,v 1.51.18.14 2011/06/09 00:42:48 each Exp $ */
#ifndef DNS_RDATASET_H
#define DNS_RDATASET_H 1
#define DNS_RDATASETATTR_CHECKNAMES 0x00008000 /*%< Used by resolver. */
#define DNS_RDATASETATTR_REQUIREDGLUE 0x00010000
#define DNS_RDATASETATTR_LOADORDER 0x00020000
+#define DNS_RDATASETATTR_NEGATIVE 0x00200000
/*%
* _OMITDNSSEC:
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: masterdump.c,v 1.73.18.22 2011/05/27 23:49:06 tbox Exp $ */
+/* $Id: masterdump.c,v 1.73.18.23 2011/06/09 00:42:47 each Exp $ */
/*! \file */
isc_uint32_t current_ttl;
isc_boolean_t current_ttl_valid;
dns_rdatatype_t type;
+ unsigned int type_start;
REQUIRE(DNS_RDATASET_VALID(rdataset));
* Type.
*/
- if (rdataset->type == 0) {
+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
type = rdataset->covers;
} else {
type = rdataset->type;
}
- {
- unsigned int type_start;
- INDENT_TO(type_column);
- type_start = target->used;
- if (rdataset->type == 0)
- RETERR(str_totext("\\-", target));
- result = dns_rdatatype_totext(type, target);
- if (result != ISC_R_SUCCESS)
- return (result);
- column += (target->used - type_start);
- }
+ INDENT_TO(type_column);
+ type_start = target->used;
+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
+ RETERR(str_totext("\\-", target));
+ result = dns_rdatatype_totext(type, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ column += (target->used - type_start);
/*
* Rdata.
*/
INDENT_TO(rdata_column);
- if (rdataset->type == 0) {
+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
if (NXDOMAIN(rdataset))
RETERR(str_totext(";-$NXDOMAIN\n", target));
else
dns_rdataset_t *rds = sorted[i];
if (ctx->style.flags & DNS_STYLEFLAG_TRUST)
fprintf(f, "; %s\n", dns_trust_totext(rds->trust));
- if (rds->type == 0 &&
+ if (((rds->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) &&
(ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) {
/* Omit negative cache entries */
} else {
dns_rdataset_init(&rdataset);
dns_rdatasetiter_current(rdsiter, &rdataset);
- if (rdataset.type == 0 &&
+ if (((rdataset.attributes & DNS_RDATASETATTR_NEGATIVE) != 0) &&
(ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) {
/* Omit negative cache entries */
} else {
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: message.c,v 1.222.18.18 2009/01/19 23:46:15 tbox Exp $ */
+/* $Id: message.c,v 1.222.18.19 2011/06/09 00:42:47 each Exp $ */
/*! \file */
isc_result_t
dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
- unsigned int first_section;
+ unsigned int clear_after;
isc_result_t result;
REQUIRE(DNS_MESSAGE_VALID(msg));
if (want_question_section) {
if (!msg->question_ok)
return (DNS_R_FORMERR);
- first_section = DNS_SECTION_ANSWER;
+ clear_after = DNS_SECTION_ANSWER;
} else
- first_section = DNS_SECTION_QUESTION;
+ clear_after = DNS_SECTION_QUESTION;
msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
- msgresetnames(msg, first_section);
+ msgresetnames(msg, clear_after);
msgresetopt(msg);
msgresetsigs(msg, ISC_TRUE);
msginitprivate(msg);
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ncache.c,v 1.36.18.11 2011/05/31 02:18:34 marka Exp $ */
+/* $Id: ncache.c,v 1.36.18.12 2011/06/09 00:42:47 each Exp $ */
/*! \file */
RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset)
== ISC_R_SUCCESS);
ncrdataset.trust = trust;
+ ncrdataset.attributes |= DNS_RDATASETATTR_NEGATIVE;
if (message->rcode == dns_rcode_nxdomain)
ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN;
REQUIRE(rdataset != NULL);
REQUIRE(rdataset->type == 0);
+ REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
savedbuffer = *target;
count = 0;
REQUIRE(ncacherdataset != NULL);
REQUIRE(ncacherdataset->type == 0);
+ REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
REQUIRE(name != NULL);
REQUIRE(!dns_rdataset_isassociated(rdataset));
REQUIRE(type != dns_rdatatype_rrsig);
REQUIRE(ncacherdataset != NULL);
REQUIRE(ncacherdataset->type == 0);
+ REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
REQUIRE(name != NULL);
REQUIRE(!dns_rdataset_isassociated(rdataset));
REQUIRE(ncacherdataset != NULL);
REQUIRE(ncacherdataset->type == 0);
+ REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
REQUIRE(found != NULL);
REQUIRE(!dns_rdataset_isassociated(rdataset));
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb.c,v 1.196.18.66 2011/03/02 23:45:32 tbox Exp $ */
+/* $Id: rbtdb.c,v 1.196.18.67 2011/06/09 00:42:47 each Exp $ */
/*! \file */
#define RDATASET_ATTR_IGNORE 0x0004
#define RDATASET_ATTR_RETAIN 0x0008
#define RDATASET_ATTR_NXDOMAIN 0x0010
+#define RDATASET_ATTR_NEGATIVE 0x0100
typedef struct acache_cbarg {
dns_rdatasetadditional_t type;
(((header)->attributes & RDATASET_ATTR_RETAIN) != 0)
#define NXDOMAIN(header) \
(((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
+#define NEGATIVE(header) \
+ (((header)->attributes & RDATASET_ATTR_NEGATIVE) != 0)
#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
#define DEFAULT_CACHE_NODE_LOCK_COUNT 1009 /*%< Should be prime. */
rdataset->covers = RBTDB_RDATATYPE_EXT(header->type);
rdataset->ttl = header->ttl - now;
rdataset->trust = header->trust;
+ if (NEGATIVE(header))
+ rdataset->attributes |= DNS_RDATASETATTR_NEGATIVE;
if (NXDOMAIN(header))
rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;
rdataset->private1 = rbtdb;
*nodep = node;
}
- if (RBTDB_RDATATYPE_BASE(found->type) == 0) {
+ if (NEGATIVE(found)) {
/*
* We found a negative cache entry.
*/
if (found == NULL)
return (ISC_R_NOTFOUND);
- if (RBTDB_RDATATYPE_BASE(found->type) == 0) {
+ if (NEGATIVE(found)) {
/*
* We found a negative cache entry.
*/
negtype = 0;
if (rbtversion == NULL && !newheader_nx) {
rdtype = RBTDB_RDATATYPE_BASE(newheader->type);
- if (rdtype == 0) {
+ if (NEGATIVE(newheader)) {
/*
* We're adding a negative cache entry.
*/
now = 0;
} else {
newheader->serial = 1;
+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
+ newheader->attributes |= RDATASET_ATTR_NEGATIVE;
if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
newheader->attributes |= RDATASET_ATTR_NXDOMAIN;
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
type = header->type;
rdtype = RBTDB_RDATATYPE_BASE(header->type);
- if (rdtype == 0) {
+ if (NEGATIVE(header)) {
covers = RBTDB_RDATATYPE_EXT(header->type);
negtype = RBTDB_RDATATYPE_VALUE(covers, 0);
} else
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataset.c,v 1.72.18.11 2011/05/27 23:49:07 tbox Exp $ */
+/* $Id: rdataset.c,v 1.72.18.12 2011/06/09 00:42:48 each Exp $ */
/*! \file */
count = 1;
result = dns_rdataset_first(rdataset);
INSIST(result == ISC_R_NOMORE);
- } else if (rdataset->type == 0) {
+ } else if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
/*
* This is a negative caching rdataset.
*/
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.c,v 1.284.18.105 2011/01/27 23:45:12 tbox Exp $ */
+/* $Id: resolver.c,v 1.284.18.106 2011/06/09 00:42:48 each Exp $ */
/*! \file */
FCTX_ADDRINFO_FORWARDER) != 0)
#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
+#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
#define dns_db_transfernode(a,b,c) do { (*c) = (*b); (*b) = NULL; } while (0)
* Negative results must be indicated in event->result.
*/
if (dns_rdataset_isassociated(event->rdataset) &&
- event->rdataset->type == dns_rdatatype_none) {
+ NEGATIVE(event->rdataset)) {
INSIST(event->result == DNS_R_NCACHENXDOMAIN ||
event->result == DNS_R_NCACHENXRRSET);
}
if (result != ISC_R_SUCCESS &&
result != DNS_R_UNCHANGED)
goto noanswer_response;
- if (ardataset != NULL && ardataset->type == 0) {
+ if (ardataset != NULL && NEGATIVE(ardataset)) {
if (NXDOMAIN(ardataset))
eresult = DNS_R_NCACHENXDOMAIN;
else
result = ISC_R_SUCCESS;
if (!need_validation &&
ardataset != NULL &&
- ardataset->type == 0) {
+ NEGATIVE(ardataset)) {
/*
* The answer in the cache is
* better than the answer we
if (result == DNS_R_UNCHANGED) {
if (ANSWER(rdataset) &&
ardataset != NULL &&
- ardataset->type == 0) {
+ NEGATIVE(ardataset)) {
/*
* The answer in the cache is better
* than the answer we found, and is
* Negative results must be indicated in event->result.
*/
if (dns_rdataset_isassociated(event->rdataset) &&
- event->rdataset->type == dns_rdatatype_none) {
+ NEGATIVE(event->rdataset)) {
INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
eresult == DNS_R_NCACHENXRRSET);
}
* care about whether it is DNS_R_NCACHENXDOMAIN or
* DNS_R_NCACHENXRRSET then extract it.
*/
- if (ardataset->type == 0) {
+ if (NEGATIVE(ardataset)) {
/*
* The cache data is a negative cache entry.
*/
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.c,v 1.119.18.63 2011/05/27 01:46:22 marka Exp $ */
+/* $Id: validator.c,v 1.119.18.64 2011/06/09 00:42:48 each Exp $ */
/*! \file */
#define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
#define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
+#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
+
static void
destroy(dns_validator_t *val);
name = dns_fixedname_name(&val->fname);
if ((val->attributes & VALATTR_INSECURITY) != 0 &&
val->frdataset.covers == dns_rdatatype_ds &&
- val->frdataset.type == 0 &&
+ NEGATIVE(&val->frdataset) &&
isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET)) {
if (val->mustbesecure) {
validator_log(val, ISC_LOG_WARNING,
val->attributes |= VALATTR_NEEDNODATA;
result = nsecvalidate(val, ISC_FALSE);
} else if (val->event->rdataset != NULL &&
- val->event->rdataset->type == 0)
+ NEGATIVE(val->event->rdataset))
{
/*
* This is a nonexistence validation.