+24 October 2018: Ralph
+ - Add markdel function to ECS slabhash.
+ - Limit ECS scope returned to client to the scope used for caching.
+ - Make lint like previous #4154 fix.
+
22 October 2018: Wouter
- Fix #4192: unbound-control-setup generates keys not readable by
group.
struct addrtree *
addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *),
- size_t (*sizefunc)(void *), void *env, unsigned int max_node_count)
+ size_t (*sizefunc)(void *), void *env, uint32_t max_node_count)
{
struct addrtree *tree;
log_assert(delfunc != NULL);
struct addrnode *root;
/** Number of elements in the tree (not always equal to number of
* nodes) */
- unsigned int node_count;
+ uint32_t node_count;
/** Maximum number of allowed nodes, will be enforced by LRU list.
* Excluding the root node, 0 for unlimited */
- unsigned int max_node_count;
+ uint32_t max_node_count;
/** Size of tree in bytes */
size_t size_bytes;
/** Maximum prefix length we are willing to cache. */
*/
struct addrtree *
addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *),
- size_t (*sizefunc)(void *), void *env, unsigned int max_node_count);
+ size_t (*sizefunc)(void *), void *env, uint32_t max_node_count);
/**
* Free tree and all nodes below.
}
+void
+subnet_markdel(void* key)
+{
+ struct msgreply_entry *e = (struct msgreply_entry*)key;
+ e->key.qtype = 0;
+ e->key.qclass = 0;
+}
+
int
subnetmod_init(struct module_env *env, int id)
{
HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
msg_cache_sizefunc, query_info_compare, query_entry_delete,
subnet_data_delete, NULL);
+ slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel);
if(!sn_env->subnet_msg_cache) {
log_err("subnet: could not create cache");
free(sn_env);
c_out->subnet_source_mask = c_in->subnet_source_mask;
memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE);
c_out->subnet_scope_mask = s_in->subnet_scope_mask;
+ /* Limit scope returned to client to scope used for caching. */
+ if(c_out->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
+ if(c_out->subnet_scope_mask >
+ qstate->env->cfg->max_client_subnet_ipv4) {
+ c_out->subnet_scope_mask =
+ qstate->env->cfg->max_client_subnet_ipv4;
+ }
+ }
+ else if(c_out->subnet_scope_mask >
+ qstate->env->cfg->max_client_subnet_ipv6) {
+ c_out->subnet_scope_mask =
+ qstate->env->cfg->max_client_subnet_ipv6;
+ }
c_out->subnet_validdata = 1;
}
return module_finished;
int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
int id, void* cbargs);
+/** mark subnet msg to be deleted */
+void subnet_markdel(void* key);
+
#endif /* SUBNETMOD_H */
e->copy_query = 1;
} else if(str_keyword(&parse, "copy_ednsdata_assume_clientsubnet")) {
e->copy_ednsdata_assume_clientsubnet = 1;
+ } else if(str_keyword(&parse, "increment_ecs_scope")) {
+ e->increment_ecs_scope = 1;
} else if(str_keyword(&parse, "sleep=")) {
e->sleeptime = (unsigned int) strtol(parse, (char**)&parse, 10);
while(isspace((unsigned char)*parse))
e->copy_id = 0;
e->copy_query = 0;
e->copy_ednsdata_assume_clientsubnet = 0;
+ e->increment_ecs_scope = 0;
e->sleeptime = 0;
e->next = NULL;
return e;
if(walk_qlen >= 15 && walk_plen >= 15) {
walk_p[15] = walk_q[14];
}
+ if(match->increment_ecs_scope) {
+ walk_p[15]++;
+ }
}
if(match->sleeptime > 0) {
/** copy ednsdata to reply, assume it is clientsubnet and
* adjust scopemask to match sourcemask */
uint8_t copy_ednsdata_assume_clientsubnet;
+ /** increment the ECS scope copied from the sourcemask by one */
+ uint8_t increment_ecs_scope;
/** in seconds */
unsigned int sleeptime;
{
addrlen_t l;
time_t i;
- unsigned int count;
+ uint32_t count;
addrkey_t *k;
struct addrtree* t;
struct module_env env;
ns.example.com. IN A 1.2.3.4
ENTRY_END
+ ; client send /17, we return /18
+ ENTRY_BEGIN
+ MATCH opcode qtype qname ednsdata
+ ADJUST copy_id copy_ednsdata_assume_clientsubnet increment_ecs_scope
+ REPLY QR NOERROR
+ SECTION QUESTION
+ www.example.com. IN TXT
+ SECTION ANSWER
+ www.example.com. IN TXT "longer scope"
+ SECTION AUTHORITY
+ example.com. IN NS ns.example.com.
+ SECTION ADDITIONAL
+ HEX_EDNSDATA_BEGIN
+ ; client is 127.1.0.1
+ 00 08 ; OPC
+ 00 07 ; option length
+ 00 01 ; Family
+ 11 00 ; source mask, scopemask
+ 7f 01 00 ; address
+ HEX_EDNSDATA_END
+ ns.example.com. IN A 1.2.3.4
+ ENTRY_END
+
RANGE_END
STEP 1 QUERY
ns.example.com. IN A 1.2.3.4
ENTRY_END
+STEP 21 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 TXT? (DO)
+ 07 65 78 61 6d 70 6c 65
+ 03 63 6f 6d 00 00 10 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 01 00 ;127.1.0.0/17
+ HEX_ANSWER_END
+ENTRY_END
+
+
+
+; server returns /18, since we cache the result to max-client-subnet-ipv4 (/17),
+; the initial answer returned to the client should also be capped to /17.
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+ MATCH all ednsdata
+ REPLY QR RD RA NOERROR
+ SECTION QUESTION
+ www.example.com. IN TXT
+ SECTION ANSWER
+ www.example.com. IN TXT "longer scope"
+ SECTION AUTHORITY
+ example.com. IN NS ns.example.com.
+ SECTION ADDITIONAL
+ HEX_EDNSDATA_BEGIN
+ ; client is 127.1.0.1
+ 00 08 ; OPC
+ 00 07 ; option length
+ 00 01 ; Family
+ 11 11 ; source mask, scopemask
+ 7f 01 00 ; address
+ HEX_EDNSDATA_END
+ ns.example.com. IN A 1.2.3.4
+ENTRY_END
SCENARIO_END
{
if(fptr == NULL) return 1;
else if(fptr == &rrset_markdel) return 1;
+#ifdef CLIENT_SUBNET
+ else if(fptr == &subnet_markdel) return 1;
+#endif
return 0;
}