Commit e3c35e75 authored by Dima Volodin's avatar Dima Volodin

[1386] EDNS fallback on FORMERR

parent 1615a521
......@@ -175,12 +175,12 @@ struct IOFetchData {
/// IOFetch Constructor - just initialize the private data
IOFetch::IOFetch(Protocol protocol, IOService& service,
const isc::dns::Question& question, const IOAddress& address, uint16_t port,
OutputBufferPtr& buff, Callback* cb, int wait)
const isc::dns::Question& question, const IOAddress& address,
uint16_t port, OutputBufferPtr& buff, Callback* cb, int wait, bool edns)
{
MessagePtr query_msg(new Message(Message::RENDER));
initIOFetch(query_msg, protocol, service, question, address, port, buff,
cb, wait);
cb, wait, edns);
}
IOFetch::IOFetch(Protocol protocol, IOService& service,
......@@ -214,7 +214,7 @@ void
IOFetch::initIOFetch(MessagePtr& query_msg, Protocol protocol, IOService& service,
const isc::dns::Question& question,
const IOAddress& address, uint16_t port,
OutputBufferPtr& buff, Callback* cb, int wait)
OutputBufferPtr& buff, Callback* cb, int wait, bool edns)
{
data_ = boost::shared_ptr<IOFetchData>(new IOFetchData(
protocol, service, address, port, buff, cb, wait));
......@@ -224,9 +224,13 @@ IOFetch::initIOFetch(MessagePtr& query_msg, Protocol protocol, IOService& servic
query_msg->setRcode(Rcode::NOERROR());
query_msg->setHeaderFlag(Message::HEADERFLAG_RD);
query_msg->addQuestion(question);
EDNSPtr edns_query(new EDNS());
edns_query->setUDPSize(Message::DEFAULT_MAX_EDNS0_UDPSIZE);
query_msg->setEDNS(edns_query);
if (edns) {
EDNSPtr edns_query(new EDNS());
edns_query->setUDPSize(Message::DEFAULT_MAX_EDNS0_UDPSIZE);
query_msg->setEDNS(edns_query);
}
MessageRenderer renderer(*data_->msgbuf);
query_msg->toWire(renderer);
}
......
......@@ -131,11 +131,14 @@ public:
/// and deleting it if necessary.
/// \param wait Timeout for the fetch (in ms). The default value of
/// -1 indicates no timeout.
/// \param edns true if the request should be EDNS. The default value is
/// true.
IOFetch(Protocol protocol, isc::asiolink::IOService& service,
const isc::dns::Question& question,
const isc::asiolink::IOAddress& address,
uint16_t port, isc::util::OutputBufferPtr& buff, Callback* cb,
int wait = -1);
int wait = -1,
bool edns = true);
/// \brief Constructor
/// This constructor has one parameter "query_message", which
......@@ -206,7 +209,8 @@ private:
void initIOFetch(isc::dns::MessagePtr& query_message, Protocol protocol,
isc::asiolink::IOService& service, const isc::dns::Question& question,
const isc::asiolink::IOAddress& address, uint16_t port,
isc::util::OutputBufferPtr& buff, Callback* cb, int wait);
isc::util::OutputBufferPtr& buff, Callback* cb, int wait,
bool edns = true);
/// \brief Log I/O Failure
///
......
......@@ -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(&current_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()) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment