]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Tests! better coverage of cases in module.
authorYuri Schaeffer <yuri@nlnetlabs.nl>
Fri, 25 Jan 2013 17:05:07 +0000 (17:05 +0000)
committerYuri Schaeffer <yuri@nlnetlabs.nl>
Fri, 25 Jan 2013 17:05:07 +0000 (17:05 +0000)
testpkts now handles empty HEX_EDNSDATA block.

git-svn-id: file:///svn/unbound/branches/edns-subnet@2823 be551aaa-1e26-0410-a405-d3ace91eadb9

edns-subnet/subnetmod.c
services/mesh.c
services/outside_network.c
testcode/ldns-testpkts.c
testdata/subnet_derived.crpl [new file with mode: 0644]
testdata/subnet_format_ip4.crpl
testdata/subnet_nondefault_opc.crpl [new file with mode: 0644]
testdata/subnet_not_whitelisted.crpl [new file with mode: 0644]
testdata/subnet_without_validator.crpl [new file with mode: 0644]

index f6ab787c5e71d153817b43f896d333611805d42d..887a48f7717563b850156890240d1d36395d0651 100644 (file)
@@ -51,6 +51,15 @@ void subnetmod_inform_super(struct module_qstate* qstate, int id, struct module_
 {
 }
 
+void cp_edns_bad_response(struct edns_data* target, struct edns_data* source)
+{
+       target->subnet_scope_mask  = 0;
+       target->subnet_source_mask = source->subnet_source_mask;
+       target->subnet_addr_fam    = source->subnet_addr_fam;
+       memcpy(target->subnet_addr,  source->subnet_addr, INET6_SIZE);
+       target->subnet_validdata = 1;
+}
+
 void subnetmod_operate(struct module_qstate* qstate, enum module_ev event, 
        int id, struct outbound_entry* ATTR_UNUSED(outbound))
 {
@@ -73,6 +82,7 @@ void subnetmod_operate(struct module_qstate* qstate, enum module_ev event,
                (event == module_event_pass && snq == NULL)) {
                snq = sub_new(qstate, id);
                edns_from_client = qstate->edns_from_client;
+               
                if(!edns_from_client || !edns_from_client->subnet_validdata) {
                        /* No clients are interested in result or we could not
                         * parse it, we don't do vandergaast */
@@ -84,6 +94,7 @@ void subnetmod_operate(struct module_qstate* qstate, enum module_ev event,
                /* copy information from client request to upstream query */
                memcpy(&qstate->edns_out, edns_from_client, sizeof(struct edns_data));
                qstate->edns_out.subnet_scope_mask = 0;
+               qstate->edns_out.subnet_sent = 0;
 #if 0
                while(1) {
                        /* cache returns valid answer with largest mask. */
@@ -142,46 +153,50 @@ void subnetmod_operate(struct module_qstate* qstate, enum module_ev event,
        /* Query handed back by next module, we have a 'final' answer */
        if(event == module_event_moddone) {
                verbose(VERB_QUERY, "subnet: done");
-               /* There are no clients */
-               if(!qstate->mesh_info->reply_list) {
-                       qstate->edns_in.subnet_validdata = 0;
-                       qstate->ext_state[id] = module_finished;
-                       return;
-               }
-               verbose(VERB_QUERY, "subnet: work todo");
-               if(qstate->edns_in.subnet_validdata && qstate->edns_out.subnet_sent) {
-                       verbose(VERB_QUERY, "subnet: is not cached");
-                       /* can we accept response? */
-                       size_t sn_octs, remainder;
-                       sn_octs = qstate->edns_out.subnet_source_mask / 8;
-                       remainder = 8 - (size_t)(qstate->edns_out.subnet_source_mask % 8);
-                       if(qstate->edns_out.subnet_addr_fam != qstate->edns_in.subnet_addr_fam ||
-                               qstate->edns_out.subnet_source_mask != qstate->edns_in.subnet_source_mask ||
-                               memcmp(qstate->edns_out.subnet_addr, qstate->edns_in.subnet_addr, sn_octs) != 0 ||
-                               (qstate->edns_out.subnet_addr[sn_octs]^qstate->edns_in.subnet_addr[sn_octs])>>remainder) {
-                               /* we can not, restart query without option */
-                               verbose(VERB_QUERY, "subnet: forged data");
-                               qstate->edns_out.subnet_validdata = 0;
-                               qstate->ext_state[id] = module_wait_module;
-                               return;
+               qstate->edns_to_client = NULL;
+               if (!qstate->edns_out.subnet_sent) {
+                       if (qstate->edns_in.subnet_validdata) {
+                               verbose(VERB_QUERY, "subnet: received spurious data");
                        }
-                       verbose(VERB_QUERY, "subnet: now cache it");
-                       // TODO PUT IT IN OUR SPECIAL CACHE
-                       if(qstate->edns_out.subnet_downstream) {
-                               verbose(VERB_QUERY, "subnet: attach");
-                               /* client wants to see option */
-                               qstate->edns_in.subnet_validdata = 1;
+                       if (qstate->edns_out.subnet_downstream) {
+                               qstate->edns_to_client = &qstate->edns_in;
+                               cp_edns_bad_response(qstate->edns_to_client, 
+                                                                       qstate->edns_from_client);
+                       }
+               } else {
+                       /* subnet sent but nothing came back */
+                       if (!qstate->edns_in.subnet_validdata) {
+                               // TODO PUT IT IN OUR SPECIAL CACHE
+                               if (qstate->edns_out.subnet_downstream) {
+                                       qstate->edns_to_client = &qstate->edns_in;
+                                       cp_edns_bad_response(qstate->edns_to_client, 
+                                                                               qstate->edns_from_client);
+                               }
+                       } else {
+                               verbose(VERB_QUERY, "subnet: is not cached");
+                               /* can we accept response? */
+                               size_t sn_octs, remainder;
+                               sn_octs = qstate->edns_out.subnet_source_mask / 8;
+                               remainder = 8 - (size_t)(qstate->edns_out.subnet_source_mask % 8);
+                               if(qstate->edns_out.subnet_addr_fam != qstate->edns_in.subnet_addr_fam ||
+                                       qstate->edns_out.subnet_source_mask != qstate->edns_in.subnet_source_mask ||
+                                       memcmp(qstate->edns_out.subnet_addr, qstate->edns_in.subnet_addr, sn_octs) != 0 ||
+                                       (qstate->edns_out.subnet_addr[sn_octs]^qstate->edns_in.subnet_addr[sn_octs])>>remainder) {
+                                       /* we can not, restart query without option */
+                                       verbose(VERB_QUERY, "subnet: forged data");
+                                       qstate->edns_out.subnet_validdata = 0;
+                                       qstate->ext_state[id] = module_wait_module;
+                                       return;
+                               }
+                               verbose(VERB_QUERY, "subnet: now cache it");
+                               // TODO PUT IT IN OUR SPECIAL CACHE
+                               if (qstate->edns_out.subnet_downstream) {
+                                       qstate->edns_to_client = qstate->edns_from_client;
+                                       verbose(VERB_QUERY, "subnet: attach");
+                                       qstate->edns_to_client->subnet_scope_mask = 
+                                               qstate->edns_in.subnet_scope_mask;
+                               }
                        }
-               } else if(qstate->edns_out.subnet_downstream) {
-                       /* client wants to see option but we din't get anything
-                        * back from server (that we've asked for). Copy request
-                        * with scope 0 */
-                       verbose(VERB_QUERY, "subnet: attach");
-                       qstate->edns_in.subnet_scope_mask = 0;
-                       qstate->edns_in.subnet_source_mask = qstate->edns_out.subnet_source_mask;
-                       qstate->edns_in.subnet_addr_fam = qstate->edns_out.subnet_addr_fam;
-                       memcpy(qstate->edns_in.subnet_addr, qstate->edns_out.subnet_addr, INET6_SIZE);
-                       qstate->edns_in.subnet_validdata = 1;
                }
                qstate->ext_state[id] = module_finished;
                return;
index 27d6a95213ad0f32352f57f93462a28efa9085f3..86ef0b2b3ea783f4197b980eecf2d83f80eafee8 100644 (file)
@@ -370,6 +370,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
        } else {
                struct sockaddr_storage *ss;
                void* sinaddr;
+               edns->subnet_downstream = 0;
                /* Construct subnet option from original query */
                ss = &s->reply_list->query_reply.addr;
                if(((struct sockaddr_in*)ss)->sin_family == AF_INET) {
@@ -594,6 +595,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
        mstate->s.prefetch_leeway = 0;
 #ifdef CLIENT_SUBNET
        mstate->s.edns_from_client = NULL;
+       mstate->s.edns_to_client = NULL;
 #endif
        /* init modules */
        for(i=0; i<env->mesh->mods.num; i++) {
index 0945b24b1cedd4f843b717fa31a0131037cc2696..7968faadc721838bf7a2d5d8729bd94d054093b8 100644 (file)
@@ -1860,8 +1860,8 @@ outnet_serviced_query(struct outside_network* outnet,
                        sq->edns = edns;
                        /* This tells our module we've appened the option*/
                        edns->subnet_sent = 1;
-               }
-#endif         
+               } 
+#endif
                /* perform first network action */
                if(outnet->do_udp && !(tcp_upstream || ssl_upstream)) {
                        if(!serviced_udp_send(sq, buff)) {
index 53b19f7615bf62c120787ad0a546df7c632703ef..d3f473f08c0b632a5c3fe9392377b4fc03bfa3a9 100644 (file)
@@ -711,19 +711,29 @@ match_ednsdata(ldns_pkt* q, struct reply_packet* p)
 {
        size_t qdlen, pdlen;
        uint8_t *qd, *pd;
-       if(!ldns_pkt_edns(q) || !ldns_pkt_edns_data(q)) {
-               verbose(3, "No EDNS data\n");
-               return 0;
+       int q_set = ldns_pkt_edns(q) && ldns_pkt_edns_data(q);
+       int p_set = p->raw_ednsdata != NULL;
+       
+       if (p_set) {
+               pdlen = ldns_buffer_limit(p->raw_ednsdata);
+               pd = ldns_buffer_begin(p->raw_ednsdata);
+               verbose_hex(3, pd, pdlen, "edns expect: ");
+       } else {
+               verbose(3, "edns expect: <NULL>");
        }
-       qdlen = ldns_rdf_size(ldns_pkt_edns_data(q));
-       pdlen = ldns_buffer_limit(p->raw_ednsdata);
-       qd = ldns_rdf_data(ldns_pkt_edns_data(q));
-       pd = ldns_buffer_begin(p->raw_ednsdata);
-       if( qdlen == pdlen && 0 == memcmp(qd, pd, qdlen) ) return 1;
-       verbose(3, "EDNS data does not match.\n");
-       verbose_hex(3, qd, qdlen, "q: ");
-       verbose_hex(3, pd, pdlen, "p: ");
-       return 0;
+       if (q_set) {
+               qdlen = ldns_rdf_size(ldns_pkt_edns_data(q));
+               qd = ldns_rdf_data(ldns_pkt_edns_data(q));
+               verbose_hex(3, qd, qdlen, "edns got   : ");
+       } else {
+               verbose(3, "edns got   : <NULL>");
+       }
+       if ((!p_set || pdlen == 0) && !q_set)
+               return 1;
+       else if (!p_set || !q_set)
+               return 0;
+       else 
+               return qdlen == pdlen && 0 == memcmp(qd, pd, qdlen);
 }
 
 /* finds entry in list, or returns NULL */
diff --git a/testdata/subnet_derived.crpl b/testdata/subnet_derived.crpl
new file mode 100644 (file)
index 0000000..e5fadf1
--- /dev/null
@@ -0,0 +1,176 @@
+server:
+       send-client-subnet: 5.0.15.10
+       send-client-subnet: 193.0.14.129 
+       client-subnet-opc: 20730
+       max-client-subnet-ipv4: 21
+       verbosity: 3
+       module-config: "subnetcache validator iterator"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Must not send subnet option for 'derived' queries.
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 193.0.14.129 
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       . IN NS
+               SECTION ANSWER
+                       . IN NS K.ROOT-SERVERS.NET.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       K.ROOT-SERVERS.NET.     IN      A       193.0.14.129
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       a.gtld-servers.net. IN AAAA
+               SECTION AUTHORITY
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION AUTHORITY
+                       com.    IN NS   a.gtld-servers.net.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                                                       ; client is 127.0.0.1
+                               50 fa           ; OPC
+                               00 07           ; option length
+                               00 01           ; Family
+                               15 00           ; source mask, scopemask
+                               7f 00 00        ; address
+                       HEX_EDNSDATA_END
+                       a.gtld-servers.net.     IN      A       192.5.6.30
+       ENTRY_END
+       
+RANGE_END
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 192.5.6.30
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname
+               ADJUST copy_id copy_query
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION AUTHORITY
+                       example.com.    IN NS   ns.example.com.
+               SECTION ADDITIONAL
+                       ns.example.com.         IN      A       5.0.15.10
+       ENTRY_END
+       
+RANGE_END
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 5.0.15.10
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       example.com. IN NS
+               SECTION ANSWER
+                       example.com.    IN NS   ns.example.com.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       ns.example.com.     IN      A       5.0.15.10
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       ns.example.com. IN AAAA
+               SECTION ANSWER
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode subdomain ednsdata
+               ADJUST copy_id copy_query
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ANSWER
+                       www.example.com.        IN A    4.3.2.1
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                                                       ; client is 127.0.0.1
+                               50 fa           ; OPC
+                               00 07           ; option length
+                               00 01           ; Family
+                               15 00           ; source mask, scopemask
+                               7f 00 00        ; address
+                       HEX_EDNSDATA_END
+       ENTRY_END
+       
+RANGE_END
+
+;; ----------------------------------------
+
+STEP 1 QUERY
+
+       ENTRY_BEGIN
+               REPLY RD
+               SECTION QUESTION
+               www.example.com. IN A
+       ENTRY_END
+
+STEP 5 CHECK_OUT_QUERY
+
+       ENTRY_BEGIN
+               MATCH qname qtype opcode ednsdata
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we must send empty back to unbound
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+STEP 10 CHECK_ANSWER
+
+       ENTRY_BEGIN
+               MATCH all
+               REPLY QR RD RA NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ANSWER
+                       www.example.com.        IN A    4.3.2.1
+               SECTION AUTHORITY
+               SECTION ADDITIONAL
+       ENTRY_END
+
+SCENARIO_END
index e39f35a3f409736b8693cbe5d74ba0d4d9db5820..aa4883063e496547fb568d92b291b4214b7b3239 100644 (file)
@@ -10,154 +10,164 @@ stub-zone:
        stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
 CONFIG_END
 
-SCENARIO_BEGIN Test formatting of edns subnet option
+SCENARIO_BEGIN Subnet option ONLY in final query
 
-; K.ROOT-SERVERS.NET.
 RANGE_BEGIN 0 100
+
        ADDRESS 193.0.14.129 
-ENTRY_BEGIN
-MATCH opcode qtype qname
-ADJUST copy_id
-REPLY QR NOERROR
-SECTION QUESTION
-. IN NS
-SECTION ANSWER
-. IN NS        K.ROOT-SERVERS.NET.
-SECTION ADDITIONAL
-K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
-ENTRY_END
-
-ENTRY_BEGIN
-MATCH opcode qtype qname
-ADJUST copy_id
-REPLY QR NOERROR
-SECTION QUESTION
-a.gtld-servers.net. IN AAAA
-SECTION AUTHORITY
-SECTION ADDITIONAL
-ENTRY_END
-
-ENTRY_BEGIN
-MATCH opcode qtype qname
-ADJUST copy_id
-REPLY QR NOERROR
-SECTION QUESTION
-www.example.com. IN A
-SECTION AUTHORITY
-com.   IN NS   a.gtld-servers.net.
-SECTION ADDITIONAL
-a.gtld-servers.net.    IN      A       192.5.6.30
-ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       . IN NS
+               SECTION ANSWER
+                       . IN NS K.ROOT-SERVERS.NET.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       K.ROOT-SERVERS.NET.     IN      A       193.0.14.129
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       a.gtld-servers.net. IN AAAA
+               SECTION AUTHORITY
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION AUTHORITY
+                       com.    IN NS   a.gtld-servers.net.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       a.gtld-servers.net.     IN      A       192.5.6.30
+       ENTRY_END
+       
 RANGE_END
 
-; a.gtld-servers.net.
 RANGE_BEGIN 0 100
+
        ADDRESS 192.5.6.30
-ENTRY_BEGIN
-MATCH opcode qtype qname
-ADJUST copy_id
-REPLY QR NOERROR
-SECTION QUESTION
-com. IN NS
-SECTION ANSWER
-com.    IN NS   a.gtld-servers.net.
-SECTION ADDITIONAL
-a.gtld-servers.net.     IN      A       192.5.6.30
-ENTRY_END
-
-ENTRY_BEGIN
-MATCH opcode qtype qname
-ADJUST copy_id
-REPLY QR NOERROR
-SECTION QUESTION
-a.gtld-servers.net. IN AAAA
-SECTION ANSWER
-SECTION ADDITIONAL
-ENTRY_END
-
-ENTRY_BEGIN
-MATCH opcode subdomain
-ADJUST copy_id copy_query
-REPLY QR NOERROR
-SECTION QUESTION
-example.com. IN A
-SECTION AUTHORITY
-example.com.   IN NS   ns.example.com.
-SECTION ADDITIONAL
-ns.example.com.                IN      A       5.0.15.10
-ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode subdomain ednsdata
+               ADJUST copy_id copy_query
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       example.com. IN A
+               SECTION AUTHORITY
+                       example.com.    IN NS   ns.example.com.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       ns.example.com.         IN      A       5.0.15.10
+       ENTRY_END
+       
 RANGE_END
 
-; ns.example.com.
 RANGE_BEGIN 0 100
+
        ADDRESS 5.0.15.10
-ENTRY_BEGIN
-MATCH opcode qtype qname
-ADJUST copy_id
-REPLY QR NOERROR
-SECTION QUESTION
-example.com. IN NS
-SECTION ANSWER
-example.com.    IN NS   ns.example.com.
-SECTION ADDITIONAL
-ns.example.com.     IN      A       5.0.15.10
-ENTRY_END
-
-ENTRY_BEGIN
-MATCH opcode qtype qname
-ADJUST copy_id
-REPLY QR NOERROR
-SECTION QUESTION
-ns.example.com. IN AAAA
-SECTION ANSWER
-SECTION ADDITIONAL
-ENTRY_END
-
-ENTRY_BEGIN
-MATCH opcode subdomain
-ADJUST copy_id copy_query
-REPLY QR NOERROR
-SECTION QUESTION
-www.example.com. IN A
-SECTION ANSWER
-www.example.com.       IN A    4.3.2.1
-ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       example.com. IN NS
+               SECTION ANSWER
+                       example.com.    IN NS   ns.example.com.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       ns.example.com.     IN      A       5.0.15.10
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       ns.example.com. IN AAAA
+               SECTION ANSWER
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode subdomain ednsdata
+               ADJUST copy_id copy_query
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ANSWER
+                       www.example.com.        IN A    4.3.2.1
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                                                       ; client is 127.0.0.1
+                               50 fa           ; OPC
+                               00 07           ; option length
+                               00 01           ; Family
+                               15 00           ; source mask, scopemask
+                               7f 00 00        ; address
+                       HEX_EDNSDATA_END
+       ENTRY_END
+       
 RANGE_END
 
+;; ----------------------------------------
+
 STEP 1 QUERY
-ENTRY_BEGIN
-REPLY RD
-SECTION QUESTION
-www.example.com. IN A
-ENTRY_END
 
-; query sent to .com server
+       ENTRY_BEGIN
+               REPLY RD
+               SECTION QUESTION
+               www.example.com. IN A
+       ENTRY_END
+
 STEP 5 CHECK_OUT_QUERY
-ENTRY_BEGIN
-MATCH qname qtype opcode ednsdata
-SECTION QUESTION
-www.example.com. IN A
-SECTION ADDITIONAL
-HEX_EDNSDATA_BEGIN
-                               ; client is 127.0.0.1
-       50 fa           ; OPC
-       00 07           ; option length
-       00 01           ; Family
-       15 00           ; source mask, scopemask
-       7f 00 00        ; address
-HEX_EDNSDATA_END
-ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH qname qtype opcode ednsdata
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we must send empty back to unbound
+                       HEX_EDNSDATA_END
+       ENTRY_END
 
 STEP 10 CHECK_ANSWER
-ENTRY_BEGIN
-MATCH all
-REPLY QR RD RA NOERROR
-SECTION QUESTION
-www.example.com. IN A
-SECTION ANSWER
-www.example.com.       IN A    4.3.2.1
-SECTION AUTHORITY
-SECTION ADDITIONAL
-ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH all
+               REPLY QR RD RA NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ANSWER
+                       www.example.com.        IN A    4.3.2.1
+               SECTION AUTHORITY
+               SECTION ADDITIONAL
+       ENTRY_END
 
 SCENARIO_END
diff --git a/testdata/subnet_nondefault_opc.crpl b/testdata/subnet_nondefault_opc.crpl
new file mode 100644 (file)
index 0000000..0348434
--- /dev/null
@@ -0,0 +1,173 @@
+server:
+       send-client-subnet: 5.0.15.10
+       client-subnet-opc: 99
+       max-client-subnet-ipv4: 21
+       verbosity: 3
+       module-config: "subnetcache validator iterator"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Works for other than default OPC
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 193.0.14.129 
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       . IN NS
+               SECTION ANSWER
+                       . IN NS K.ROOT-SERVERS.NET.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       K.ROOT-SERVERS.NET.     IN      A       193.0.14.129
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       a.gtld-servers.net. IN AAAA
+               SECTION AUTHORITY
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION AUTHORITY
+                       com.    IN NS   a.gtld-servers.net.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       a.gtld-servers.net.     IN      A       192.5.6.30
+       ENTRY_END
+       
+RANGE_END
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 192.5.6.30
+
+       ENTRY_BEGIN
+               MATCH opcode subdomain ednsdata
+               ADJUST copy_id copy_query
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       example.com. IN A
+               SECTION AUTHORITY
+                       example.com.    IN NS   ns.example.com.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       ns.example.com.         IN      A       5.0.15.10
+       ENTRY_END
+       
+RANGE_END
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 5.0.15.10
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       example.com. IN NS
+               SECTION ANSWER
+                       example.com.    IN NS   ns.example.com.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       ns.example.com.     IN      A       5.0.15.10
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       ns.example.com. IN AAAA
+               SECTION ANSWER
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode subdomain ednsdata
+               ADJUST copy_id copy_query
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ANSWER
+                       www.example.com.        IN A    4.3.2.1
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                                                       ; client is 127.0.0.1
+                               00 63           ; OPC
+                               00 07           ; option length
+                               00 01           ; Family
+                               15 00           ; source mask, scopemask
+                               7f 00 00        ; address
+                       HEX_EDNSDATA_END
+       ENTRY_END
+       
+RANGE_END
+
+;; ----------------------------------------
+
+STEP 1 QUERY
+
+       ENTRY_BEGIN
+               REPLY RD
+               SECTION QUESTION
+               www.example.com. IN A
+       ENTRY_END
+
+STEP 5 CHECK_OUT_QUERY
+
+       ENTRY_BEGIN
+               MATCH qname qtype opcode ednsdata
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we must send empty back to unbound
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+STEP 10 CHECK_ANSWER
+
+       ENTRY_BEGIN
+               MATCH all
+               REPLY QR RD RA NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ANSWER
+                       www.example.com.        IN A    4.3.2.1
+               SECTION AUTHORITY
+               SECTION ADDITIONAL
+       ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/subnet_not_whitelisted.crpl b/testdata/subnet_not_whitelisted.crpl
new file mode 100644 (file)
index 0000000..105e0cb
--- /dev/null
@@ -0,0 +1,168 @@
+server:
+;      send-client-subnet: 5.0.15.10
+       client-subnet-opc: 20730
+       max-client-subnet-ipv4: 21
+       verbosity: 3
+       module-config: "subnetcache validator iterator"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Subnet option MUST NOT be send to any host
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 193.0.14.129 
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       . IN NS
+               SECTION ANSWER
+                       . IN NS K.ROOT-SERVERS.NET.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       K.ROOT-SERVERS.NET.     IN      A       193.0.14.129
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       a.gtld-servers.net. IN AAAA
+               SECTION AUTHORITY
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION AUTHORITY
+                       com.    IN NS   a.gtld-servers.net.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       a.gtld-servers.net.     IN      A       192.5.6.30
+       ENTRY_END
+       
+RANGE_END
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 192.5.6.30
+
+       ENTRY_BEGIN
+               MATCH opcode subdomain ednsdata
+               ADJUST copy_id copy_query
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       example.com. IN A
+               SECTION AUTHORITY
+                       example.com.    IN NS   ns.example.com.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       ns.example.com.         IN      A       5.0.15.10
+       ENTRY_END
+       
+RANGE_END
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 5.0.15.10
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       example.com. IN NS
+               SECTION ANSWER
+                       example.com.    IN NS   ns.example.com.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       ns.example.com.     IN      A       5.0.15.10
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       ns.example.com. IN AAAA
+               SECTION ANSWER
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode subdomain ednsdata
+               ADJUST copy_id copy_query
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ANSWER
+                       www.example.com.        IN A    4.3.2.1
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+       ENTRY_END
+       
+RANGE_END
+
+;; ----------------------------------------
+
+STEP 1 QUERY
+
+       ENTRY_BEGIN
+               REPLY RD
+               SECTION QUESTION
+               www.example.com. IN A
+       ENTRY_END
+
+STEP 5 CHECK_OUT_QUERY
+
+       ENTRY_BEGIN
+               MATCH qname qtype opcode ednsdata
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we must send empty back to unbound
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+STEP 10 CHECK_ANSWER
+
+       ENTRY_BEGIN
+               MATCH all
+               REPLY QR RD RA NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ANSWER
+                       www.example.com.        IN A    4.3.2.1
+               SECTION AUTHORITY
+               SECTION ADDITIONAL
+       ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/subnet_without_validator.crpl b/testdata/subnet_without_validator.crpl
new file mode 100644 (file)
index 0000000..a4c4e92
--- /dev/null
@@ -0,0 +1,173 @@
+server:
+       send-client-subnet: 5.0.15.10
+       client-subnet-opc: 20730
+       max-client-subnet-ipv4: 21
+       verbosity: 3
+       module-config: "subnetcache iterator"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Works without validator module
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 193.0.14.129 
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       . IN NS
+               SECTION ANSWER
+                       . IN NS K.ROOT-SERVERS.NET.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       K.ROOT-SERVERS.NET.     IN      A       193.0.14.129
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       a.gtld-servers.net. IN AAAA
+               SECTION AUTHORITY
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION AUTHORITY
+                       com.    IN NS   a.gtld-servers.net.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       a.gtld-servers.net.     IN      A       192.5.6.30
+       ENTRY_END
+       
+RANGE_END
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 192.5.6.30
+
+       ENTRY_BEGIN
+               MATCH opcode subdomain ednsdata
+               ADJUST copy_id copy_query
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       example.com. IN A
+               SECTION AUTHORITY
+                       example.com.    IN NS   ns.example.com.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       ns.example.com.         IN      A       5.0.15.10
+       ENTRY_END
+       
+RANGE_END
+
+RANGE_BEGIN 0 100
+
+       ADDRESS 5.0.15.10
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       example.com. IN NS
+               SECTION ANSWER
+                       example.com.    IN NS   ns.example.com.
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+                       ns.example.com.     IN      A       5.0.15.10
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode qtype qname ednsdata
+               ADJUST copy_id
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       ns.example.com. IN AAAA
+               SECTION ANSWER
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we expect to receive empty
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+       ENTRY_BEGIN
+               MATCH opcode subdomain ednsdata
+               ADJUST copy_id copy_query
+               REPLY QR NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ANSWER
+                       www.example.com.        IN A    4.3.2.1
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                                                       ; client is 127.0.0.1
+                               50 fa           ; OPC
+                               00 07           ; option length
+                               00 01           ; Family
+                               15 00           ; source mask, scopemask
+                               7f 00 00        ; address
+                       HEX_EDNSDATA_END
+       ENTRY_END
+       
+RANGE_END
+
+;; ----------------------------------------
+
+STEP 1 QUERY
+
+       ENTRY_BEGIN
+               REPLY RD
+               SECTION QUESTION
+               www.example.com. IN A
+       ENTRY_END
+
+STEP 5 CHECK_OUT_QUERY
+
+       ENTRY_BEGIN
+               MATCH qname qtype opcode ednsdata
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ADDITIONAL
+                       HEX_EDNSDATA_BEGIN
+                               ;; we must send empty back to unbound
+                       HEX_EDNSDATA_END
+       ENTRY_END
+
+STEP 10 CHECK_ANSWER
+
+       ENTRY_BEGIN
+               MATCH all
+               REPLY QR RD RA NOERROR
+               SECTION QUESTION
+                       www.example.com. IN A
+               SECTION ANSWER
+                       www.example.com.        IN A    4.3.2.1
+               SECTION AUTHORITY
+               SECTION ADDITIONAL
+       ENTRY_END
+
+SCENARIO_END