]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Remove ECS option after REFUSED answer
authorRalph Dolmans <ralph@nlnetlabs.nl>
Mon, 10 Apr 2017 09:12:04 +0000 (09:12 +0000)
committerRalph Dolmans <ralph@nlnetlabs.nl>
Mon, 10 Apr 2017 09:12:04 +0000 (09:12 +0000)
- Fix small memory leak in edns_opt_copy_alloc

git-svn-id: file:///svn/unbound/trunk@4100 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
edns-subnet/subnetmod.c
edns-subnet/subnetmod.h
iterator/iterator.c
util/data/msgreply.c
util/data/msgreply.h
util/fptr_wlist.c
util/fptr_wlist.h
util/module.h

index 54f748e4fe365202e0d6f489b9364c95425f1e1e..40bf83ab90c9144159c6b1c031cdd09a03b1dae7 100644 (file)
@@ -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
index c29b7907ea79cdf580afdac2193483176dfe49d1..b786c2869b29f7fc0288310bf759a0df56bc5e4d 100644 (file)
@@ -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))
index 58c83505a7751f8887b68b91c4ec7ef7e5d25847..f2baa466ae61af4bceacdd04c3d8f8764a47aa4c 100644 (file)
@@ -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 */
index 7e3c77f6d7014b51474e3441a2c8bf9ae8401bfe..43b3d30c330bfd4e2fd768dca2f4933cdc79aad9 100644 (file)
@@ -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)
index 1ba34b639c425e98594fc95c86e9e8ce4502958c..2ce898d7f031467e4727cd14ed83b36c72cf0f8c 100644 (file)
@@ -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;
                        }
index bccfd270c8ea8496e37b6fd7e0e70666ad03fcf2..acbdd3deb61bd13fa9eb3a4156ce23ac0366a45d 100644 (file)
@@ -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
  */
index 1e03d0973a496bc31f022124c2995a86c66dc848..03244a123d69f086186840dffe37b18822434b17 100644 (file)
@@ -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;
+}
index 3fe9a879aba1d2f55f57e0da6125e920e8d25409..653f8f0e75d4f1aa9f7a04cfe67f8ab2ebf6e44c 100644 (file)
@@ -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 */
 /** 
index f9360b53a77a327d5a1e91c5af5b321b45a495c8..82b50ccd7d06dfb2711a2716ded7d5089b6a6433 100644 (file)
@@ -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.