diff --git a/unbound-1.16.2/edns-subnet/addrtree.c b/unbound-1.16.2/edns-subnet/addrtree.c index 180a022..ebe71b9 100644 --- a/unbound-1.16.2/edns-subnet/addrtree.c +++ b/unbound-1.16.2/edns-subnet/addrtree.c @@ -97,6 +97,7 @@ node_create(struct addrtree *tree, void *elem, addrlen_t scope, tree->node_count++; node->scope = scope; node->ttl = ttl; + node->only_match_scope_zero = 0; node->edge[0] = NULL; node->edge[1] = NULL; node->parent_edge = NULL; @@ -155,6 +156,7 @@ clean_node(struct addrtree *tree, struct addrnode *node) if (!node->elem) return; tree->size_bytes -= tree->sizefunc(node->elem); tree->delfunc(tree->env, node->elem); + node->only_match_scope_zero = 0; node->elem = NULL; } @@ -358,7 +360,7 @@ issub(const addrkey_t *s1, addrlen_t l1, void addrtree_insert(struct addrtree *tree, const addrkey_t *addr, addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl, - time_t now) + time_t now, int only_match_scope_zero) { struct addrnode *newnode, *node; struct addredge *edge; @@ -381,6 +383,7 @@ addrtree_insert(struct addrtree *tree, const addrkey_t *addr, /* update this node's scope and data */ clean_node(tree, node); node->ttl = ttl; + node->only_match_scope_zero = only_match_scope_zero; node->elem = elem; node->scope = scope; tree->size_bytes += tree->sizefunc(elem); @@ -447,6 +450,7 @@ addrtree_insert(struct addrtree *tree, const addrkey_t *addr, newnode->elem = elem; newnode->scope = scope; newnode->ttl = ttl; + newnode->only_match_scope_zero = only_match_scope_zero; } tree->size_bytes += node_size(tree, newnode); @@ -483,7 +487,8 @@ addrtree_find(struct addrtree *tree, const addrkey_t *addr, /* Current node more specific then question. */ log_assert(depth <= sourcemask); /* does this node have data? if yes, see if we have a match */ - if (node->elem && node->ttl >= now) { + if (node->elem && node->ttl >= now && + !(sourcemask != 0 && node->only_match_scope_zero)) { /* saved at wrong depth */; log_assert(node->scope >= depth); if (depth == node->scope || diff --git a/unbound-1.16.2/edns-subnet/addrtree.h b/unbound-1.16.2/edns-subnet/addrtree.h index 1aea54e..0bc1837 100644 --- a/unbound-1.16.2/edns-subnet/addrtree.h +++ b/unbound-1.16.2/edns-subnet/addrtree.h @@ -95,6 +95,10 @@ struct addrnode { time_t ttl; /** Number of significant bits in address. */ addrlen_t scope; + /** Only use the element for queries for subnet/0. Set if the query + * for /0 was answered with scope 0. For query /x answer scope 0, + * they can match anything and this is false. */ + int only_match_scope_zero; /** A node can have 0-2 edges, set to NULL for unused */ struct addredge *edge[2]; /** edge between this node and parent */ @@ -157,11 +161,12 @@ void addrtree_delete(struct addrtree *tree); * @param scope: Number of significant bits in addr. * @param elem: data to store in the tree. * @param ttl: elem is valid up to this time, seconds. + * @param only_match_scope_zero: set for when query /0 has scope /0 answer. * @param now: Current time in seconds. */ void addrtree_insert(struct addrtree *tree, const addrkey_t *addr, addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl, - time_t now); + time_t now, int only_match_scope_zero); /** * Find a node containing an element in the tree. diff --git a/unbound-1.16.2/edns-subnet/subnetmod.c b/unbound-1.16.2/edns-subnet/subnetmod.c index 7544611..53d3048 100644 --- a/unbound-1.16.2/edns-subnet/subnetmod.c +++ b/unbound-1.16.2/edns-subnet/subnetmod.c @@ -51,10 +51,12 @@ #include "services/cache/dns.h" #include "util/module.h" #include "util/regional.h" +#include "util/fptr_wlist.h" #include "util/storage/slabhash.h" #include "util/config_file.h" #include "util/data/msgreply.h" #include "sldns/sbuffer.h" +#include "sldns/wire2str.h" #include "iterator/iter_utils.h" /** externally called */ @@ -151,10 +153,12 @@ int ecs_whitelist_check(struct query_info* qinfo, /* Cache by default, might be disabled after parsing EDNS option * received from nameserver. */ - if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL)) { + if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL) + && sq->ecs_client_in.subnet_validdata) { qstate->no_cache_store = 0; } + sq->subnet_sent_no_subnet = 0; if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream && qstate->env->cfg->client_subnet_always_forward) || ecs_is_whitelisted(sn_env->whitelist, @@ -165,6 +169,14 @@ int ecs_whitelist_check(struct query_info* qinfo, * set. */ if(!edns_opt_list_find(qstate->edns_opts_back_out, qstate->env->cfg->client_subnet_opcode)) { + /* if the client is not wanting an EDNS subnet option, + * omit it and store that we omitted it but actually + * are doing EDNS subnet to the server. */ + if(sq->ecs_server_out.subnet_source_mask == 0) { + sq->subnet_sent_no_subnet = 1; + sq->subnet_sent = 0; + return 1; + } subnet_ecs_opt_list_append(&sq->ecs_server_out, &qstate->edns_opts_back_out, qstate, region); } @@ -331,6 +343,7 @@ update_cache(struct module_qstate *qstate, int id) struct slabhash *subnet_msg_cache = sne->subnet_msg_cache; struct ecs_data *edns = &sq->ecs_client_in; size_t i; + int only_match_scope_zero; /* We already calculated hash upon lookup (lookup_and_reply) if we were * allowed to look in the ECS cache */ @@ -392,9 +405,12 @@ update_cache(struct module_qstate *qstate, int id) reply_info_set_ttls(rep, *qstate->env->now); rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */ rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */ + if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0) + only_match_scope_zero = 1; + else only_match_scope_zero = 0; addrtree_insert(tree, (addrkey_t*)edns->subnet_addr, edns->subnet_source_mask, sq->max_scope, rep, - rep->ttl, *qstate->env->now); + rep->ttl, *qstate->env->now, only_match_scope_zero); lock_rw_unlock(&lru_entry->lock); if (need_to_insert) { @@ -475,6 +491,69 @@ common_prefix(uint8_t *a, uint8_t *b, uint8_t net) return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]); } +/** + * Create sub request that looks up the query. + * @param qstate: query state + * @param sq: subnet qstate + * @return false on failure. + */ +static int +generate_sub_request(struct module_qstate *qstate, struct subnet_qstate* sq) +{ + struct module_qstate* subq = NULL; + uint16_t qflags = 0; /* OPCODE QUERY, no flags */ + int prime = 0; + int valrec = 0; + struct query_info qinf; + qinf.qname = qstate->qinfo.qname; + qinf.qname_len = qstate->qinfo.qname_len; + qinf.qtype = qstate->qinfo.qtype; + qinf.qclass = qstate->qinfo.qclass; + qinf.local_alias = NULL; + + qflags |= BIT_RD; + if((qstate->query_flags & BIT_CD)!=0) { + qflags |= BIT_CD; + valrec = 1; + } + + fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); + if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, valrec, + &subq)) { + return 0; + } + if(subq) { + /* It is possible to access the subquery module state. */ + if(sq->ecs_client_in.subnet_source_mask == 0 && + edns_opt_list_find(qstate->edns_opts_front_in, + qstate->env->cfg->client_subnet_opcode)) { + subq->no_cache_store = 1; + } + } + return 1; +} + +/** + * Perform the query without subnet + * @param qstate: query state + * @param sq: subnet qstate + * @return module state + */ +static enum module_ext_state +generate_lookup_without_subnet(struct module_qstate *qstate, + struct subnet_qstate* sq) +{ + verbose(VERB_ALGO, "subnetcache: make subquery to look up without subnet"); + if(!generate_sub_request(qstate, sq)) { + verbose(VERB_ALGO, "Could not generate sub query"); + qstate->return_rcode = LDNS_RCODE_FORMERR; + qstate->return_msg = NULL; + return module_finished; + } + sq->wait_subquery = 1; + return module_wait_subquery; +} + static enum module_ext_state eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) { @@ -495,7 +574,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) } /* We have not asked for subnet data */ - if (!sq->subnet_sent) { + if (!sq->subnet_sent && !sq->subnet_sent_no_subnet) { if (s_in->subnet_validdata) verbose(VERB_QUERY, "subnetcache: received spurious data"); if (sq->subnet_downstream) /* Copy back to client */ @@ -504,22 +583,27 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) } /* subnet sent but nothing came back */ - if (!s_in->subnet_validdata) { + if (!s_in->subnet_validdata && !sq->subnet_sent_no_subnet) { /* The authority indicated no support for edns subnet. As a * consequence the answer ended up in the regular cache. It * is still useful to put it in the edns subnet cache for * when a client explicitly asks for subnet specific answer. */ verbose(VERB_QUERY, "subnetcache: Authority indicates no support"); - if(!sq->started_no_cache_store) { - lock_rw_wrlock(&sne->biglock); - update_cache(qstate, id); - lock_rw_unlock(&sne->biglock); - } - if (sq->subnet_downstream) - cp_edns_bad_response(c_out, c_in); - return module_finished; + return generate_lookup_without_subnet(qstate, sq); } - + + /* Purposefully there was no sent subnet, and there is consequently + * no subnet in the answer. If there was, use the subnet in the answer + * anyway. But if there is not, treat it as a prefix 0 answer. */ + if(sq->subnet_sent_no_subnet && !s_in->subnet_validdata) { + /* Fill in 0.0.0.0/0 scope 0, or ::0/0 scope 0, for caching. */ + s_in->subnet_addr_fam = s_out->subnet_addr_fam; + s_in->subnet_source_mask = 0; + s_in->subnet_scope_mask = 0; + memset(s_in->subnet_addr, 0, INET6_SIZE); + s_in->subnet_validdata = 1; + } + /* Being here means we have asked for and got a subnet specific * answer. Also, the answer from the authority is not yet cached * anywhere. */ @@ -530,13 +614,14 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) !common_prefix(s_out->subnet_addr, s_in->subnet_addr, s_out->subnet_source_mask)) { - /* we can not accept, restart query without option */ + /* we can not accept, perform query without option */ verbose(VERB_QUERY, "subnetcache: forged data"); s_out->subnet_validdata = 0; (void)edns_opt_list_remove(&qstate->edns_opts_back_out, qstate->env->cfg->client_subnet_opcode); sq->subnet_sent = 0; - return module_restart_next; + sq->subnet_sent_no_subnet = 0; + return generate_lookup_without_subnet(qstate, sq); } lock_rw_wrlock(&sne->biglock); @@ -656,6 +741,7 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response, edns_opt_list_remove(&qstate->edns_opts_back_out, qstate->env->cfg->client_subnet_opcode); sq->subnet_sent = 0; + sq->subnet_sent_no_subnet = 0; memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out)); } else if (!sq->track_max_scope && FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR && @@ -674,6 +760,24 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response, return 1; } +/** verbose print edns subnet option in pretty print */ +static void +subnet_log_print(const char* s, struct edns_option* ecs_opt) +{ + if(verbosity >= VERB_ALGO) { + char buf[256]; + char* str = buf; + size_t str_len = sizeof(buf); + if(!ecs_opt) { + verbose(VERB_ALGO, "%s (null)", s); + return; + } + (void)sldns_wire2str_edns_subnet_print(&str, &str_len, + ecs_opt->opt_data, ecs_opt->opt_len); + verbose(VERB_ALGO, "%s %s", s, buf); + } +} + int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* ATTR_UNUSED(cbargs)) @@ -688,6 +792,7 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id, qstate->env->cfg->client_subnet_opcode)) && parse_subnet_option(ecs_opt, &sq->ecs_server_in) && sq->subnet_sent && sq->ecs_server_in.subnet_validdata) { + subnet_log_print("answer has edns subnet", ecs_opt); /* Only skip global cache store if we sent an ECS option * and received one back. Answers from non-whitelisted * servers will end up in global cache. Answers for @@ -698,6 +803,12 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id, sq->ecs_server_in.subnet_scope_mask > sq->max_scope)) sq->max_scope = sq->ecs_server_in.subnet_scope_mask; + } else if(sq->subnet_sent_no_subnet) { + /* The answer can be stored as scope 0, not in global cache. */ + qstate->no_cache_store = 1; + } else if(sq->subnet_sent) { + /* Need another query to be able to store in global cache. */ + qstate->no_cache_store = 1; } return 1; @@ -715,6 +826,32 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, strmodulevent(event)); log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo); + if(sq && sq->wait_subquery_done) { + /* The subquery lookup returned. */ + if(sq->ecs_client_in.subnet_source_mask == 0 && + edns_opt_list_find(qstate->edns_opts_front_in, + qstate->env->cfg->client_subnet_opcode)) { + if(!sq->started_no_cache_store && + qstate->return_msg) { + lock_rw_wrlock(&sne->biglock); + update_cache(qstate, id); + lock_rw_unlock(&sne->biglock); + } + if (sq->subnet_downstream) + cp_edns_bad_response(&sq->ecs_client_out, + &sq->ecs_client_in); + /* It is a scope zero lookup, append edns subnet + * option to the querier. */ + subnet_ecs_opt_list_append(&sq->ecs_client_out, + &qstate->edns_opts_front_out, qstate, + qstate->region); + } + sq->wait_subquery_done = 0; + qstate->ext_state[id] = module_finished; + qstate->no_cache_store = sq->started_no_cache_store; + qstate->no_cache_lookup = sq->started_no_cache_lookup; + return; + } if((event == module_event_new || event == module_event_pass) && sq == NULL) { struct edns_option* ecs_opt; @@ -725,6 +862,8 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, } sq = (struct subnet_qstate*)qstate->minfo[id]; + if(sq->wait_subquery) + return; /* Wait for that subquery to return */ if((ecs_opt = edns_opt_list_find( qstate->edns_opts_front_in, @@ -736,6 +875,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, qstate->ext_state[id] = module_finished; return; } + subnet_log_print("query has edns subnet", ecs_opt); sq->subnet_downstream = 1; } else if(qstate->mesh_info->reply_list) { @@ -748,6 +888,14 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, /* No clients are interested in result or we could not * parse it, we don't do client subnet */ sq->ecs_server_out.subnet_validdata = 0; + if(edns_opt_list_find(qstate->edns_opts_front_in, + qstate->env->cfg->client_subnet_opcode)) { + /* aggregated this deaggregated state */ + qstate->ext_state[id] = + generate_lookup_without_subnet( + qstate, sq); + return; + } verbose(VERB_ALGO, "subnetcache: pass to next module"); qstate->ext_state[id] = module_wait_module; return; @@ -775,10 +923,25 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, subnet_ecs_opt_list_append(&sq->ecs_client_out, &qstate->edns_opts_front_out, qstate, qstate->region); + if(verbosity >= VERB_ALGO) { + subnet_log_print("reply has edns subnet", + edns_opt_list_find( + qstate->edns_opts_front_out, + qstate->env->cfg-> + client_subnet_opcode)); + } return; } lock_rw_unlock(&sne->biglock); } + if(sq->ecs_client_in.subnet_source_mask == 0 && + edns_opt_list_find(qstate->edns_opts_front_in, + qstate->env->cfg->client_subnet_opcode)) { + /* client asked for resolution without edns subnet */ + qstate->ext_state[id] = generate_lookup_without_subnet( + qstate, sq); + return; + } sq->ecs_server_out.subnet_addr_fam = sq->ecs_client_in.subnet_addr_fam; @@ -815,6 +978,8 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, qstate->ext_state[id] = module_wait_module; return; } + if(sq && sq->wait_subquery) + return; /* Wait for that subquery to return */ /* Query handed back by next module, we have a 'final' answer */ if(sq && event == module_event_moddone) { qstate->ext_state[id] = eval_response(qstate, id, sq); @@ -823,6 +988,13 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, subnet_ecs_opt_list_append(&sq->ecs_client_out, &qstate->edns_opts_front_out, qstate, qstate->region); + if(verbosity >= VERB_ALGO) { + subnet_log_print("reply has edns subnet", + edns_opt_list_find( + qstate->edns_opts_front_out, + qstate->env->cfg-> + client_subnet_opcode)); + } } qstate->no_cache_store = sq->started_no_cache_store; qstate->no_cache_lookup = sq->started_no_cache_lookup; @@ -856,10 +1028,27 @@ subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate), } void -subnetmod_inform_super(struct module_qstate *ATTR_UNUSED(qstate), - int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super)) +subnetmod_inform_super(struct module_qstate *qstate, int id, + struct module_qstate *super) { - /* Not used */ + struct subnet_qstate* super_sq = + (struct subnet_qstate*)super->minfo[id]; + log_query_info(VERB_ALGO, "subnetcache inform_super: query", + &super->qinfo); + super_sq->wait_subquery = 0; + super_sq->wait_subquery_done = 1; + if(qstate->return_rcode != LDNS_RCODE_NOERROR || + !qstate->return_msg) { + super->return_msg = NULL; + super->return_rcode = LDNS_RCODE_SERVFAIL; + return; + } + super->return_rcode = LDNS_RCODE_NOERROR; + super->return_msg = dns_copy_msg(qstate->return_msg, super->region); + if(!super->return_msg) { + log_err("subnetcache: copy response, out of memory"); + super->return_rcode = LDNS_RCODE_SERVFAIL; + } } size_t diff --git a/unbound-1.16.2/edns-subnet/subnetmod.h b/unbound-1.16.2/edns-subnet/subnetmod.h index f0bcaad..3893820 100644 --- a/unbound-1.16.2/edns-subnet/subnetmod.h +++ b/unbound-1.16.2/edns-subnet/subnetmod.h @@ -85,6 +85,13 @@ struct subnet_qstate { struct ecs_data ecs_server_out; int subnet_downstream; int subnet_sent; + /** + * If there was no subnet sent because the client used source prefix + * length 0 for omitting the information. Then the answer is cached + * like subnet was a /0 scope. Like the subnet_sent flag, but when + * the EDNS subnet option is omitted because the client asked. + */ + int subnet_sent_no_subnet; /** keep track of longest received scope, set after receiving CNAME for * incoming QNAME. */ int track_max_scope; @@ -95,6 +102,10 @@ struct subnet_qstate { int started_no_cache_store; /** has the subnet module been started with no_cache_lookup? */ int started_no_cache_lookup; + /** Wait for subquery that has been started for nonsubnet lookup. */ + int wait_subquery; + /** The subquery waited for is done. */ + int wait_subquery_done; }; void subnet_data_delete(void* d, void* ATTR_UNUSED(arg)); diff --git a/unbound-1.16.2/iterator/iterator.c b/unbound-1.16.2/iterator/iterator.c index da9b799..3cacd5d 100644 --- a/unbound-1.16.2/iterator/iterator.c +++ b/unbound-1.16.2/iterator/iterator.c @@ -3982,10 +3982,10 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq, /* like packet got dropped */ goto handle_it; } - if(!inplace_cb_edns_back_parsed_call(qstate->env, qstate)) { - log_err("unable to call edns_back_parsed callback"); - goto handle_it; - } + } + if(!inplace_cb_edns_back_parsed_call(qstate->env, qstate)) { + log_err("unable to call edns_back_parsed callback"); + goto handle_it; } /* remove CD-bit, we asked for in case we handle validation ourself */ diff --git a/unbound-1.16.2/testcode/unitecs.c b/unbound-1.16.2/testcode/unitecs.c index b240bfc..68d6907 100644 --- a/unbound-1.16.2/testcode/unitecs.c +++ b/unbound-1.16.2/testcode/unitecs.c @@ -173,7 +173,7 @@ static void consistency_test(void) for (i = 0; i < 1000; i++) { l = randomkey(&k, 128); elem = (struct reply_info *) calloc(1, sizeof(struct reply_info)); - addrtree_insert(t, k, l, 64, elem, timenow + 10, timenow); + addrtree_insert(t, k, l, 64, elem, timenow + 10, timenow, 0); /* This should always hold because no items ever expire. They * could be overwritten, though. */ unit_assert( count <= t->node_count ); @@ -189,7 +189,7 @@ static void consistency_test(void) for (i = 0; i < 1000; i++) { l = randomkey(&k, 128); elem = (struct reply_info *) calloc(1, sizeof(struct reply_info)); - addrtree_insert(t, k, l, 64, elem, i + 10, i); + addrtree_insert(t, k, l, 64, elem, i + 10, i, 0); free(k); unit_assert( !addrtree_inconsistent(t) ); } @@ -201,7 +201,7 @@ static void consistency_test(void) for (i = 0; i < 1000; i++) { l = randomkey(&k, 128); elem = (struct reply_info *) calloc(1, sizeof(struct reply_info)); - addrtree_insert(t, k, l, 64, elem, i + 10, i); + addrtree_insert(t, k, l, 64, elem, i + 10, i, 0); unit_assert( t->node_count <= 27); free(k); unit_assert( !addrtree_inconsistent(t) ); diff --git a/unbound-1.16.2/testdata/subnet_noecs_mult.rpl b/unbound-1.16.2/testdata/subnet_noecs_mult.rpl new file mode 100644 index 0000000..3e2acef --- /dev/null +++ b/unbound-1.16.2/testdata/subnet_noecs_mult.rpl @@ -0,0 +1,334 @@ +# config +server: + send-client-subnet: 1.2.3.4 + max-client-subnet-ipv4: 17 + module-config: "subnetcache iterator" + qname-minimisation: no + minimal-responses: yes + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test subnet with no edns subnet from server multiple times +; Multiple queries are sent to a server that does not reply with the +; edns-subnet option. + +; 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 subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +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 subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 50 52 + ADDRESS 1.2.3.4 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. host.example.com. 4 86400 3600 86400 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION ADDITIONAL + ; Match this subnet option + HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 11 00 ; source mask, scopemask + 7f 00 00 ; address + HEX_EDNSDATA_END + ; This is the response, without the subnet option + HEX_ANSWER_BEGIN; + 00 00 84 00 00 01 00 01 ; ID 0 QR AA NOERROR + 00 00 00 01 03 77 77 77 ; www.example.com A (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 + C0 0C 00 01 00 01 00 00 0E 10 ; www.example.com. A IN 3600 + 00 04 0A 14 1E 2C ; rdata 10.20.30.44 + 00 00 29 10 00 00 00 + 80 00 00 00 + HEX_ANSWER_END +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION ADDITIONAL + ; Match this subnet option + HEX_EDNSDATA_BEGIN + ; client is 127.2.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 11 00 ; source mask, scopemask + 7f 02 00 ; address + HEX_EDNSDATA_END + ; This is the response, without the subnet option + HEX_ANSWER_BEGIN; + 00 00 84 00 00 01 00 01 ; ID 0 QR AA NOERROR + 00 00 00 01 03 77 77 77 ; www.example.com A (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 + C0 0C 00 01 00 01 00 00 0E 10 ; www.example.com. A IN 3600 + 00 04 0A 14 1E 2C ; rdata 10.20.30.44 + 00 00 29 10 00 00 00 + 80 00 00 00 + HEX_ANSWER_END +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION ADDITIONAL + ; Match this subnet option + HEX_EDNSDATA_BEGIN + ; client is 127.3.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 11 00 ; source mask, scopemask + 7f 03 00 ; address + HEX_EDNSDATA_END + ; This is the response, without the subnet option + HEX_ANSWER_BEGIN; + 00 00 84 00 00 01 00 01 ; ID 0 QR AA NOERROR + 00 00 00 01 03 77 77 77 ; www.example.com A (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 + C0 0C 00 01 00 01 00 00 0E 10 ; www.example.com. A IN 3600 + 00 04 0A 14 1E 2C ; rdata 10.20.30.44 + 00 00 29 10 00 00 00 + 80 00 00 00 + HEX_ANSWER_END +ENTRY_END + +; The answer for a query without subnet +;ENTRY_BEGIN +;MATCH opcode qtype qname +;ADJUST copy_id +;REPLY QR AA NOERROR +;SECTION QUESTION +;www.example.com. IN A +;SECTION ANSWER +;www.example.com. IN A 10.20.30.40 +;ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 53 57 + ADDRESS 1.2.3.4 +; The answer for a query without subnet +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +RANGE_END + +STEP 10 QUERY +ENTRY_BEGIN + HEX_ANSWER_BEGIN; + 00 00 01 00 00 01 00 00 ; ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 11 00 ; ip4, scope 17, source 0 + 7f 00 00 ; 127.0.0.0/17 + HEX_ANSWER_END +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN + HEX_ANSWER_BEGIN; + 00 00 01 00 00 01 00 00 ; ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 11 00 ; ip4, scope 17, source 0 + 7f 02 00 ; 127.2.0.0/17 + HEX_ANSWER_END +ENTRY_END + +STEP 30 QUERY +ENTRY_BEGIN + HEX_ANSWER_BEGIN; + 00 00 01 00 00 01 00 00 ; ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 11 00 ; ip4, scope 17, source 0 + 7f 03 00 ; 127.3.0.0/17 + HEX_ANSWER_END +ENTRY_END + +; recursion happens here. +; The upstream server RANGE starts responding at STEP 50. +STEP 50 TRAFFIC + +; The upstream server now responds for the nonsubnet response. +STEP 55 TRAFFIC + +STEP 60 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA DO NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +;www.example.com. IN A 10.20.30.44 +SECTION ADDITIONAL +; HEX_EDNSDATA_BEGIN +; ; client is 127.3.0.1 +; 00 08 ; OPC +; 00 07 ; option length +; 00 01 ; Family +; 11 00 ; source mask, scopemask +; 7f 03 00 ; address +; HEX_EDNSDATA_END +ENTRY_END + +STEP 70 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA DO NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +;www.example.com. IN A 10.20.30.44 +SECTION ADDITIONAL +; HEX_EDNSDATA_BEGIN +; ; client is 127.2.0.1 +; 00 08 ; OPC +; 00 07 ; option length +; 00 01 ; Family +; 11 00 ; source mask, scopemask +; 7f 02 00 ; address +; HEX_EDNSDATA_END +ENTRY_END + +STEP 80 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA DO NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +;www.example.com. IN A 10.20.30.44 +SECTION ADDITIONAL +; HEX_EDNSDATA_BEGIN +; ; client is 127.0.0.1 +; 00 08 ; OPC +; 00 07 ; option length +; 00 01 ; Family +; 11 00 ; source mask, scopemask +; 7f 00 00 ; address +; HEX_EDNSDATA_END +ENTRY_END + +SCENARIO_END diff --git a/unbound-1.16.2/testdata/subnet_noecs_refused.rpl b/unbound-1.16.2/testdata/subnet_noecs_refused.rpl new file mode 100644 index 0000000..39fbe85 --- /dev/null +++ b/unbound-1.16.2/testdata/subnet_noecs_refused.rpl @@ -0,0 +1,159 @@ +# config +server: + send-client-subnet: 1.2.3.4 + max-client-subnet-ipv4: 17 + module-config: "subnetcache iterator" + qname-minimisation: no + minimal-responses: yes + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test subnet with no edns subnet support but it is refused +; The query is sent to a server that does not reply with the edns-subnet +; option. The upstream server sends rcode refused. That results in a +; NULL return_msg. + +; 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 subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +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 subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. host.example.com. 4 86400 3600 86400 3600 +ENTRY_END + +; This matches the no EDNS subnet info queries that are made for the +; fallback without subnet. The answer is refused. +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +;www.example.com. IN A 10.20.30.40 +ENTRY_END + +; This matches the initial query with edns subnet in the query, +; the answer has no edns subnet in the reply. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +RANGE_END + +STEP 1 QUERY +;ENTRY_BEGIN +;REPLY RD DO +;SECTION QUESTION +;www.example.com. IN A +; but send this query with subnet scope zero in the query, because that +; makes the reply possibly get stored in the cache. +; +; query with subnet 0.0.0.0/0. +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 08 + + 00 08 00 04 ; OPC, optlen + 00 01 00 00 ; ip4, scope 0, source 0 + ;0.0.0.0/0 +HEX_ANSWER_END +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA DO SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +;www.example.com. IN A 10.20.30.40 +ENTRY_END +SCENARIO_END diff --git a/unbound-1.16.2/testdata/subnet_noecs_support.rpl b/unbound-1.16.2/testdata/subnet_noecs_support.rpl new file mode 100644 index 0000000..0c9826c --- /dev/null +++ b/unbound-1.16.2/testdata/subnet_noecs_support.rpl @@ -0,0 +1,127 @@ +# config +server: + send-client-subnet: 1.2.3.4 + max-client-subnet-ipv4: 17 + module-config: "subnetcache iterator" + qname-minimisation: no + minimal-responses: yes + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test subnet with no edns subnet support from the server +; The query is sent to a server that does not reply with the edns-subnet +; option. + +; 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 subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +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 subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. host.example.com. 4 86400 3600 86400 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA DO NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +SCENARIO_END diff --git a/unbound-1.16.2/testdata/subnet_prezero.rpl b/unbound-1.16.2/testdata/subnet_prezero.rpl new file mode 100644 index 0000000..22cdfff --- /dev/null +++ b/unbound-1.16.2/testdata/subnet_prezero.rpl @@ -0,0 +1,155 @@ +; subnet unit test +server: + trust-anchor-signaling: no + send-client-subnet: 1.2.3.4 + send-client-subnet: 1.2.3.5 + target-fetch-policy: "0 0 0 0 0" + module-config: "subnetcache validator iterator" + qname-minimisation: no + minimal-responses: no + +stub-zone: + name: "example.com" + stub-addr: 1.2.3.4 +CONFIG_END + +SCENARIO_BEGIN Test subnetcache source prefix zero from client. +; In RFC7871 section-7.1.2 (para. 2). +; It says that the recursor must send no EDNS subnet or its own address +; in the EDNS subnet to the upstream server. And use that answer for the +; source prefix length zero query. That type of query is for privacy. +; The authority server is then going to use the resolver's IP, if any, to +; tailor the answer to the query source address. + +; ns.example.com +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 + +; reply with 0.0.0.0/0 in reply +; For the test the answers for 0.0.0.0/0 queries are SERVFAIL, the normal +; answers are NOERROR. +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id +REPLY QR AA DO SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME star.c10r.example.com. +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 00 04 ; OPCODE=subnet, optlen + 00 01 00 00 ; ip4, scope 0, source 0 + ; 0.0.0.0/0 +HEX_EDNSDATA_END +ENTRY_END + +; reply without subnet +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME star.c10r.example.com. +ENTRY_END + +; delegation answer for c10r.example.com, with subnet /0 +ENTRY_BEGIN +MATCH opcode subdomain ednsdata +ADJUST copy_id copy_query +REPLY QR DO SERVFAIL +SECTION QUESTION +c10r.example.com. IN NS +SECTION AUTHORITY +c10r.example.com. IN NS ns.c10r.example.com. +SECTION ADDITIONAL +ns.c10r.example.com. IN A 1.2.3.5 +HEX_EDNSDATA_BEGIN + 00 08 00 04 ; OPCODE=subnet, optlen + 00 01 00 00 ; ip4, scope 0, source 0 + ; 0.0.0.0/0 +HEX_EDNSDATA_END +ENTRY_END + +; delegation answer for c10r.example.com, without subnet +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR DO NOERROR +SECTION QUESTION +c10r.example.com. IN NS +SECTION AUTHORITY +c10r.example.com. IN NS ns.c10r.example.com. +SECTION ADDITIONAL +ns.c10r.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.c10r.example.com +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 + +; reply with 0.0.0.0/0 in reply +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id +REPLY QR AA DO SERVFAIL +SECTION QUESTION +star.c10r.example.com. IN A +SECTION ANSWER +star.c10r.example.com. IN A 1.2.3.6 +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 00 04 ; OPCODE=subnet, optlen + 00 01 00 00 ; ip4, scope 0, source 0 + ; 0.0.0.0/0 +HEX_EDNSDATA_END +ENTRY_END + +; reply without subnet +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +star.c10r.example.com. IN A +SECTION ANSWER +star.c10r.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ask for www.example.com +; server answers with CNAME to a delegation, that then +; returns a /24 answer. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 00 04 ; OPCODE=subnet, optlen + 00 01 00 00 ; ip4, scope 0, source 0 + ; 0.0.0.0/0 +HEX_EDNSDATA_END +ENTRY_END + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA DO NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME star.c10r.example.com. +star.c10r.example.com. IN A 1.2.3.6 +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 00 04 ; OPCODE=subnet, optlen + 00 01 00 00 ; ip4, scope 0, source 0 + ; 0.0.0.0/0 +HEX_EDNSDATA_END +ENTRY_END +SCENARIO_END diff --git a/unbound-1.16.2/testdata/subnet_scopezero.rpl b/unbound-1.16.2/testdata/subnet_scopezero.rpl new file mode 100644 index 0000000..e006514 --- /dev/null +++ b/unbound-1.16.2/testdata/subnet_scopezero.rpl @@ -0,0 +1,439 @@ +; scope of 0, if the query also had scope of 0, do not answer this +; to everyone, but only for scope 0 queries. Otherwise can answer cached. + +server: + target-fetch-policy: "0 0 0 0 0" + send-client-subnet: 1.2.3.4 + module-config: "subnetcache validator iterator" + verbosity: 4 + qname-minimisation: no + +stub-zone: + name: "." + stub-addr: 193.0.14.129 + +stub-zone: + name: "example.com" + stub-addr: 1.2.3.4 +CONFIG_END + +SCENARIO_BEGIN Test subnet cache with scope zero queries and responses. + +; the upstream server. +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 +RANGE_END + +RANGE_BEGIN 0 11 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +;copy_ednsdata_assume_clientsubnet +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 00 00 ; address +HEX_EDNSDATA_END +ENTRY_END +RANGE_END + +RANGE_BEGIN 20 31 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +;copy_ednsdata_assume_clientsubnet +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.41 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 01 00 ; address +HEX_EDNSDATA_END +ENTRY_END +RANGE_END + +RANGE_BEGIN 40 51 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +;copy_ednsdata_assume_clientsubnet +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.42 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 ; OPC + 00 04 ; option length + 00 01 ; Family + 00 00 ; source mask, scopemask + ; address 0.0.0.0/0 scope 0 +HEX_EDNSDATA_END +ENTRY_END +RANGE_END + +RANGE_BEGIN 120 131 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +;copy_ednsdata_assume_clientsubnet +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.43 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 00 ; source mask, scopemask + 7f 02 00 ; address 127.2.0.0/24 scope 0 +HEX_EDNSDATA_END +ENTRY_END +RANGE_END + +; query for 127.0.0.0/24 +STEP 1 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 00 00 ;127.0.0.0/24 +HEX_ANSWER_END +ENTRY_END + +; answer is 10.20.30.40 for 127.0.0.0/24 scope 17 +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 00 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +; query for 127.1.0.0/24 +STEP 20 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 01 00 ;127.1.0.0/24 +HEX_ANSWER_END +ENTRY_END + +; answer is 10.20.30.41 for 127.1.0.0/24 scope 17 +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.41 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.1.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 01 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +; query for 0.0.0.0/0 +STEP 40 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 08 + + 00 08 00 04 ; OPC, optlen + 00 01 00 00 ; ip4, scope 0, source 0 + ;0.0.0.0/0 +HEX_ANSWER_END +ENTRY_END + +; answer is 10.20.30.42 for 0.0.0.0/0 scope 0 +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.42 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 ; OPC + 00 04 ; option length + 00 01 ; Family + 00 00 ; source mask, scopemask + ; address +HEX_EDNSDATA_END +ENTRY_END + +; query for 127.0.0.0/24, again, it should be in cache. +; and not from the scope 0 answer. +STEP 60 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 00 00 ;127.0.0.0/24 +HEX_ANSWER_END +ENTRY_END + +; answer should be 10.20.30.40 for 127.0.0.0/24 scope 17 +STEP 70 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 00 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +; query for 127.1.0.0/24, again, it should be in cache. +STEP 80 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 01 00 ;127.1.0.0/24 +HEX_ANSWER_END +ENTRY_END + +; answer should be 10.20.30.41 for 127.1.0.0/24 scope 17 +STEP 90 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.41 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.1.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 01 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +; query for 0.0.0.0/0, again. +STEP 100 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 08 + + 00 08 00 04 ; OPC, optlen + 00 01 00 00 ; ip4, scope 0, source 0 + ;0.0.0.0/0 +HEX_ANSWER_END +ENTRY_END + +; answer should be 10.20.30.42 for 0.0.0.0/0 scope 0 +STEP 110 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.42 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 ; OPC + 00 04 ; option length + 00 01 ; Family + 00 00 ; source mask, scopemask + ; address +HEX_EDNSDATA_END +ENTRY_END + +; now a query for a /24 that gets an answer for a /0. +STEP 120 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 02 00 ;127.2.0.0/24 +HEX_ANSWER_END +ENTRY_END + +; answer should be 10.20.30.43 for 127.2.0.0/24 scope 0 +STEP 130 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.43 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.2.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 00 ; source mask, scopemask + 7f 02 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +; the scope 0 answer is now used to answer queries from +; query for 127.0.0.0/24 +STEP 140 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 00 00 ;127.0.0.0/24 +HEX_ANSWER_END +ENTRY_END + +STEP 150 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.43 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 00 ; source mask, scopemask + 7f 00 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +SCENARIO_END diff --git a/unbound-1.16.2/testdata/subnet_scopezero_noedns.rpl b/unbound-1.16.2/testdata/subnet_scopezero_noedns.rpl new file mode 100644 index 0000000..25df0dd --- /dev/null +++ b/unbound-1.16.2/testdata/subnet_scopezero_noedns.rpl @@ -0,0 +1,441 @@ +; scope of 0, if the query also had scope of 0, do not answer this +; to everyone, but only for scope 0 queries. Otherwise can answer cached. + +server: + target-fetch-policy: "0 0 0 0 0" + send-client-subnet: 1.2.3.4 + module-config: "subnetcache validator iterator" + verbosity: 4 + qname-minimisation: no + +stub-zone: + name: "." + stub-addr: 193.0.14.129 + +stub-zone: + name: "example.com" + stub-addr: 1.2.3.4 +CONFIG_END + +SCENARIO_BEGIN Test subnet cache with scope zero response without EDNS. + +; the upstream server. +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 +RANGE_END + +RANGE_BEGIN 0 11 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +;copy_ednsdata_assume_clientsubnet +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 00 00 ; address +HEX_EDNSDATA_END +ENTRY_END +RANGE_END + +RANGE_BEGIN 20 31 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +;copy_ednsdata_assume_clientsubnet +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.41 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 01 00 ; address +HEX_EDNSDATA_END +ENTRY_END +RANGE_END + +RANGE_BEGIN 40 51 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +;copy_ednsdata_assume_clientsubnet +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.42 +SECTION AUTHORITY +SECTION ADDITIONAL +;no EDNS in this answer. Tests if the back_parsed callback +;is called to process the lack of edns contents. +;HEX_EDNSDATA_BEGIN + ;00 08 ; OPC + ;00 04 ; option length + ;00 01 ; Family + ;00 00 ; source mask, scopemask + ; ; address 0.0.0.0/0 scope 0 +;HEX_EDNSDATA_END +ENTRY_END +RANGE_END + +RANGE_BEGIN 120 131 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +;copy_ednsdata_assume_clientsubnet +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.43 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 00 ; source mask, scopemask + 7f 02 00 ; address 127.2.0.0/24 scope 0 +HEX_EDNSDATA_END +ENTRY_END +RANGE_END + +; query for 127.0.0.0/24 +STEP 1 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 00 00 ;127.0.0.0/24 +HEX_ANSWER_END +ENTRY_END + +; answer is 10.20.30.40 for 127.0.0.0/24 scope 17 +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 00 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +; query for 127.1.0.0/24 +STEP 20 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 01 00 ;127.1.0.0/24 +HEX_ANSWER_END +ENTRY_END + +; answer is 10.20.30.41 for 127.1.0.0/24 scope 17 +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.41 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.1.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 01 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +; query for 0.0.0.0/0 +STEP 40 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 08 + + 00 08 00 04 ; OPC, optlen + 00 01 00 00 ; ip4, scope 0, source 0 + ;0.0.0.0/0 +HEX_ANSWER_END +ENTRY_END + +; answer is 10.20.30.42 for 0.0.0.0/0 scope 0 +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.42 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 ; OPC + 00 04 ; option length + 00 01 ; Family + 00 00 ; source mask, scopemask + ; address +HEX_EDNSDATA_END +ENTRY_END + +; query for 127.0.0.0/24, again, it should be in cache. +; and not from the scope 0 answer. +STEP 60 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 00 00 ;127.0.0.0/24 +HEX_ANSWER_END +ENTRY_END + +; answer should be 10.20.30.40 for 127.0.0.0/24 scope 17 +STEP 70 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 00 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +; query for 127.1.0.0/24, again, it should be in cache. +STEP 80 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 01 00 ;127.1.0.0/24 +HEX_ANSWER_END +ENTRY_END + +; answer should be 10.20.30.41 for 127.1.0.0/24 scope 17 +STEP 90 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.41 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.1.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 11 ; source mask, scopemask + 7f 01 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +; query for 0.0.0.0/0, again. +STEP 100 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 08 + + 00 08 00 04 ; OPC, optlen + 00 01 00 00 ; ip4, scope 0, source 0 + ;0.0.0.0/0 +HEX_ANSWER_END +ENTRY_END + +; answer should be 10.20.30.42 for 0.0.0.0/0 scope 0 +STEP 110 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.42 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 ; OPC + 00 04 ; option length + 00 01 ; Family + 00 00 ; source mask, scopemask + ; address +HEX_EDNSDATA_END +ENTRY_END + +; now a query for a /24 that gets an answer for a /0. +STEP 120 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 02 00 ;127.2.0.0/24 +HEX_ANSWER_END +ENTRY_END + +; answer should be 10.20.30.43 for 127.2.0.0/24 scope 0 +STEP 130 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.43 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.2.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 00 ; source mask, scopemask + 7f 02 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +; the scope 0 answer is now used to answer queries from +; query for 127.0.0.0/24 +STEP 140 QUERY +ENTRY_BEGIN +HEX_ANSWER_BEGIN + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 18 00 ; ip4, scope 24, source 0 + 7f 00 00 ;127.0.0.0/24 +HEX_ANSWER_END +ENTRY_END + +STEP 150 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ednsdata +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.43 +SECTION AUTHORITY +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 00 ; source mask, scopemask + 7f 00 00 ; address +HEX_EDNSDATA_END +ENTRY_END + +SCENARIO_END