From: Ralph Dolmans Date: Mon, 10 Apr 2017 09:12:04 +0000 (+0000) Subject: - Remove ECS option after REFUSED answer X-Git-Tag: release-1.6.2rc1~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a5c7c469ee85c463294fad1430548461c2280073;p=thirdparty%2Funbound.git - Remove ECS option after REFUSED answer - Fix small memory leak in edns_opt_copy_alloc git-svn-id: file:///svn/unbound/trunk@4100 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 54f748e4f..40bf83ab9 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,8 +1,12 @@ -7 april 2017: George +10 April 2017: Ralph + - Remove ECS option after REFUSED answer + - Fix small memory leak in edns_opt_copy_alloc + +7 April 2017: George - Fix pythonmod for cb changes. - Some whitespace fixup. -7 april 2017: Ralph +7 April 2017: Ralph - Unlock view in respip unit test 6 April 2017: Ralph diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c index c29b7907e..b786c2869 100644 --- a/edns-subnet/subnetmod.c +++ b/edns-subnet/subnetmod.c @@ -227,6 +227,8 @@ subnetmod_init(struct module_env *env, int id) env, id); inplace_cb_register((void*)ecs_edns_back_parsed, inplace_cb_edns_back_parsed, NULL, env, id); + inplace_cb_register((void*)ecs_query_response, + inplace_cb_query_response, NULL, env, id); lock_rw_init(&sn_env->biglock); return 1; } @@ -588,6 +590,26 @@ subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs, #endif /* INET6 */ } +int +ecs_query_response(struct module_qstate* qstate, struct dns_msg* response, + int id, void* ATTR_UNUSED(cbargs)) +{ + struct subnet_qstate *sq; + + if(!response || !(sq=(struct subnet_qstate*)qstate->minfo[id])) + return 1; + + if(sq->subnet_sent && + FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_REFUSED) { + /* REFUSED reponse to ECS query, remove ECS option. */ + edns_opt_list_remove(&qstate->edns_opts_back_out, + qstate->env->cfg->client_subnet_opcode); + sq->subnet_sent = 0; + memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out)); + } + return 1; +} + int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* ATTR_UNUSED(cbargs)) diff --git a/edns-subnet/subnetmod.h b/edns-subnet/subnetmod.h index 58c83505a..f2baa466a 100644 --- a/edns-subnet/subnetmod.h +++ b/edns-subnet/subnetmod.h @@ -123,4 +123,8 @@ int ecs_whitelist_check(struct query_info* qinfo, uint16_t flags, * store. Called just after parsing EDNS data from server. */ int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs); +/** Remove ECS record from back_out when query resulted in REFUSED response. */ +int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response, + int id, void* cbargs); + #endif /* SUBNETMOD_H */ diff --git a/iterator/iterator.c b/iterator/iterator.c index 7e3c77f6d..43b3d30c3 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -2194,6 +2194,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, int dnsseclame = 0; enum response_type type; iq->num_current_queries--; + + if(!inplace_cb_query_response_call(qstate->env, qstate, iq->response)) + log_err("unable to call query_response callback"); + if(iq->response == NULL) { /* Don't increment qname when QNAME minimisation is enabled */ if(qstate->env->cfg->qname_minimisation) diff --git a/util/data/msgreply.c b/util/data/msgreply.c index 1ba34b639..2ce898d7f 100644 --- a/util/data/msgreply.c +++ b/util/data/msgreply.c @@ -1074,6 +1074,19 @@ int inplace_cb_edns_back_parsed_call(struct module_env* env, return 1; } +int inplace_cb_query_response_call(struct module_env* env, + struct module_qstate* qstate, struct dns_msg* response) { + struct inplace_cb* cb = + env->inplace_cb_lists[inplace_cb_query_response]; + for(; cb; cb=cb->next) { + fptr_ok(fptr_whitelist_inplace_cb_query_response( + (inplace_cb_query_response_func_type*)cb->cb)); + (void)(*(inplace_cb_query_response_func_type*)cb->cb)(qstate, + response, cb->id, cb->cb_arg); + } + return 1; +} + struct edns_option* edns_opt_copy_region(struct edns_option* list, struct regional* region) { @@ -1164,6 +1177,7 @@ struct edns_option* edns_opt_copy_alloc(struct edns_option* list) if(s->opt_data) { s->opt_data = memdup(s->opt_data, s->opt_len); if(!s->opt_data) { + free(s); edns_opt_list_free(result); return NULL; } diff --git a/util/data/msgreply.h b/util/data/msgreply.h index bccfd270c..acbdd3deb 100644 --- a/util/data/msgreply.h +++ b/util/data/msgreply.h @@ -50,14 +50,13 @@ struct iovec; struct regional; struct edns_data; struct edns_option; -struct inplace_cb_reply; -struct inplace_cb_query; -struct inplace_cb_edns_back_parsed; +struct inplace_cb; struct module_qstate; struct module_env; struct msg_parse; struct rrset_parse; struct local_rrset; +struct dns_msg; /** calculate the prefetch TTL as 90% of original. Calculation * without numerical overflow (uin32_t) */ @@ -625,8 +624,8 @@ int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo, /** * Call the registered functions in the inplace_cb_edns_back_parsed linked list. - * This function is going to get called after receiving a reply from a - * nameserver. + * This function is going to get called after parsing the EDNS data on the + * reply from a nameserver. * @param env: module environment. * @param qstate: module qstate. * @return false on failure (a callback function returned an error). @@ -634,6 +633,18 @@ int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo, int inplace_cb_edns_back_parsed_call(struct module_env* env, struct module_qstate* qstate); +/** + * Call the registered functions in the inplace_cb_query_reponse linked list. + * This function is going to get called after receiving a reply from a + * nameserver. + * @param env: module environment. + * @param qstate: module qstate. + * @param response: received response + * @return false on failure (a callback function returned an error). + */ +int inplace_cb_query_response_call(struct module_env* env, + struct module_qstate* qstate, struct dns_msg* response); + /** * Copy edns option list allocated to the new region */ diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index 1e03d0973..03244a123 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -518,3 +518,15 @@ int fptr_whitelist_inplace_cb_edns_back_parsed( #endif return 0; } + +int fptr_whitelist_inplace_cb_query_response( + inplace_cb_query_response_func_type* fptr) +{ +#ifdef CLIENT_SUBNET + if(fptr == &ecs_query_response) + return 1; +#else + (void)fptr; +#endif + return 0; +} diff --git a/util/fptr_wlist.h b/util/fptr_wlist.h index 3fe9a879a..653f8f0e7 100644 --- a/util/fptr_wlist.h +++ b/util/fptr_wlist.h @@ -359,6 +359,14 @@ int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_type* fptr); int fptr_whitelist_inplace_cb_edns_back_parsed( inplace_cb_edns_back_parsed_func_type* fptr); +/** + * Check function pointer whitelist for inplace_cb_query_response func values. + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_inplace_cb_query_response( + inplace_cb_query_response_func_type* fptr); + /** Due to module breakage by fptr wlist, these test app declarations * are presented here */ /** diff --git a/util/module.h b/util/module.h index f9360b53a..82b50ccd7 100644 --- a/util/module.h +++ b/util/module.h @@ -198,6 +198,9 @@ enum inplace_cb_list_type { /* Inplace callbacks for when a query is ready to be sent to the back.*/ inplace_cb_query, /* Inplace callback for when a reply is received from the back. */ + inplace_cb_query_response, + /* Inplace callback for when EDNS is parsed on a reply received from the + * back. */ inplace_cb_edns_back_parsed, /* Total number of types. Used for array initialization. * Should always be last. */ @@ -272,15 +275,28 @@ typedef int inplace_cb_query_func_type(struct query_info* qinfo, uint16_t flags, int id, void* callback); /** - * Inplace callback function called after receiving reply from back. + * Inplace callback function called after parsing edns on query reply. * Called as func(qstate, cb_args) * Where: * qstate: the query state + * id: module id * cb_args: argument passed when registering callback. */ typedef int inplace_cb_edns_back_parsed_func_type(struct module_qstate* qstate, int id, void* cb_args); +/** + * Inplace callback function called after parsing query response. + * Called as func(qstate, id, cb_args) + * Where: + * qstate: the query state + * response: query response + * id: module id + * cb_args: argument passed when registering callback. + */ +typedef int inplace_cb_query_response_func_type(struct module_qstate* qstate, + struct dns_msg* response, int id, void* cb_args); + /** * Module environment. * Services and data provided to the module.