]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- #4140: Expose repinfo (comm_reply) to the inplace_callbacks. This
authorGeorge Thessalonikefs <george@nlnetlabs.nl>
Wed, 22 Aug 2018 10:51:13 +0000 (10:51 +0000)
committerGeorge Thessalonikefs <george@nlnetlabs.nl>
Wed, 22 Aug 2018 10:51:13 +0000 (10:51 +0000)
  gives access to reply information for the client's communication
  point when the callback is called before the mesh state (modules).
  Changes to C and Python's inplace_callback signatures were also
  necessary.

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

15 files changed:
daemon/worker.c
doc/Changelog
libunbound/libworker.c
pythonmod/doc/examples/example6.rst
pythonmod/examples/inplace_callbacks.py
pythonmod/examples/resip.py
pythonmod/interface.i
pythonmod/pythonmod.h
services/authzone.c
services/authzone.h
services/localzone.c
services/mesh.c
util/data/msgreply.c
util/data/msgreply.h
util/module.h

index 84193bdabcc33d28d8c6c42a73b574f2a8462ee2..5ce5ef3a9b2340dd37e960f9e39bbc10b5ebc49a 100644 (file)
@@ -511,7 +511,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
                        edns->ext_rcode = 0;
                        edns->bits &= EDNS_DO;
                        if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL,
-                               msg->rep, LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
+                               msg->rep, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
                                        return 0;
                        error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, 
                                &msg->qinfo, id, flags, edns);
@@ -542,7 +542,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
        edns->ext_rcode = 0;
        edns->bits &= EDNS_DO;
        if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, msg->rep,
-               (int)(flags&LDNS_RCODE_MASK), edns, worker->scratchpad))
+               (int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad))
                        return 0;
        msg->rep->flags |= BIT_QR|BIT_RA;
        if(!apply_edns_options(edns, &edns_bak, worker->env.cfg,
@@ -551,7 +551,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
                repinfo->c->buffer, 0, 1, worker->scratchpad,
                udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
                if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
-                       LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
+                       LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
                                edns->opt_list = NULL;
                error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, 
                        &msg->qinfo, id, flags, edns);
@@ -673,7 +673,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
                edns->ext_rcode = 0;
                edns->bits &= EDNS_DO;
                if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep,
-                       LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
+                       LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
                        goto bail_out;
                error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, 
                        qinfo, id, flags, edns);
@@ -707,7 +707,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
        edns->ext_rcode = 0;
        edns->bits &= EDNS_DO;
        if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, rep,
-               (int)(flags&LDNS_RCODE_MASK), edns, worker->scratchpad))
+               (int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad))
                goto bail_out;
        *alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
        if(worker->daemon->use_response_ip && !partial_rep &&
@@ -741,7 +741,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
                repinfo->c->buffer, timenow, 1, worker->scratchpad,
                udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
                if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
-                       LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
+                       LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
                                edns->opt_list = NULL;
                error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, 
                        qinfo, id, flags, edns);
@@ -788,10 +788,11 @@ reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
  * @param num: number of strings in array.
  * @param edns: edns reply information.
  * @param worker: worker with scratch region.
+ * @param repinfo: reply information for a communication point.
  */
 static void
 chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
-       struct worker* worker)
+       struct worker* worker, struct comm_reply* repinfo)
 {
        int i;
        unsigned int rd = LDNS_RD_WIRE(sldns_buffer_begin(pkt));
@@ -824,7 +825,7 @@ chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
        edns->udp_size = EDNS_ADVERTISED_SIZE;
        edns->bits &= EDNS_DO;
        if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL,
-               LDNS_RCODE_NOERROR, edns, worker->scratchpad))
+               LDNS_RCODE_NOERROR, edns, repinfo, worker->scratchpad))
                        edns->opt_list = NULL;
        if(sldns_buffer_capacity(pkt) >=
                sldns_buffer_limit(pkt)+calc_edns_field_size(edns))
@@ -834,9 +835,9 @@ chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
 /** Reply with one string */
 static void
 chaos_replyonestr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
-       struct worker* worker)
+       struct worker* worker, struct comm_reply* repinfo)
 {
-       chaos_replystr(pkt, (char**)&str, 1, edns, worker);
+       chaos_replystr(pkt, (char**)&str, 1, edns, worker, repinfo);
 }
 
 /**
@@ -844,9 +845,11 @@ chaos_replyonestr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
  * @param pkt: buffer
  * @param edns: edns reply information.
  * @param w: worker with scratch region.
+ * @param repinfo: reply information for a communication point.
  */
 static void
-chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w)
+chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w,
+       struct comm_reply* repinfo)
 {
 #define TA_RESPONSE_MAX_TXT 16 /* max number of TXT records */
 #define TA_RESPONSE_MAX_TAGS 32 /* max number of tags printed per zone */
@@ -857,7 +860,7 @@ chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w)
 
        if(!w->env.need_to_validate) {
                /* no validator module, reply no trustanchors */
-               chaos_replystr(pkt, NULL, 0, edns, w);
+               chaos_replystr(pkt, NULL, 0, edns, w, repinfo);
                return;
        }
 
@@ -891,7 +894,7 @@ chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w)
        }
        lock_basic_unlock(&w->env.anchors->lock);
 
-       chaos_replystr(pkt, str_array, num, edns, w);
+       chaos_replystr(pkt, str_array, num, edns, w, repinfo);
        regional_free_all(w->scratchpad);
 }
 
@@ -900,12 +903,13 @@ chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w)
  * @param w: worker
  * @param qinfo: query info. Pointer into packet buffer.
  * @param edns: edns info from query.
+ * @param repinfo: reply information for a communication point.
  * @param pkt: packet buffer.
  * @return: true if a reply is to be sent.
  */
 static int
-answer_chaos(struct worker* w, struct query_info* qinfo, 
-       struct edns_data* edns, sldns_buffer* pkt)
+answer_chaos(struct worker* w, struct query_info* qinfo,
+       struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* pkt)
 {
        struct config_file* cfg = w->env.cfg;
        if(qinfo->qtype != LDNS_RR_TYPE_ANY && qinfo->qtype != LDNS_RR_TYPE_TXT)
@@ -921,13 +925,13 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
                        char buf[MAXHOSTNAMELEN+1];
                        if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
                                buf[MAXHOSTNAMELEN] = 0;
-                               chaos_replyonestr(pkt, buf, edns, w);
+                               chaos_replyonestr(pkt, buf, edns, w, repinfo);
                        } else  {
                                log_err("gethostname: %s", strerror(errno));
-                               chaos_replyonestr(pkt, "no hostname", edns, w);
+                               chaos_replyonestr(pkt, "no hostname", edns, w, repinfo);
                        }
                }
-               else    chaos_replyonestr(pkt, cfg->identity, edns, w);
+               else    chaos_replyonestr(pkt, cfg->identity, edns, w, repinfo);
                return 1;
        }
        if(query_dname_compare(qinfo->qname, 
@@ -938,8 +942,8 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
                if(cfg->hide_version) 
                        return 0;
                if(cfg->version==NULL || cfg->version[0]==0)
-                       chaos_replyonestr(pkt, PACKAGE_STRING, edns, w);
-               else    chaos_replyonestr(pkt, cfg->version, edns, w);
+                       chaos_replyonestr(pkt, PACKAGE_STRING, edns, w, repinfo);
+               else    chaos_replyonestr(pkt, cfg->version, edns, w, repinfo);
                return 1;
        }
        if(query_dname_compare(qinfo->qname,
@@ -947,7 +951,7 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
        {
                if(cfg->hide_trustanchor)
                        return 0;
-               chaos_trustanchor(pkt, edns, w);
+               chaos_trustanchor(pkt, edns, w, repinfo);
                return 1;
        }
 
@@ -1330,7 +1334,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
        if(c->type != comm_udp)
                edns.udp_size = 65535; /* max size for TCP replies */
        if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
-               &edns, c->buffer)) {
+               &edns, repinfo, c->buffer)) {
                server_stats_insrcode(&worker->stats, c->buffer);
                regional_free_all(worker->scratchpad);
                goto send_reply;
@@ -1357,7 +1361,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
        }
        if(worker->env.auth_zones &&
                auth_zones_answer(worker->env.auth_zones, &worker->env,
-               &qinfo, &edns, c->buffer, worker->scratchpad)) {
+               &qinfo, &edns, repinfo, c->buffer, worker->scratchpad)) {
                regional_free_all(worker->scratchpad);
                if(sldns_buffer_limit(c->buffer) == 0) {
                        comm_point_drop_reply(repinfo);
index a98ce05b58c3e252cad547f6572d69f73bc44747..8d6ca34b44999caef0e4c3851147e8eb91b298d5 100644 (file)
@@ -1,3 +1,10 @@
+22 August 2018: George
+       - #4140: Expose repinfo (comm_reply) to the inplace_callbacks. This
+         gives access to reply information for the client's communication
+         point when the callback is called before the mesh state (modules).
+         Changes to C and Python's inplace_callback signatures were also
+         necessary.
+
 21 August 2018: Wouter
        - log-local-actions: yes option for unbound.conf that logs all the
          local zone actions, a patch from Saksham Manchanda (Secure64).
index d984b3f39839a1562f98f1f85ef67f1c8d8e5795..05006a0ec44c0cbf897215baab1e70972e0a5ca0 100644 (file)
@@ -610,7 +610,7 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
                return UB_NOERROR;
        }
        if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones,
-               w->env, &qinfo, &edns, w->back->udp_buff, w->env->scratch)) {
+               w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
                regional_free_all(w->env->scratch);
                libworker_fillup_fg(q, LDNS_RCODE_NOERROR, 
                        w->back->udp_buff, sec_status_insecure, NULL, 0);
@@ -689,7 +689,7 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
                return UB_NOERROR;
        }
        if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones,
-               w->env, &qinfo, &edns, w->back->udp_buff, w->env->scratch)) {
+               w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
                regional_free_all(w->env->scratch);
                free(qinfo.qname);
                libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
@@ -827,7 +827,7 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
                return;
        }
        if(w->ctx->env->auth_zones && auth_zones_answer(w->ctx->env->auth_zones,
-               w->env, &qinfo, &edns, w->back->udp_buff, w->env->scratch)) {
+               w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
                regional_free_all(w->env->scratch);
                q->msg_security = sec_status_insecure;
                add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0);
index eb3254022946988d8d094a6eb7ef540c019d52bc..d294fb8be618ef747c5e8d70acc665805844ab1d 100644 (file)
@@ -40,9 +40,12 @@ The callback function's prototype is the following:
 
 .. code-block:: python
 
-    def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
-        """Function that will be registered as an inplace callback function.
+    def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
+                               region, **kwargs):
+        """
+        Function that will be registered as an inplace callback function.
         It will be called when answering with a resolved query.
+
         :param qinfo: query_info struct;
         :param qstate: module qstate. It contains the available opt_lists; It
                        SHOULD NOT be altered;
@@ -54,7 +57,13 @@ The callback function's prototype is the following:
                              reply. It can be populated with EDNS options;
         :param region: region to allocate temporary data. Needs to be used when we
                        want to append a new option to opt_list_out.
+        :param **kwargs: Dictionary that may contain parameters added in a future
+                         release. Current parameters:
+            ``repinfo``: Reply information for a communication point (comm_reply).
+                         It is None when the callback happens in the mesh states.
+
         :return: True on success, False on failure.
+
         """
 
 .. note:: The function's name is irrelevant.
@@ -76,9 +85,12 @@ The callback function's prototype is the following:
 
 .. code-block:: python
 
-    def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
-        """Function that will be registered as an inplace callback function.
+    def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
+                               region, **kwargs):
+        """
+        Function that will be registered as an inplace callback function.
         It will be called when answering from the cache.
+
         :param qinfo: query_info struct;
         :param qstate: module qstate. None;
         :param rep: reply_info struct;
@@ -90,7 +102,17 @@ The callback function's prototype is the following:
                              reply. It can be populated with EDNS options;
         :param region: region to allocate temporary data. Needs to be used when we
                        want to append a new option to opt_list_out.
+        :param **kwargs: Dictionary that may contain parameters added in a future
+                         release. Current parameters:
+            ``repinfo``: Reply information for a communication point (comm_reply).
+                         It is None when the callback happens in the mesh
+                         states(modules).
+
         :return: True on success, False on failure.
+
+        For demonstration purposes we want to see if EDNS option 65002 is present
+        and reply with a new value.
+
         """
 
 .. note:: The function's name is irrelevant.
@@ -112,9 +134,12 @@ The callback function's prototype is the following:
 
 .. code-block:: python
 
-    def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
-        """Function that will be registered as an inplace callback function.
+    def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
+                               region, **kwargs):
+        """
+        Function that will be registered as an inplace callback function.
         It will be called when answering from local data.
+
         :param qinfo: query_info struct;
         :param qstate: module qstate. None;
         :param rep: reply_info struct;
@@ -126,7 +151,14 @@ The callback function's prototype is the following:
                              reply. It can be populated with EDNS options;
         :param region: region to allocate temporary data. Needs to be used when we
                        want to append a new option to opt_list_out.
+        :param **kwargs: Dictionary that may contain parameters added in a future
+                         release. Current parameters:
+            ``repinfo``: Reply information for a communication point (comm_reply).
+                         It is None when the callback happens in the mesh
+                         states(modules).
+
         :return: True on success, False on failure.
+
         """
 
 .. note:: The function's name is irrelevant.
@@ -148,9 +180,12 @@ The callback function's prototype is the following:
 
 .. code-block:: python
 
-    def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
-        """Function that will be registered as an inplace callback function.
+    def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
+                                  region, **kwargs):
+        """
+        Function that will be registered as an inplace callback function.
         It will be called when answering with SERVFAIL.
+
         :param qinfo: query_info struct;
         :param qstate: module qstate. If not None the relevant opt_lists are
                        available here;
@@ -163,7 +198,17 @@ The callback function's prototype is the following:
                              reply. It can be populated with EDNS options;
         :param region: region to allocate temporary data. Needs to be used when we
                        want to append a new option to opt_list_out.
+        :param **kwargs: Dictionary that may contain parameters added in a future
+                         release. Current parameters:
+            ``repinfo``: Reply information for a communication point (comm_reply).
+                         It is None when the callback happens in the mesh
+                         states(modules).
+
         :return: True on success, False on failure.
+
+        For demonstration purposes we want to reply with an empty EDNS code '65003'
+        and log the IP address(es) of the client(s).
+
         """
 
 .. note:: The function's name is irrelevant.
index 02ee56e36e21ebf7d4737cb832f5ec370771692a..e47fc8292be27e13ba41aecc2938f9d8bf473a98 100644 (file)
@@ -6,18 +6,18 @@
  Copyright (c) 2016, NLnet Labs.
 
  This software is open source.
+
  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:
+
     * Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.
+
     * Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
+
     * Neither the name of the organization nor the names of its
       contributors may be used to endorse or promote products derived from this
       software without specific prior written permission.
@@ -43,6 +43,8 @@
 #       This query returns SERVFAIL as the txt record of bogus.nlnetlabs.nl is
 #       intentionally bogus. The reply will contain an empty EDNS option
 #       with option code 65003.
+#       Unbound will also log the source address(es) of the client(s) that made
+#       the request.
 #       (unbound needs to be validating for this example to work)
 
 # Useful functions:
 
 
 def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
-                           region):
-    """Function that will be registered as an inplace callback function.
+                           region, **kwargs):
+    """
+    Function that will be registered as an inplace callback function.
     It will be called when answering with a resolved query.
+
     :param qinfo: query_info struct;
     :param qstate: module qstate. It contains the available opt_lists; It
                    SHOULD NOT be altered;
@@ -84,16 +88,25 @@ def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
                          reply. It can be populated with EDNS options;
     :param region: region to allocate temporary data. Needs to be used when we
                    want to append a new option to opt_list_out.
+    :param **kwargs: Dictionary that may contain parameters added in a future
+                     release. Current parameters:
+        ``repinfo``: Reply information for a communication point (comm_reply).
+                     It is None when the callback happens in the mesh
+                     states(modules).
+
     :return: True on success, False on failure.
+
     """
     log_info("python: called back while replying.")
     return True
 
 
 def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
-                           region):
-    """Function that will be registered as an inplace callback function.
+                           region, **kwargs):
+    """
+    Function that will be registered as an inplace callback function.
     It will be called when answering from the cache.
+
     :param qinfo: query_info struct;
     :param qstate: module qstate. None;
     :param rep: reply_info struct;
@@ -105,10 +118,17 @@ def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
                          reply. It can be populated with EDNS options;
     :param region: region to allocate temporary data. Needs to be used when we
                    want to append a new option to opt_list_out.
+    :param **kwargs: Dictionary that may contain parameters added in a future
+                     release. Current parameters:
+        ``repinfo``: Reply information for a communication point (comm_reply).
+                     It is None when the callback happens in the mesh
+                     states(modules).
+
     :return: True on success, False on failure.
 
     For demonstration purposes we want to see if EDNS option 65002 is present
     and reply with a new value.
+
     """
     log_info("python: called back while answering from cache.")
     # Inspect the incoming EDNS options.
@@ -134,9 +154,11 @@ def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
 
 
 def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
-                           region):
-    """Function that will be registered as an inplace callback function.
+                           region, **kwargs):
+    """
+    Function that will be registered as an inplace callback function.
     It will be called when answering from local data.
+
     :param qinfo: query_info struct;
     :param qstate: module qstate. None;
     :param rep: reply_info struct;
@@ -148,7 +170,14 @@ def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
                          reply. It can be populated with EDNS options;
     :param region: region to allocate temporary data. Needs to be used when we
                    want to append a new option to opt_list_out.
+    :param **kwargs: Dictionary that may contain parameters added in a future
+                     release. Current parameters:
+        ``repinfo``: Reply information for a communication point (comm_reply).
+                     It is None when the callback happens in the mesh
+                     states(modules).
+
     :return: True on success, False on failure.
+
     """
     log_info("python: called back while replying with local data or chaos"
              " reply.")
@@ -156,9 +185,11 @@ def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
 
 
 def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
-                              region):
-    """Function that will be registered as an inplace callback function.
+                              region, **kwargs):
+    """
+    Function that will be registered as an inplace callback function.
     It will be called when answering with SERVFAIL.
+
     :param qinfo: query_info struct;
     :param qstate: module qstate. If not None the relevant opt_lists are
                    available here;
@@ -171,23 +202,62 @@ def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
                          reply. It can be populated with EDNS options;
     :param region: region to allocate temporary data. Needs to be used when we
                    want to append a new option to opt_list_out.
+    :param **kwargs: Dictionary that may contain parameters added in a future
+                     release. Current parameters:
+        ``repinfo``: Reply information for a communication point (comm_reply).
+                     It is None when the callback happens in the mesh
+                     states(modules).
+
     :return: True on success, False on failure.
 
-    For demonstration purposes we want to reply with an empty EDNS code '65003'.
+    For demonstration purposes we want to reply with an empty EDNS code '65003'
+    and log the IP address(es) of the client(s).
+
     """
     log_info("python: called back while servfail.")
+    # Append the example ENDS option
     b = bytearray.fromhex("")
     edns_opt_list_append(opt_list_out, 65003, b, region)
+
+    # Log the client(s) IP address(es)
+    comm_reply = kwargs['repinfo']
+    if comm_reply:
+        # If it is not None this callback was called before the query reached
+        # the mesh states(modules). There is only one client associated with
+        # this query.
+        addr = comm_reply.addr
+        port = comm_reply.port
+        addr_family = comm_reply.family
+        log_info("python: Client IP: {}({}), port: {}"
+                 "".format(addr, addr_family, port))
+    else:
+        # If it is not None this callback was called while the query is in the
+        # mesh states(modules). In this case they may be multiple clients
+        # waiting for this query.
+        # The following code is the same as with the resip.py example.
+        rl = qstate.mesh_info.reply_list
+        while (rl):
+            if rl.query_reply:
+                q = rl.query_reply
+                log_info("python: Client IP: {}({}), port: {}"
+                         "".format(q.addr, q.family, q.port))
+            rl = rl.next
+
+
     return True
 
 
 def init_standard(id, env):
-    """New version of the init function.
+    """
+    New version of the init function.
+
     The function's signature is the same as the C counterpart and allows for
     extra functionality during init.
+
     ..note:: This function is preferred by unbound over the old init function.
     ..note:: The previously accessible configuration options can now be found in
              env.cgf.
+
     """
     log_info("python: inited script {}".format(env.cfg.python_script))
 
@@ -215,11 +285,14 @@ def init_standard(id, env):
 
 
 def init(id, cfg):
-    """Previous version init function.
+    """
+    Previous version of the init function.
+
     ..note:: This function is still supported for backwards compatibility when
              the init_standard function is missing. When init_standard is
              present this function SHOULD be omitted to avoid confusion to the
              reader.
+
     """
     return True
 
index 6bcac7252cd296889bd6860b7bcfcbd4e4d4410b..4a9f24fc6448087e1bf8c9dc242cd762a89f34fa 100644 (file)
@@ -47,7 +47,7 @@ def deinit(id): return True
 def inform_super(id, qstate, superqstate, qdata): return True
 
 def operate(id, event, qstate, qdata):
-    print "Operate", event,"state:",qstate
+    print("Operate {} state: {}".format(event, qstate))
 
     # Please note that if this module blocks, by moving to the validator
     # to validate or iterator to lookup or spawn a subquery to look up,
@@ -61,14 +61,14 @@ def operate(id, event, qstate, qdata):
             msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA)
             #append RR
             if (qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY):
-               rl = qstate.mesh_info.reply_list
-               while (rl):
-                   if rl.query_reply:
-                      q = rl.query_reply
-                     # The TTL of 0 is mandatory, otherwise it ends up in
-                     # the cache, and is returned to other IP addresses.
-                      msg.answer.append("%s 0 IN TXT \"%s %d (%s)\"" % (qstate.qinfo.qname_str, q.addr,q.port,q.family))
-                   rl = rl.next
+                rl = qstate.mesh_info.reply_list
+                while (rl):
+                    if rl.query_reply:
+                        q = rl.query_reply
+                        # The TTL of 0 is mandatory, otherwise it ends up in
+                        # the cache, and is returned to other IP addresses.
+                        msg.answer.append("%s 0 IN TXT \"%s %d (%s)\"" % (qstate.qinfo.qname_str, q.addr,q.port,q.family))
+                    rl = rl.next
 
             #set qstate.return_msg 
             if not msg.set_return_msg(qstate):
@@ -90,7 +90,7 @@ def operate(id, event, qstate, qdata):
         log_info("pythonmod: iterator module done")
         qstate.ext_state[id] = MODULE_FINISHED 
         return True
-      
+
     log_err("pythonmod: bad event")
     qstate.ext_state[id] = MODULE_ERROR
     return True
index df06d1064b04096bd765d34d35c8a0ebc5a0fff5..96accb69cca6e48e7405204f818f5a46cd796ab6 100644 (file)
@@ -1365,11 +1365,12 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
     int python_inplace_cb_reply_generic(struct query_info* qinfo,
         struct module_qstate* qstate, struct reply_info* rep, int rcode,
         struct edns_data* edns, struct edns_option** opt_list_out,
-        struct regional* region, int id, void* python_callback)
+        struct comm_reply* repinfo, struct regional* region, int id,
+        void* python_callback)
     {
         PyObject *func, *py_edns, *py_qstate, *py_opt_list_out, *py_qinfo;
-        PyObject *py_rep, *py_region;
-        PyObject *result;
+        PyObject *py_rep, *py_repinfo, *py_region;
+        PyObject *py_args, *py_kwargs, *result;
         int res = 0;
 
         PyGILState_STATE gstate = PyGILState_Ensure();
@@ -1381,15 +1382,21 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
             SWIGTYPE_p_p_edns_option, 0);
         py_qinfo = SWIG_NewPointerObj((void*) qinfo, SWIGTYPE_p_query_info, 0);
         py_rep = SWIG_NewPointerObj((void*) rep, SWIGTYPE_p_reply_info, 0);
+        py_repinfo = SWIG_NewPointerObj((void*) repinfo, SWIGTYPE_p_comm_reply, 0);
         py_region = SWIG_NewPointerObj((void*) region, SWIGTYPE_p_regional, 0);
-        result = PyObject_CallFunction(func, "OOOiOOO", py_qinfo, py_qstate,
-            py_rep, rcode, py_edns, py_opt_list_out, py_region);
+        py_args = Py_BuildValue("(OOOiOOO)", py_qinfo, py_qstate, py_rep,
+            rcode, py_edns, py_opt_list_out, py_region);
+        py_kwargs = Py_BuildValue("{s:O}", "repinfo", py_repinfo);
+        result = PyObject_Call(func, py_args, py_kwargs);
         Py_XDECREF(py_edns);
         Py_XDECREF(py_qstate);
         Py_XDECREF(py_opt_list_out);
         Py_XDECREF(py_qinfo);
         Py_XDECREF(py_rep);
+        Py_XDECREF(py_repinfo);
         Py_XDECREF(py_region);
+        Py_XDECREF(py_args);
+        Py_XDECREF(py_kwargs);
         if (result) {
             res = PyInt_AsLong(result);
         }
index 7c7c0e751c30cc438063eeec68c17521a09be4ec..991ae51a20a74751041aed84a6020294b097c4e9 100644 (file)
@@ -72,5 +72,6 @@ size_t pythonmod_get_mem(struct module_env* env, int id);
 int python_inplace_cb_reply_generic(struct query_info* qinfo,
        struct module_qstate* qstate, struct reply_info* rep, int rcode,
        struct edns_data* edns, struct edns_option** opt_list_out,
-       struct regional* region, int id, void* python_callback);
+       struct comm_reply* repinfo, struct regional* region, int id,
+       void* python_callback);
 #endif /* PYTHONMOD_H */
index e8c99077d492d7bf2c8ecaef819d0bd08bfa37a3..9a4fb5a50e38f2f5b7151d10b7e32e9dd6a8bf06 100644 (file)
@@ -3169,8 +3169,8 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
 /** encode auth answer */
 static void
 auth_answer_encode(struct query_info* qinfo, struct module_env* env,
-       struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
-       struct dns_msg* msg)
+       struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
+       struct regional* temp, struct dns_msg* msg)
 {
        uint16_t udpsize;
        udpsize = edns->udp_size;
@@ -3180,7 +3180,7 @@ auth_answer_encode(struct query_info* qinfo, struct module_env* env,
        edns->bits &= EDNS_DO;
 
        if(!inplace_cb_reply_local_call(env, qinfo, NULL, msg->rep,
-               (int)FLAGS_GET_RCODE(msg->rep->flags), edns, temp)
+               (int)FLAGS_GET_RCODE(msg->rep->flags), edns, repinfo, temp)
                || !reply_info_answer_encode(qinfo, msg->rep,
                *(uint16_t*)sldns_buffer_begin(buf),
                sldns_buffer_read_u16_at(buf, 2),
@@ -3195,8 +3195,8 @@ auth_answer_encode(struct query_info* qinfo, struct module_env* env,
 /** encode auth error answer */
 static void
 auth_error_encode(struct query_info* qinfo, struct module_env* env,
-       struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
-       int rcode)
+       struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
+       struct regional* temp, int rcode)
 {
        edns->edns_version = EDNS_ADVERTISED_VERSION;
        edns->udp_size = EDNS_ADVERTISED_SIZE;
@@ -3204,7 +3204,7 @@ auth_error_encode(struct query_info* qinfo, struct module_env* env,
        edns->bits &= EDNS_DO;
 
        if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
-               rcode, edns, temp))
+               rcode, edns, repinfo, temp))
                edns->opt_list = NULL;
        error_encode(buf, rcode|BIT_AA, qinfo,
                *(uint16_t*)sldns_buffer_begin(buf),
@@ -3212,8 +3212,8 @@ auth_error_encode(struct query_info* qinfo, struct module_env* env,
 }
 
 int auth_zones_answer(struct auth_zones* az, struct module_env* env,
-       struct query_info* qinfo, struct edns_data* edns, struct sldns_buffer* buf,
-       struct regional* temp)
+       struct query_info* qinfo, struct edns_data* edns,
+       struct comm_reply* repinfo, struct sldns_buffer* buf, struct regional* temp)
 {
        struct dns_msg* msg = NULL;
        struct auth_zone* z;
@@ -3261,9 +3261,9 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
 
        /* encode answer */
        if(!r)
-               auth_error_encode(qinfo, env, edns, buf, temp,
+               auth_error_encode(qinfo, env, edns, repinfo, buf, temp,
                        LDNS_RCODE_SERVFAIL);
-       else    auth_answer_encode(qinfo, env, edns, buf, temp, msg);
+       else    auth_answer_encode(qinfo, env, edns, repinfo, buf, temp, msg);
 
        return 1;
 }
index 39a16966c2aa3b9ee9343ca4d1f9abd2c3ce2e9e..8c636eaa446c9476b8b014c1f912e367f62f001c 100644 (file)
@@ -512,12 +512,13 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
  * @param qinfo: query info (parsed).
  * @param edns: edns info (parsed).
  * @param buf: buffer with query ID and flags, also for reply.
+ * @param repinfo: reply information for a communication point.
  * @param temp: temporary storage region.
  * @return false if not answered
  */
 int auth_zones_answer(struct auth_zones* az, struct module_env* env,
-       struct query_info* qinfo, struct edns_data* edns, struct sldns_buffer* buf,
-       struct regional* temp);
+       struct query_info* qinfo, struct edns_data* edns,
+       struct comm_reply* repinfo, struct sldns_buffer* buf, struct regional* temp);
 
 /** 
  * Find the auth zone that is above the given qname.
index b9acc642accf681f6731052b50f7b70477f5f0fb..e4c574f079b23c412223160d5f966efd00edd728 100644 (file)
@@ -1146,8 +1146,9 @@ void local_zones_print(struct local_zones* zones)
 /** encode answer consisting of 1 rrset */
 static int
 local_encode(struct query_info* qinfo, struct module_env* env,
-       struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
-       struct ub_packed_rrset_key* rrset, int ansec, int rcode)
+       struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
+       struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec,
+       int rcode)
 {
        struct reply_info rep;
        uint16_t udpsize;
@@ -1165,23 +1166,22 @@ local_encode(struct query_info* qinfo, struct module_env* env,
        edns->udp_size = EDNS_ADVERTISED_SIZE;
        edns->ext_rcode = 0;
        edns->bits &= EDNS_DO;
-       if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns, temp)
-               || !reply_info_answer_encode(qinfo, &rep,
-               *(uint16_t*)sldns_buffer_begin(buf),
-               sldns_buffer_read_u16_at(buf, 2),
-               buf, 0, 0, temp, udpsize, edns,
-               (int)(edns->bits&EDNS_DO), 0))
+       if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns,
+               repinfo, temp) || !reply_info_answer_encode(qinfo, &rep,
+               *(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2),
+               buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) {
                error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
                        *(uint16_t*)sldns_buffer_begin(buf),
                        sldns_buffer_read_u16_at(buf, 2), edns);
+       }
        return 1;
 }
 
 /** encode local error answer */
 static void
 local_error_encode(struct query_info* qinfo, struct module_env* env,
-       struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
-       int rcode, int r)
+       struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
+       struct regional* temp, int rcode, int r)
 {
        edns->edns_version = EDNS_ADVERTISED_VERSION;
        edns->udp_size = EDNS_ADVERTISED_SIZE;
@@ -1189,7 +1189,7 @@ local_error_encode(struct query_info* qinfo, struct module_env* env,
        edns->bits &= EDNS_DO;
 
        if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
-               rcode, edns, temp))
+               rcode, edns, repinfo, temp))
                edns->opt_list = NULL;
        error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf),
                sldns_buffer_read_u16_at(buf, 2), edns);
@@ -1310,7 +1310,8 @@ find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
 /** answer local data match */
 static int
 local_data_answer(struct local_zone* z, struct module_env* env,
-       struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
+       struct query_info* qinfo, struct edns_data* edns,
+       struct comm_reply* repinfo, sldns_buffer* buf,
        struct regional* temp, int labs, struct local_data** ldp,
        enum localzone_type lz_type, int tag, struct config_strlist** tag_datas,
        size_t tag_datas_size, char** tagname, int num_tags)
@@ -1339,7 +1340,7 @@ local_data_answer(struct local_zone* z, struct module_env* env,
                                 * chain. */
                                if(qinfo->local_alias)
                                        return 1;
-                               return local_encode(qinfo, env, edns, buf, temp,
+                               return local_encode(qinfo, env, edns, repinfo, buf, temp,
                                        &r, 1, LDNS_RCODE_NOERROR);
                        }
                }
@@ -1374,29 +1375,31 @@ local_data_answer(struct local_zone* z, struct module_env* env,
                struct ub_packed_rrset_key r = *lr->rrset;
                r.rk.dname = qinfo->qname;
                r.rk.dname_len = qinfo->qname_len;
-               return local_encode(qinfo, env, edns, buf, temp, &r, 1, 
+               return local_encode(qinfo, env, edns, repinfo, buf, temp, &r, 1,
                        LDNS_RCODE_NOERROR);
        }
-       return local_encode(qinfo, env, edns, buf, temp, lr->rrset, 1, 
+       return local_encode(qinfo, env, edns, repinfo, buf, temp, lr->rrset, 1,
                LDNS_RCODE_NOERROR);
 }
 
 /** 
- * answer in case where no exact match is found 
- * @param z: zone for query
- * @param env: module environment
- * @param qinfo: query
- * @param edns: edns from query
+ * Answer in case where no exact match is found.
+ * @param z: zone for query.
+ * @param env: module environment.
+ * @param qinfo: query.
+ * @param edns: edns from query.
+ * @param repinfo: source address for checks. may be NULL.
  * @param buf: buffer for answer.
- * @param temp: temp region for encoding
+ * @param temp: temp region for encoding.
  * @param ld: local data, if NULL, no such name exists in localdata.
- * @param lz_type: type of the local zone
+ * @param lz_type: type of the local zone.
  * @return 1 if a reply is to be sent, 0 if not.
  */
 static int
 lz_zone_answer(struct local_zone* z, struct module_env* env,
-       struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
-       struct regional* temp, struct local_data* ld, enum localzone_type lz_type)
+       struct query_info* qinfo, struct edns_data* edns,
+       struct comm_reply* repinfo, sldns_buffer* buf, struct regional* temp,
+       struct local_data* ld, enum localzone_type lz_type)
 {
        if(lz_type == local_zone_deny || lz_type == local_zone_inform_deny) {
                /** no reply at all, signal caller by clearing buffer. */
@@ -1405,7 +1408,7 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
                return 1;
        } else if(lz_type == local_zone_refuse
                || lz_type == local_zone_always_refuse) {
-               local_error_encode(qinfo, env, edns, buf, temp,
+               local_error_encode(qinfo, env, edns, repinfo, buf, temp,
                        LDNS_RCODE_REFUSED, (LDNS_RCODE_REFUSED|BIT_AA));
                return 1;
        } else if(lz_type == local_zone_static ||
@@ -1421,9 +1424,9 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
                int rcode = (ld || lz_type == local_zone_redirect)?
                        LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
                if(z->soa)
-                       return local_encode(qinfo, env, edns, buf, temp, 
+                       return local_encode(qinfo, env, edns, repinfo, buf, temp,
                                z->soa, 0, rcode);
-               local_error_encode(qinfo, env, edns, buf, temp, rcode,
+               local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode,
                        (rcode|BIT_AA));
                return 1;
        } else if(lz_type == local_zone_typetransparent
@@ -1438,9 +1441,9 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
        if(ld && ld->rrsets) {
                int rcode = LDNS_RCODE_NOERROR;
                if(z->soa)
-                       return local_encode(qinfo, env, edns, buf, temp, 
+                       return local_encode(qinfo, env, edns, repinfo, buf, temp,
                                z->soa, 0, rcode);
-               local_error_encode(qinfo, env, edns, buf, temp, rcode,
+               local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode,
                        (rcode|BIT_AA));
                return 1;
        }
@@ -1584,14 +1587,14 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
        if(lzt != local_zone_always_refuse
                && lzt != local_zone_always_transparent
                && lzt != local_zone_always_nxdomain
-               && local_data_answer(z, env, qinfo, edns, buf, temp, labs, &ld, lzt,
-                       tag, tag_datas, tag_datas_size, tagname, num_tags)) {
+               && local_data_answer(z, env, qinfo, edns, repinfo, buf, temp, labs,
+                       &ld, lzt, tag, tag_datas, tag_datas_size, tagname, num_tags)) {
                lock_rw_unlock(&z->lock);
                /* We should tell the caller that encode is deferred if we found
                 * a local alias. */
                return !qinfo->local_alias;
        }
-       r = lz_zone_answer(z, env, qinfo, edns, buf, temp, ld, lzt);
+       r = lz_zone_answer(z, env, qinfo, edns, repinfo, buf, temp, ld, lzt);
        lock_rw_unlock(&z->lock);
        return r && !qinfo->local_alias; /* see above */
 }
index 6688d9c2cec278203055940021673175b7337a32..c6bb9ef2bc6394b12ff9739d52609f993ea15584 100644 (file)
@@ -386,7 +386,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
                if(!s) {
                        log_err("mesh_state_create: out of memory; SERVFAIL");
                        if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
-                               LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
+                               LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
                                        edns->opt_list = NULL;
                        error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
                                qinfo, qid, qflags, edns);
@@ -402,7 +402,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
                        if(!s->s.edns_opts_front_in) {
                                log_err("mesh_state_create: out of memory; SERVFAIL");
                                if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL,
-                                       NULL, LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
+                                       NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
                                                edns->opt_list = NULL;
                                error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
                                        qinfo, qid, qflags, edns);
@@ -430,7 +430,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
        if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo)) {
                        log_err("mesh_new_client: out of memory; SERVFAIL");
                        if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
-                               NULL, LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
+                               NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
                                        edns->opt_list = NULL;
                        error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
                                qinfo, qid, qflags, edns);
@@ -987,11 +987,11 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
        if(rcode) {
                if(rcode == LDNS_RCODE_SERVFAIL) {
                        if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
-                               rep, rcode, &r->edns, m->s.region))
+                               rep, rcode, &r->edns, NULL, m->s.region))
                                        r->edns.opt_list = NULL;
                } else {
                        if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
-                               &r->edns, m->s.region))
+                               &r->edns, NULL, m->s.region))
                                        r->edns.opt_list = NULL;
                }
                fptr_ok(fptr_whitelist_mesh_cb(r->cb));
@@ -1006,7 +1006,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
                r->edns.bits &= EDNS_DO;
 
                if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
-                       LDNS_RCODE_NOERROR, &r->edns, m->s.region) ||
+                       LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region) ||
                        !reply_info_answer_encode(&m->s.qinfo, rep, r->qid, 
                        r->qflags, r->buf, 0, 1, 
                        m->s.env->scratch, udp_size, &r->edns, 
@@ -1084,11 +1084,11 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
                m->s.qinfo.local_alias = r->local_alias;
                if(rcode == LDNS_RCODE_SERVFAIL) {
                        if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
-                               rep, rcode, &r->edns, m->s.region))
+                               rep, rcode, &r->edns, NULL, m->s.region))
                                        r->edns.opt_list = NULL;
                } else { 
                        if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
-                               &r->edns, m->s.region))
+                               &r->edns, NULL, m->s.region))
                                        r->edns.opt_list = NULL;
                }
                error_encode(r->query_reply.c->buffer, rcode, &m->s.qinfo,
@@ -1103,7 +1103,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
                m->s.qinfo.qname = r->qname;
                m->s.qinfo.local_alias = r->local_alias;
                if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
-                       LDNS_RCODE_NOERROR, &r->edns, m->s.region) ||
+                       LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region) ||
                        !apply_edns_options(&r->edns, &edns_bak,
                                m->s.env->cfg, r->query_reply.c,
                                m->s.region) ||
@@ -1113,7 +1113,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
                        (int)(r->edns.bits & EDNS_DO), secure)) 
                {
                        if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
-                       rep, LDNS_RCODE_SERVFAIL, &r->edns, m->s.region))
+                       rep, LDNS_RCODE_SERVFAIL, &r->edns, NULL, m->s.region))
                                r->edns.opt_list = NULL;
                        error_encode(r->query_reply.c->buffer, 
                                LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid, 
index 1e16d912ca79a868691df6c8309cc740db8aed02..248ecb8eb58589743de02a0e3b475940cab1495c 100644 (file)
@@ -1014,7 +1014,7 @@ static int inplace_cb_reply_call_generic(
     struct inplace_cb* callback_list, enum inplace_cb_list_type type,
        struct query_info* qinfo, struct module_qstate* qstate,
        struct reply_info* rep, int rcode, struct edns_data* edns,
-       struct regional* region)
+       struct comm_reply* repinfo, struct regional* region)
 {
        struct inplace_cb* cb;
        struct edns_option* opt_list_out = NULL;
@@ -1027,7 +1027,7 @@ static int inplace_cb_reply_call_generic(
                fptr_ok(fptr_whitelist_inplace_cb_reply_generic(
                        (inplace_cb_reply_func_type*)cb->cb, type));
                (void)(*(inplace_cb_reply_func_type*)cb->cb)(qinfo, qstate, rep,
-                       rcode, edns, &opt_list_out, region, cb->id, cb->cb_arg);
+                       rcode, edns, &opt_list_out, repinfo, region, cb->id, cb->cb_arg);
        }
        edns->opt_list = opt_list_out;
        return 1;
@@ -1035,44 +1035,45 @@ static int inplace_cb_reply_call_generic(
 
 int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
        struct module_qstate* qstate, struct reply_info* rep, int rcode,
-       struct edns_data* edns, struct regional* region)
+       struct edns_data* edns, struct comm_reply* repinfo, struct regional* region)
 {
        return inplace_cb_reply_call_generic(
                env->inplace_cb_lists[inplace_cb_reply], inplace_cb_reply, qinfo,
-               qstate, rep, rcode, edns, region);
+               qstate, rep, rcode, edns, repinfo, region);
 }
 
 int inplace_cb_reply_cache_call(struct module_env* env,
        struct query_info* qinfo, struct module_qstate* qstate,
        struct reply_info* rep, int rcode, struct edns_data* edns,
-       struct regional* region)
+       struct comm_reply* repinfo, struct regional* region)
 {
        return inplace_cb_reply_call_generic(
                env->inplace_cb_lists[inplace_cb_reply_cache], inplace_cb_reply_cache,
-               qinfo, qstate, rep, rcode, edns, region);
+               qinfo, qstate, rep, rcode, edns, repinfo, region);
 }
 
 int inplace_cb_reply_local_call(struct module_env* env,
        struct query_info* qinfo, struct module_qstate* qstate,
        struct reply_info* rep, int rcode, struct edns_data* edns,
-       struct regional* region)
+       struct comm_reply* repinfo, struct regional* region)
 {
        return inplace_cb_reply_call_generic(
                env->inplace_cb_lists[inplace_cb_reply_local], inplace_cb_reply_local,
-               qinfo, qstate, rep, rcode, edns, region);
+               qinfo, qstate, rep, rcode, edns, repinfo, region);
 }
 
 int inplace_cb_reply_servfail_call(struct module_env* env,
        struct query_info* qinfo, struct module_qstate* qstate,
        struct reply_info* rep, int rcode, struct edns_data* edns,
-       struct regional* region)
+       struct comm_reply* repinfo, struct regional* region)
 {
        /* We are going to servfail. Remove any potential edns options. */
        if(qstate)
                qstate->edns_opts_front_out = NULL;
        return inplace_cb_reply_call_generic(
                env->inplace_cb_lists[inplace_cb_reply_servfail],
-               inplace_cb_reply_servfail, qinfo, qstate, rep, rcode, edns, region);
+               inplace_cb_reply_servfail, qinfo, qstate, rep, rcode, edns, repinfo,
+               region);
 }
 
 int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo,
index 60e6438a84abd889cde5a14621f5cfbad1a41316..73103b7c05b7d1ebbc943787f58831ea41f7c25e 100644 (file)
@@ -545,12 +545,13 @@ struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code);
  * @param rep: Reply info. Could be NULL.
  * @param rcode: return code.
  * @param edns: edns data of the reply.
+ * @param repinfo: comm_reply. NULL.
  * @param region: region to store data.
  * @return false on failure (a callback function returned an error).
  */
 int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
        struct module_qstate* qstate, struct reply_info* rep, int rcode,
-       struct edns_data* edns, struct regional* region);
+       struct edns_data* edns, struct comm_reply* repinfo, struct regional* region);
 
 /**
  * Call the registered functions in the inplace_cb_reply_cache linked list.
@@ -561,13 +562,14 @@ int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
  * @param rep: Reply info.
  * @param rcode: return code.
  * @param edns: edns data of the reply. Edns input can be found here.
+ * @param repinfo: comm_reply. Reply information for a communication point.
  * @param region: region to store data.
  * @return false on failure (a callback function returned an error).
  */
 int inplace_cb_reply_cache_call(struct module_env* env,
        struct query_info* qinfo, struct module_qstate* qstate,
        struct reply_info* rep, int rcode, struct edns_data* edns,
-       struct regional* region);
+       struct comm_reply* repinfo, struct regional* region);
 
 /**
  * Call the registered functions in the inplace_cb_reply_local linked list.
@@ -578,13 +580,14 @@ int inplace_cb_reply_cache_call(struct module_env* env,
  * @param rep: Reply info.
  * @param rcode: return code.
  * @param edns: edns data of the reply. Edns input can be found here.
+ * @param repinfo: comm_reply. Reply information for a communication point.
  * @param region: region to store data.
  * @return false on failure (a callback function returned an error).
  */
 int inplace_cb_reply_local_call(struct module_env* env,
        struct query_info* qinfo, struct module_qstate* qstate,
        struct reply_info* rep, int rcode, struct edns_data* edns,
-       struct regional* region);
+       struct comm_reply* repinfo, struct regional* region);
 
 /**
  * Call the registered functions in the inplace_cb_reply linked list.
@@ -596,13 +599,14 @@ int inplace_cb_reply_local_call(struct module_env* env,
  * @param rcode: return code. LDNS_RCODE_SERVFAIL.
  * @param edns: edns data of the reply. Edns input can be found here if qstate
  *     is NULL.
+ * @param repinfo: comm_reply. Reply information for a communication point.
  * @param region: region to store data.
  * @return false on failure (a callback function returned an error).
  */
 int inplace_cb_reply_servfail_call(struct module_env* env,
        struct query_info* qinfo, struct module_qstate* qstate,
        struct reply_info* rep, int rcode, struct edns_data* edns,
-       struct regional* region);
+       struct comm_reply* repinfo, struct regional* region);
 
 /**
  * Call the registered functions in the inplace_cb_query linked list.
index 31c531384df4827003e126dc55bed96b4ef20910..1b9aed216c7b89812eba66bcc0b27173fca73225 100644 (file)
@@ -236,8 +236,8 @@ struct inplace_cb {
 
 /**
  * Inplace callback function called before replying.
- * Called as func(edns, qstate, opt_list_out, qinfo, reply_info, rcode,
- *                region, python_callback)
+ * Called as func(qinfo, qstate, rep, rcode, edns, opt_list_out, repinfo,
+ *                region, id, python_callback)
  * Where:
  *     qinfo: the query info.
  *     qstate: the module state. NULL when calling before the query reaches the
@@ -247,18 +247,23 @@ struct inplace_cb {
  *     edns: the edns_data of the reply. When qstate is NULL, it is also used as
  *             the edns input.
  *     opt_list_out: the edns options list for the reply.
+ *     repinfo: reply information for a communication point. NULL when calling
+ *             during the mesh states; the same could be found from
+ *             qstate->mesh_info->reply_list.
  *     region: region to store data.
+ *     id: module id.
  *     python_callback: only used for registering a python callback function.
  */
 typedef int inplace_cb_reply_func_type(struct query_info* qinfo,
        struct module_qstate* qstate, struct reply_info* rep, int rcode,
-       struct edns_data* edns, struct edns_option** opt_list_out, 
-       struct regional* region, int id, void* callback);
+       struct edns_data* edns, struct edns_option** opt_list_out,
+       struct comm_reply* repinfo, struct regional* region, int id,
+       void* callback);
 
 /**
  * Inplace callback function called before sending the query to a nameserver.
  * Called as func(qinfo, flags, qstate, addr, addrlen, zone, zonelen, region,
- *                python_callback)
+ *                id, python_callback)
  * Where:
  *     qinfo: query info.
  *     flags: flags of the query.
@@ -270,6 +275,7 @@ typedef int inplace_cb_reply_func_type(struct query_info* qinfo,
  *             authoritative.
  *     zonelen: length of zone.
  *     region: region to store data.
+ *     id: module id.
  *     python_callback: only used for registering a python callback function.
  */
 typedef int inplace_cb_query_func_type(struct query_info* qinfo, uint16_t flags,
@@ -279,10 +285,10 @@ typedef int inplace_cb_query_func_type(struct query_info* qinfo, uint16_t flags,
 
 /**
  * Inplace callback function called after parsing edns on query reply.
- * Called as func(qstate, cb_args)
+ * Called as func(qstate, id, cb_args)
  * Where:
- *     qstate: the query state
- *     id: module id
+ *     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, 
@@ -290,11 +296,11 @@ typedef int inplace_cb_edns_back_parsed_func_type(struct module_qstate* qstate,
 
 /**
  * Inplace callback function called after parsing query response.
- * Called as func(qstate, id, cb_args)
+ * Called as func(qstate, response, id, cb_args)
  * Where:
- *     qstate: the query state
- *     response: query response
- *     id: module id
+ *     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,