status=`expr $status + $ret`
n=`expr $n + 1`
-echo_i "query for .good is properly minimized when qname-minimization is on ($n)"
+echo_i "query for .good is properly minimized when qname-minimization is in strict mode ($n)"
ret=0
$CLEANQL
$RNDCCMD 10.53.0.6 flush
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
+n=`expr $n + 1`
+echo_i "query for .good is properly minimized when qname-minimization is in relaxed mode ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.7 flush
+$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.7 > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1
+sleep 1
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | $DIFF ans2/query.log.sorted - > /dev/null || ret=1
+ADDR _.boing.good.
+ADDR _.zoop.boing.good.
+ADDR a.bit.longer.ns.name.good.
+ADDR a.bit.longer.ns.name.good.
+ADDR ns2.good.
+ADDR ns3.good.
+ADDR ns3.good.
+__EOF
+cat << __EOF | $DIFF ans3/query.log - > /dev/null || ret=1
+ADDR _.ptang.zoop.boing.good.
+ADDR _.icky.ptang.zoop.boing.good.
+__EOF
+cat << __EOF | $DIFF ans4/query.log - > /dev/null || ret=1
+ADDR _.icky.icky.ptang.zoop.boing.good.
+ADDR icky.icky.icky.ptang.zoop.boing.good.
+__EOF
+for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
n=`expr $n + 1`
echo_i "query for .bad fails when qname-minimization is in strict mode ($n)"
ret=0
sleep 1
sort ans2/query.log > ans2/query.log.sorted
cat << __EOF | $DIFF ans2/query.log.sorted - > /dev/null || ret=1
+ADDR _.boing.bad.
+ADDR _.zoop.boing.bad.
ADDR a.bit.longer.ns.name.bad.
ADDR a.bit.longer.ns.name.bad.
-ADDR icky.icky.icky.ptang.zoop.boing.bad.
ADDR ns2.bad.
ADDR ns3.bad.
ADDR ns3.bad.
-NS bad.
-NS boing.bad.
__EOF
-echo "ADDR icky.icky.icky.ptang.zoop.boing.bad." | $DIFF ans3/query.log - > /dev/null || ret=1
-echo "ADDR icky.icky.icky.ptang.zoop.boing.bad." | $DIFF ans4/query.log - > /dev/null || ret=1
+cat << __EOF | $DIFF ans3/query.log - > /dev/null || ret=1
+ADDR _.ptang.zoop.boing.bad.
+ADDR _.icky.ptang.zoop.boing.bad.
+__EOF
+cat << __EOF | $DIFF ans4/query.log - > /dev/null || ret=1
+ADDR _.icky.icky.ptang.zoop.boing.bad.
+ADDR icky.icky.icky.ptang.zoop.boing.bad.
+__EOF
for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "icky.icky.icky.ptang.zoop.boing.ugly. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1
sleep 1
+
sort ans2/query.log > ans2/query.log.sorted
-cat << __EOF | $DIFF ans2/query.log.sorted - > /dev/null || ret=1
+cat << __EOF | $DIFF ans2/query.log.sorted - > /dev/null || cat ans2/query.log.sorted
+ADDR _.boing.ugly.
+ADDR _.boing.ugly.
ADDR a.bit.longer.ns.name.ugly.
ADDR a.bit.longer.ns.name.ugly.
ADDR icky.icky.icky.ptang.zoop.boing.ugly.
ADDR ns2.ugly.
ADDR ns3.ugly.
ADDR ns3.ugly.
-NS boing.ugly.
-NS boing.ugly.
-NS ugly.
__EOF
echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | $DIFF ans3/query.log - > /dev/null || ret=1
echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | $DIFF ans4/query.log - > /dev/null || ret=1
static const dns_name_t ip6_arpa =
DNS_NAME_INITABSOLUTE(ip6_arpa_data, ip6_arpa_offsets);
+static unsigned char underscore_data[] = "\001_";
+static unsigned char underscore_offsets[] = { 0 };
+static const dns_name_t underscore_name =
+ DNS_NAME_INITNONABSOLUTE(underscore_data, underscore_offsets);
+
static void destroy(dns_resolver_t *res);
static void empty_bucket(dns_resolver_t *res);
static isc_result_t resquery_send(resquery_t *query);
if (fctx->minimized && !fctx->forwarding) {
unsigned int options = fctx->options;
options &= ~DNS_FETCHOPT_QMINIMIZE;
+ /*
+ * In "_ A" mode we're asking for _.domain -
+ * resolver by default will follow delegations
+ * then, we don't want that.
+ */
+ if ((options & DNS_FETCHOPT_QMIN_USE_A) != 0) {
+ options |= DNS_FETCHOPT_NOFOLLOW;
+ }
fctx_increference(fctx);
task = res->buckets[bucketnum].task;
fctx_stoptimer(fctx);
goto cleanup;
}
- if (NXDOMAIN_RESULT(result) || result == DNS_R_FORMERR ||
- result == DNS_R_REMOTEFORMERR || result == ISC_R_FAILURE)
+ /*
+ * If we're doing "_ A"-style minimization we can get
+ * NX answer to minimized query - we need to continue then.
+ *
+ * Otherwise - either disable minimization if we're
+ * in relaxed mode or fail if we're in strict mode.
+ */
+
+ if ((NXDOMAIN_RESULT(result) &&
+ (fctx->options & DNS_FETCHOPT_QMIN_USE_A) == 0) ||
+ result == DNS_R_FORMERR ||
+ result == DNS_R_REMOTEFORMERR ||
+ result == ISC_R_FAILURE)
{
if ((fctx->options & DNS_FETCHOPT_QMIN_STRICT) == 0) {
fctx->qmin_labels = DNS_MAX_LABELS + 1;
case DNS_R_CHASEDSSERVERS:
break;
case DNS_R_DELEGATION:
- result = ISC_R_SUCCESS;
+ /* With NOFOLLOW we want to pass the result code */
+ if ((fctx->options & DNS_FETCHOPT_NOFOLLOW) == 0) {
+ result = ISC_R_SUCCESS;
+ }
break;
default:
/*
* work to be queued to the DNSSEC validator.
*/
if (WANTCACHE(fctx)) {
- result = cache_message(fctx, query->addrinfo, rctx.now);
- if (result != ISC_R_SUCCESS) {
- FCTXTRACE3("cache_message complete", result);
- rctx_done(&rctx, result);
+ isc_result_t tresult;
+ tresult = cache_message(fctx, query->addrinfo, rctx.now);
+ if (tresult != ISC_R_SUCCESS) {
+ FCTXTRACE3("cache_message complete", tresult);
+ rctx_done(&rctx, tresult);
return;
}
}
* reset the fetch context counters.
*
*/
- rctx->get_nameservers = true;
- rctx->next_server = true;
- rctx->fctx->restarts = 0;
- rctx->fctx->referrals++;
- rctx->fctx->querysent = 0;
- rctx->fctx->lamecount = 0;
- rctx->fctx->quotacount = 0;
- rctx->fctx->neterr = 0;
- rctx->fctx->badresp = 0;
- rctx->fctx->adberr = 0;
+ if ((rctx->fctx->options & DNS_FETCHOPT_NOFOLLOW) == 0) {
+ rctx->get_nameservers = true;
+ rctx->next_server = true;
+ rctx->fctx->restarts = 0;
+ rctx->fctx->referrals++;
+ rctx->fctx->querysent = 0;
+ rctx->fctx->lamecount = 0;
+ rctx->fctx->quotacount = 0;
+ rctx->fctx->neterr = 0;
+ rctx->fctx->badresp = 0;
+ rctx->fctx->adberr = 0;
+ }
return (ISC_R_COMPLETE);
+
}
/*
dns_name_split(&fctx->name,
fctx->qmin_labels,
NULL, dns_fixedname_name(&fname));
- result = dns_name_dup(dns_fixedname_name(&fname), fctx->mctx,
- &fctx->qminname);
- fctx->qmintype = dns_rdatatype_ns;
+ if ((fctx->options & DNS_FETCHOPT_QMIN_USE_A) != 0) {
+ isc_buffer_t dbuf;
+ dns_fixedname_t tmpname;
+ char ndata[DNS_NAME_MAXWIRE];
+ isc_buffer_init(&dbuf, ndata, DNS_NAME_MAXWIRE);
+ dns_fixedname_init(&tmpname);
+ result = dns_name_concatenate(&underscore_name,
+ dns_fixedname_name(&fname),
+ dns_fixedname_name(&tmpname),
+ &dbuf);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_name_dup(dns_fixedname_name(&tmpname),
+ fctx->mctx,
+ &fctx->qminname);
+ }
+ fctx->qmintype = dns_rdatatype_a;
+ } else {
+ result = dns_name_dup(dns_fixedname_name(&fname),
+ fctx->mctx,
+ &fctx->qminname);
+ fctx->qmintype = dns_rdatatype_ns;
+ }
fctx->minimized = true;
} else {
/* Minimization is done, we'll ask for whole qname */
fctx->minimized = false;
}
+ char domainbuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(&fctx->qminname, domainbuf, sizeof(domainbuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(5),
+ "QNAME minimization - %s minimized, qmintype %d "
+ "qminname %s", fctx->minimized ? "" : "not",
+ fctx->qmintype, domainbuf);
+
return (result);
}