Browse Source

Merge branch 'trac2796'

Conflicts:
	ChangeLog
Yoshitaka Aharen 12 years ago
parent
commit
3d291f42cd

+ 2 - 0
src/bin/auth/auth_srv.cc

@@ -521,6 +521,8 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
         return;
     }
 
+    stats_attrs.setRequestRD(message.getHeaderFlag(Message::HEADERFLAG_RD));
+
     const Opcode& opcode = message.getOpcode();
     // Get opcode at this point; for all requests regardless of message body
     // sanity check.

+ 13 - 1
src/bin/auth/b10-auth.xml.pre

@@ -20,7 +20,7 @@
 <refentry>
 
   <refentryinfo>
-    <date>February 5, 2013</date>
+    <date>May 22, 2013</date>
   </refentryinfo>
 
   <refmeta>
@@ -248,6 +248,18 @@
         but remember that if there's any error related to TSIG, some
         of the counted opcode may not be trustworthy.
       </para>
+
+      <para>
+	The <quote>qryrecursion</quote> counter is limited to queries
+	(requests of opcode 0) even though the RD bit is not specific
+	to queries.  In practice, this bit is generally just ignored for
+	other types of requests, while DNS servers behave differently
+	for queries depending on this bit.  It is also known that
+	some authoritative-only servers receive a non negligible
+	number of queries with the RD bit being set, so it would be
+	of particular interest to have a specific counters for such
+	requests.
+      </para>
     </note>
 
   </refsect1>

+ 8 - 1
src/bin/auth/statistics.cc.pre

@@ -138,7 +138,14 @@ Counters::incRequest(const MessageAttributes& msgattrs) {
     // if a short message which does not contain DNS header is received, or
     // a response message (i.e. QR bit is set) is received.
     if (opcode) {
-        server_msg_counter_.inc(opcode_to_msgcounter[opcode.get().getCode()]);
+        server_msg_counter_.inc(opcode_to_msgcounter[opcode->getCode()]);
+
+        if (opcode.get() == Opcode::QUERY()) {
+            // Recursion Desired bit
+            if (msgattrs.requestHasRD()) {
+                server_msg_counter_.inc(MSG_QRYRECURSION);
+            }
+        }
     }
 
     // TSIG

+ 18 - 0
src/bin/auth/statistics.h

@@ -66,6 +66,8 @@ private:
     enum BitAttributes {
         REQ_WITH_EDNS_0,            // request with EDNS ver.0
         REQ_WITH_DNSSEC_OK,         // DNSSEC OK (DO) bit is set in request
+        REQ_WITH_RD,                // Recursion Desired (RD) bit is set in
+                                    // request
         REQ_TSIG_SIGNED,            // request is signed with valid TSIG
         REQ_BADSIG,                 // request is signed but bad signature
         RES_IS_TRUNCATED,           // response is truncated
@@ -170,6 +172,22 @@ public:
         bit_attributes_[REQ_WITH_DNSSEC_OK] = with_dnssec_ok;
     }
 
+    /// \brief Return Recursion Desired (RD) bit of the request.
+    ///
+    /// \return true if Recursion Desired (RD) bit of the request is set
+    /// \throw None
+    bool requestHasRD() const {
+        return (bit_attributes_[REQ_WITH_RD]);
+    }
+
+    /// \brief Set Recursion Desired (RD) bit of the request.
+    ///
+    /// \param with_rd true if Recursion Desired (RD)bit of the request is set
+    /// \throw None
+    void setRequestRD(const bool with_rd) {
+        bit_attributes_[REQ_WITH_RD] = with_rd;
+    }
+
     /// \brief Return whether the request is TSIG signed or not.
     ///
     /// \return true if the request is TSIG signed

+ 1 - 0
src/bin/auth/statistics_msg_items.def

@@ -31,6 +31,7 @@ qrynoauthans	MSG_QRYNOAUTHANS		Number of queries received by the b10-auth server
 qryreferral	MSG_QRYREFERRAL			Number of queries received by the b10-auth server resulted in referral answer.
 qrynxrrset	MSG_QRYNXRRSET			Number of queries received by the b10-auth server resulted in NoError and AA bit is set in the response, but the number of answer RR == 0.
 authqryrej	MSG_QRYREJECT			Number of authoritative queries rejected by the b10-auth server.
+qryrecursion	MSG_QRYRECURSION		Number of queries received by the b10-auth server with "Recursion Desired" (RD) bit was set.
 rcode		msg_counter_rcode	Rcode statistics	=
 	noerror		MSG_RCODE_NOERROR	Number of requests received by the b10-auth server resulted in RCODE = 0 (NoError).
 	formerr		MSG_RCODE_FORMERR	Number of requests received by the b10-auth server resulted in RCODE = 1 (FormErr).

+ 58 - 0
src/bin/auth/tests/statistics_unittest.cc.pre

@@ -361,6 +361,64 @@ TEST_F(CountersTest, incrementTSIG) {
     }
 }
 
+TEST_F(CountersTest, incrementRD) {
+    Message response(Message::RENDER);
+    MessageAttributes msgattrs;
+    std::map<std::string, int> expect;
+
+    // Test these patterns:
+    //     OpCode         Recursion Desired
+    //    ---------------------------
+    //     0 (Query)      false
+    //     0 (Query)      true
+    //     2 (Status)     false
+    //     2 (Status)     true
+    //  Make sure the counter will be incremented only for the requests with
+    //  OpCode=Query and Recursion Desired (RD) bit=1.
+    int count_opcode_query = 0;
+    int count_opcode_status = 0;
+    for (int i = 0; i < 4; ++i) {
+        const bool is_recursion_desired = i & 1;
+        const uint8_t opcode_code = i & 0x2;
+        const Opcode opcode(opcode_code);
+        buildSkeletonMessage(msgattrs);
+        msgattrs.setRequestRD(is_recursion_desired);
+        msgattrs.setRequestOpCode(opcode);
+
+        response.setRcode(Rcode::REFUSED());
+        response.addQuestion(Question(Name("example.com"),
+                                      RRClass::IN(), RRType::AAAA()));
+        response.setHeaderFlag(Message::HEADERFLAG_QR);
+
+        counters.inc(msgattrs, response, true);
+
+        if (opcode == Opcode::QUERY()) {
+            ++count_opcode_query;
+        } else {
+            ++count_opcode_status;
+        }
+
+        expect.clear();
+        expect["opcode.query"] = count_opcode_query;
+        expect["opcode.status"] = count_opcode_status;
+        expect["request.v4"] = i+1;
+        expect["request.udp"] = i+1;
+        expect["request.edns0"] = i+1;
+        expect["request.dnssec_ok"] = i+1;
+        expect["responses"] = i+1;
+        // qryrecursion will (only) be incremented if i == 1: OpCode=Query and
+        // RD bit=1
+        expect["qryrecursion"] = (i == 0) ? 0 : 1;
+        expect["rcode.refused"] = i+1;
+        // these counters are for queries; the value will be equal to the
+        // number of requests with OpCode=Query
+        expect["qrynoauthans"] = count_opcode_query;
+        expect["authqryrej"] = count_opcode_query;
+        checkStatisticsCounters(counters.get()->get("zones")->get("_SERVER_"),
+                                expect);
+    }
+}
+
 TEST_F(CountersTest, incrementOpcode) {
     Message response(Message::RENDER);
     MessageAttributes msgattrs;

+ 1 - 1
tests/lettuce/features/auth_badzone.feature

@@ -24,7 +24,7 @@ Feature: Authoritative DNS server with a bad zone
         And bind10 module Resolver should not be running
 
         A query for www.example.org should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have ancount 1
         The last query response should have nscount 2
         The last query response should have adcount 2

+ 1 - 1
tests/lettuce/features/example.feature

@@ -120,7 +120,7 @@ Feature: Example feature
         The last query response should have adcount 0
         # When checking flags, we must pass them exactly as they appear in
         # the output of dig.
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
 
         A query for www.example.org type TXT should have rcode NOERROR
         The last query response should have ancount 0

+ 14 - 14
tests/lettuce/features/nsec3_auth.feature

@@ -25,7 +25,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for a.c.x.w.example. should have rcode NXDOMAIN
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 8
@@ -57,7 +57,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for ns1.example. type MX should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 4
@@ -85,7 +85,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for y.w.example. should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 4
@@ -113,7 +113,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for mc.c.example. type MX should have rcode NOERROR
-        The last query response should have flags qr rd
+        The last query response should have flags qr
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 6
@@ -148,7 +148,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for a.z.w.example. type MX should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 2
         The last query response should have nscount 5
@@ -195,7 +195,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for a.z.w.example. type AAAA should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 8
@@ -227,7 +227,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for example. type DS should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 4
@@ -259,7 +259,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for b.x.w.example. should have rcode NXDOMAIN
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 6
@@ -289,7 +289,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for a.w.example. should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 6
@@ -319,7 +319,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for *.w.example. type MX should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 2
         The last query response should have nscount 3
@@ -362,7 +362,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for *.w.example. type A should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 4
@@ -390,7 +390,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. type NSEC3 should have rcode NXDOMAIN
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 8
@@ -422,7 +422,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for ai.example. type DS should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 4
@@ -450,7 +450,7 @@ Feature: NSEC3 Authoritative service
         And bind10 module StatsHttpd should not be running
 
         A dnssec query for c.example. type DS should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 6

+ 6 - 5
tests/lettuce/features/queries.feature

@@ -75,7 +75,7 @@ Feature: Querying feature
         The statistics counters are 0 in category .Auth.zones._SERVER_
 
         A query for www.example.org should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have ancount 1
         The last query response should have nscount 2
         The last query response should have adcount 2
@@ -121,7 +121,7 @@ Feature: Querying feature
 
         # Repeat of the above
         A query for www.example.org should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have ancount 1
         The last query response should have nscount 2
         The last query response should have adcount 2
@@ -165,7 +165,7 @@ Feature: Querying feature
           | rcode.noerror |          2 |
 
         # And now query something completely different
-        A query for nosuchname.example.org should have rcode NXDOMAIN
+        A recursive query for nosuchname.example.org should have rcode NXDOMAIN
         The last query response should have flags qr aa rd
         The last query response should have ancount 0
         The last query response should have nscount 1
@@ -196,6 +196,7 @@ Feature: Querying feature
           | responses      |          3 |
           | qrysuccess     |          2 |
           | qryauthans     |          3 |
+          | qryrecursion   |          1 |
           | rcode.noerror  |          2 |
           | rcode.nxdomain |          1 |
 
@@ -225,7 +226,7 @@ Feature: Querying feature
         The statistics counters are 0 in category .Auth.zones._SERVER_
 
         A query for example.org type ANY should have rcode NOERROR
-        The last query response should have flags qr aa rd
+        The last query response should have flags qr aa
         The last query response should have ancount 4
         The last query response should have nscount 0
         The last query response should have adcount 3
@@ -284,7 +285,7 @@ Feature: Querying feature
         The statistics counters are 0 in category .Auth.zones._SERVER_
 
         A dnssec query for www.sub.example.org type AAAA should have rcode NOERROR
-        The last query response should have flags qr rd
+        The last query response should have flags qr
         The last query response should have edns_flags do
         The last query response should have ancount 0
         The last query response should have nscount 1

+ 3 - 3
tests/lettuce/features/resolver_basic.feature

@@ -24,13 +24,13 @@ Feature: Basic Resolver
         And bind10 module StatsHttpd should not be running
 
         # The ACL is set to reject any queries
-        A query for l.root-servers.net. should have rcode REFUSED
+        A recursive query for l.root-servers.net. should have rcode REFUSED
 
         # Test whether acl ACCEPT works
         When I set bind10 configuration Resolver/query_acl[0] to {"action": "ACCEPT", "from": "127.0.0.1"}
         # This address is currently hardcoded, so shouldn't cause outside traffic
-        A query for l.root-servers.net. should have rcode NOERROR
+        A recursive query for l.root-servers.net. should have rcode NOERROR
 
         # Check whether setting the ACL to reject again works
         When I set bind10 configuration Resolver/query_acl[0] to {"action": "REJECT", "from": "127.0.0.1"}
-        A query for l.root-servers.net. should have rcode REFUSED
+        A recursive query for l.root-servers.net. should have rcode REFUSED

+ 10 - 2
tests/lettuce/features/terrain/querying.py

@@ -200,14 +200,19 @@ class QueryResult(object):
         """
         pass
 
-@step('A (dnssec )?query for ([\S]+) (?:type ([A-Z0-9]+) )?' +
+@step('A (dnssec )?(recursive )?query for ([\S]+) (?:type ([A-Z0-9]+) )?' +
       '(?:class ([A-Z]+) )?(?:to ([^:]+|\[[0-9a-fA-F:]+\])(?::([0-9]+))? )?' +
       'should have rcode ([\w.]+)')
-def query(step, dnssec, query_name, qtype, qclass, addr, port, rcode):
+def query(step, dnssec, recursive, query_name, qtype, qclass, addr, port,
+          rcode):
     """
     Run a query, check the rcode of the response, and store the query
     result in world.last_query_result.
     Parameters:
+    dnssec ('dnssec'): DO bit is set in the query.
+                       Defaults to unset (no DNSSEC).
+    recursive ('recursive'): RD bit is set in the query.
+                             Defaults to unset (no recursion).
     query_name ('query for <name>'): The domain name to query.
     qtype ('type <type>', optional): The RR type to query. Defaults to A.
     qclass ('class <class>', optional): The RR class to query. Defaults to IN.
@@ -234,6 +239,9 @@ def query(step, dnssec, query_name, qtype, qclass, addr, port, rcode):
         # additional counts, so unless we need dnssec, explicitly
         # disable edns0
         additional_arguments.append("+noedns")
+    # dig sets RD bit by default.
+    if recursive is None:
+        additional_arguments.append("+norecurse")
     query_result = QueryResult(query_name, qtype, qclass, addr, port,
                                additional_arguments)
     assert query_result.rcode == rcode,\