|
@@ -229,6 +229,9 @@ private:
|
|
|
// case of a TCP packet being returned with the TC bit set.
|
|
|
IOFetch::Protocol protocol_;
|
|
|
|
|
|
+ // EDNS flag
|
|
|
+ bool edns_;
|
|
|
+
|
|
|
// To prevent both unreasonably long cname chains and cname loops,
|
|
|
// we simply keep a counter of the number of CNAMEs we have
|
|
|
// followed so far (and error if it exceeds RESOLVER_MAX_CNAME_CHAIN
|
|
@@ -358,17 +361,19 @@ private:
|
|
|
IOFetch query(protocol_, io_, question_,
|
|
|
current_ns_address.getAddress(),
|
|
|
53, buffer_, this,
|
|
|
- query_timeout_);
|
|
|
+ query_timeout_, edns_);
|
|
|
io_.get_io_service().post(query);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 'general' send, ask the NSAS to give us an address.
|
|
|
- void send(IOFetch::Protocol protocol = IOFetch::UDP) {
|
|
|
+ void send(IOFetch::Protocol protocol = IOFetch::UDP, bool edns = true) {
|
|
|
protocol_ = protocol; // Store protocol being used for this
|
|
|
+ edns_ = edns;
|
|
|
if (test_server_.second != 0) {
|
|
|
// Send query to test server
|
|
|
- LOG_DEBUG(isc::resolve::logger, RESLIB_DBG_TRACE, RESLIB_TEST_UPSTREAM)
|
|
|
+ LOG_DEBUG(isc::resolve::logger,
|
|
|
+ RESLIB_DBG_TRACE, RESLIB_TEST_UPSTREAM)
|
|
|
.arg(questionText(question_)).arg(test_server_.first);
|
|
|
gettimeofday(¤t_ns_qsent_time, NULL);
|
|
|
++outstanding_events_;
|
|
@@ -381,8 +386,9 @@ private:
|
|
|
} else {
|
|
|
// Ask the NSAS for an address for the current zone,
|
|
|
// the callback will call the actual sendTo()
|
|
|
- LOG_DEBUG(isc::resolve::logger, RESLIB_DBG_TRACE, RESLIB_NSAS_LOOKUP)
|
|
|
- .arg(cur_zone_);
|
|
|
+ LOG_DEBUG(isc::resolve::logger,
|
|
|
+ RESLIB_DBG_TRACE, RESLIB_NSAS_LOOKUP)
|
|
|
+ .arg(cur_zone_);
|
|
|
|
|
|
// Can we have multiple calls to nsas_out? Let's assume not
|
|
|
// for now
|
|
@@ -544,10 +550,30 @@ private:
|
|
|
}
|
|
|
|
|
|
// Was a TCP query so we have received a packet over TCP with the
|
|
|
- // TC bit set: report an error by dropping down to the common
|
|
|
+ // TC bit set: report an error by going to the common
|
|
|
// error code.
|
|
|
+ goto SERVFAIL;
|
|
|
+
|
|
|
+ case isc::resolve::ResponseClassifier::RCODE:
|
|
|
+ // see if it's a FORMERR and a potential EDNS problem
|
|
|
+ if (incoming.getRcode() == Rcode::FORMERR()) {
|
|
|
+ if (protocol_ == IOFetch::UDP && edns_) {
|
|
|
+ // try EDNS over TCP
|
|
|
+ send(IOFetch::TCP, true);
|
|
|
+ return (false);
|
|
|
+ } else if (protocol_ == IOFetch::TCP && edns_) {
|
|
|
+ // try UDP, no EDNS
|
|
|
+ send(IOFetch::UDP, false);
|
|
|
+ return (false);
|
|
|
+ }
|
|
|
|
|
|
+ // TC should take care of non-EDNS over UDP, fall through to
|
|
|
+ // SERVFAIL if we get FORMERR instead
|
|
|
+ }
|
|
|
+ goto SERVFAIL;
|
|
|
+
|
|
|
default:
|
|
|
+SERVFAIL:
|
|
|
// Some error in received packet it. Report it and return SERVFAIL
|
|
|
// to the caller.
|
|
|
if (logger.isDebugEnabled()) {
|