- #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.


git-svn-id: file:///svn/unbound/trunk@4870 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
George Thessalonikefs 2018-08-22 10:51:13 +00:00
parent 4daf8f5bdb
commit 0171d06aa2
15 changed files with 297 additions and 145 deletions

View file

@ -511,7 +511,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
edns->ext_rcode = 0; edns->ext_rcode = 0;
edns->bits &= EDNS_DO; edns->bits &= EDNS_DO;
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, 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; return 0;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
&msg->qinfo, id, flags, edns); &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->ext_rcode = 0;
edns->bits &= EDNS_DO; edns->bits &= EDNS_DO;
if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, msg->rep, 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; return 0;
msg->rep->flags |= BIT_QR|BIT_RA; msg->rep->flags |= BIT_QR|BIT_RA;
if(!apply_edns_options(edns, &edns_bak, worker->env.cfg, 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, repinfo->c->buffer, 0, 1, worker->scratchpad,
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) { udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL, 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; edns->opt_list = NULL;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
&msg->qinfo, id, flags, edns); &msg->qinfo, id, flags, edns);
@ -673,7 +673,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
edns->ext_rcode = 0; edns->ext_rcode = 0;
edns->bits &= EDNS_DO; edns->bits &= EDNS_DO;
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep, 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; goto bail_out;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, id, flags, edns); qinfo, id, flags, edns);
@ -707,7 +707,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
edns->ext_rcode = 0; edns->ext_rcode = 0;
edns->bits &= EDNS_DO; edns->bits &= EDNS_DO;
if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, rep, 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; goto bail_out;
*alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */ *alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
if(worker->daemon->use_response_ip && !partial_rep && 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, repinfo->c->buffer, timenow, 1, worker->scratchpad,
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) { udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL, 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; edns->opt_list = NULL;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, id, flags, edns); 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 num: number of strings in array.
* @param edns: edns reply information. * @param edns: edns reply information.
* @param worker: worker with scratch region. * @param worker: worker with scratch region.
* @param repinfo: reply information for a communication point.
*/ */
static void static void
chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns, 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; int i;
unsigned int rd = LDNS_RD_WIRE(sldns_buffer_begin(pkt)); 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->udp_size = EDNS_ADVERTISED_SIZE;
edns->bits &= EDNS_DO; edns->bits &= EDNS_DO;
if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL, 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; edns->opt_list = NULL;
if(sldns_buffer_capacity(pkt) >= if(sldns_buffer_capacity(pkt) >=
sldns_buffer_limit(pkt)+calc_edns_field_size(edns)) 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 */ /** Reply with one string */
static void static void
chaos_replyonestr(sldns_buffer* pkt, const char* str, struct edns_data* edns, 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 pkt: buffer
* @param edns: edns reply information. * @param edns: edns reply information.
* @param w: worker with scratch region. * @param w: worker with scratch region.
* @param repinfo: reply information for a communication point.
*/ */
static void 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_TXT 16 /* max number of TXT records */
#define TA_RESPONSE_MAX_TAGS 32 /* max number of tags printed per zone */ #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) { if(!w->env.need_to_validate) {
/* no validator module, reply no trustanchors */ /* no validator module, reply no trustanchors */
chaos_replystr(pkt, NULL, 0, edns, w); chaos_replystr(pkt, NULL, 0, edns, w, repinfo);
return; return;
} }
@ -891,7 +894,7 @@ chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w)
} }
lock_basic_unlock(&w->env.anchors->lock); 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); 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 w: worker
* @param qinfo: query info. Pointer into packet buffer. * @param qinfo: query info. Pointer into packet buffer.
* @param edns: edns info from query. * @param edns: edns info from query.
* @param repinfo: reply information for a communication point.
* @param pkt: packet buffer. * @param pkt: packet buffer.
* @return: true if a reply is to be sent. * @return: true if a reply is to be sent.
*/ */
static int static int
answer_chaos(struct worker* w, struct query_info* qinfo, answer_chaos(struct worker* w, struct query_info* qinfo,
struct edns_data* edns, sldns_buffer* pkt) struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* pkt)
{ {
struct config_file* cfg = w->env.cfg; struct config_file* cfg = w->env.cfg;
if(qinfo->qtype != LDNS_RR_TYPE_ANY && qinfo->qtype != LDNS_RR_TYPE_TXT) 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]; char buf[MAXHOSTNAMELEN+1];
if (gethostname(buf, MAXHOSTNAMELEN) == 0) { if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
buf[MAXHOSTNAMELEN] = 0; buf[MAXHOSTNAMELEN] = 0;
chaos_replyonestr(pkt, buf, edns, w); chaos_replyonestr(pkt, buf, edns, w, repinfo);
} else { } else {
log_err("gethostname: %s", strerror(errno)); 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; return 1;
} }
if(query_dname_compare(qinfo->qname, if(query_dname_compare(qinfo->qname,
@ -938,8 +942,8 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
if(cfg->hide_version) if(cfg->hide_version)
return 0; return 0;
if(cfg->version==NULL || cfg->version[0]==0) if(cfg->version==NULL || cfg->version[0]==0)
chaos_replyonestr(pkt, PACKAGE_STRING, edns, w); chaos_replyonestr(pkt, PACKAGE_STRING, edns, w, repinfo);
else chaos_replyonestr(pkt, cfg->version, edns, w); else chaos_replyonestr(pkt, cfg->version, edns, w, repinfo);
return 1; return 1;
} }
if(query_dname_compare(qinfo->qname, if(query_dname_compare(qinfo->qname,
@ -947,7 +951,7 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
{ {
if(cfg->hide_trustanchor) if(cfg->hide_trustanchor)
return 0; return 0;
chaos_trustanchor(pkt, edns, w); chaos_trustanchor(pkt, edns, w, repinfo);
return 1; return 1;
} }
@ -1330,7 +1334,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
if(c->type != comm_udp) if(c->type != comm_udp)
edns.udp_size = 65535; /* max size for TCP replies */ edns.udp_size = 65535; /* max size for TCP replies */
if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo, 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); server_stats_insrcode(&worker->stats, c->buffer);
regional_free_all(worker->scratchpad); regional_free_all(worker->scratchpad);
goto send_reply; goto send_reply;
@ -1357,7 +1361,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
} }
if(worker->env.auth_zones && if(worker->env.auth_zones &&
auth_zones_answer(worker->env.auth_zones, &worker->env, 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); regional_free_all(worker->scratchpad);
if(sldns_buffer_limit(c->buffer) == 0) { if(sldns_buffer_limit(c->buffer) == 0) {
comm_point_drop_reply(repinfo); comm_point_drop_reply(repinfo);

View 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 21 August 2018: Wouter
- log-local-actions: yes option for unbound.conf that logs all the - log-local-actions: yes option for unbound.conf that logs all the
local zone actions, a patch from Saksham Manchanda (Secure64). local zone actions, a patch from Saksham Manchanda (Secure64).

View file

@ -610,7 +610,7 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
return UB_NOERROR; return UB_NOERROR;
} }
if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones, 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); regional_free_all(w->env->scratch);
libworker_fillup_fg(q, LDNS_RCODE_NOERROR, libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
w->back->udp_buff, sec_status_insecure, NULL, 0); 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; return UB_NOERROR;
} }
if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones, 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); regional_free_all(w->env->scratch);
free(qinfo.qname); free(qinfo.qname);
libworker_event_done_cb(q, LDNS_RCODE_NOERROR, libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
@ -827,7 +827,7 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
return; return;
} }
if(w->ctx->env->auth_zones && auth_zones_answer(w->ctx->env->auth_zones, 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); regional_free_all(w->env->scratch);
q->msg_security = sec_status_insecure; q->msg_security = sec_status_insecure;
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0); add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0);

View file

@ -40,9 +40,12 @@ The callback function's prototype is the following:
.. code-block:: python .. code-block:: python
def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region): def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
"""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. It will be called when answering with a resolved query.
:param qinfo: query_info struct; :param qinfo: query_info struct;
:param qstate: module qstate. It contains the available opt_lists; It :param qstate: module qstate. It contains the available opt_lists; It
SHOULD NOT be altered; SHOULD NOT be altered;
@ -54,7 +57,13 @@ The callback function's prototype is the following:
reply. It can be populated with EDNS options; reply. It can be populated with EDNS options;
:param region: region to allocate temporary data. Needs to be used when we :param region: region to allocate temporary data. Needs to be used when we
want to append a new option to opt_list_out. 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. :return: True on success, False on failure.
""" """
.. note:: The function's name is irrelevant. .. note:: The function's name is irrelevant.
@ -76,9 +85,12 @@ The callback function's prototype is the following:
.. code-block:: python .. code-block:: python
def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region): def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
"""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. It will be called when answering from the cache.
:param qinfo: query_info struct; :param qinfo: query_info struct;
:param qstate: module qstate. None; :param qstate: module qstate. None;
:param rep: reply_info struct; :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; reply. It can be populated with EDNS options;
:param region: region to allocate temporary data. Needs to be used when we :param region: region to allocate temporary data. Needs to be used when we
want to append a new option to opt_list_out. 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. :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. .. note:: The function's name is irrelevant.
@ -112,9 +134,12 @@ The callback function's prototype is the following:
.. code-block:: python .. code-block:: python
def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region): def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
"""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. It will be called when answering from local data.
:param qinfo: query_info struct; :param qinfo: query_info struct;
:param qstate: module qstate. None; :param qstate: module qstate. None;
:param rep: reply_info struct; :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; reply. It can be populated with EDNS options;
:param region: region to allocate temporary data. Needs to be used when we :param region: region to allocate temporary data. Needs to be used when we
want to append a new option to opt_list_out. 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. :return: True on success, False on failure.
""" """
.. note:: The function's name is irrelevant. .. note:: The function's name is irrelevant.
@ -148,9 +180,12 @@ The callback function's prototype is the following:
.. code-block:: python .. code-block:: python
def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region): def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
"""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. It will be called when answering with SERVFAIL.
:param qinfo: query_info struct; :param qinfo: query_info struct;
:param qstate: module qstate. If not None the relevant opt_lists are :param qstate: module qstate. If not None the relevant opt_lists are
available here; available here;
@ -163,7 +198,17 @@ The callback function's prototype is the following:
reply. It can be populated with EDNS options; reply. It can be populated with EDNS options;
:param region: region to allocate temporary data. Needs to be used when we :param region: region to allocate temporary data. Needs to be used when we
want to append a new option to opt_list_out. 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. :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. .. note:: The function's name is irrelevant.

View file

@ -43,6 +43,8 @@
# This query returns SERVFAIL as the txt record of bogus.nlnetlabs.nl is # This query returns SERVFAIL as the txt record of bogus.nlnetlabs.nl is
# intentionally bogus. The reply will contain an empty EDNS option # intentionally bogus. The reply will contain an empty EDNS option
# with option code 65003. # 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) # (unbound needs to be validating for this example to work)
# Useful functions: # Useful functions:
@ -70,9 +72,11 @@
def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
region): region, **kwargs):
"""Function that will be registered as an inplace callback function. """
Function that will be registered as an inplace callback function.
It will be called when answering with a resolved query. It will be called when answering with a resolved query.
:param qinfo: query_info struct; :param qinfo: query_info struct;
:param qstate: module qstate. It contains the available opt_lists; It :param qstate: module qstate. It contains the available opt_lists; It
SHOULD NOT be altered; 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; reply. It can be populated with EDNS options;
:param region: region to allocate temporary data. Needs to be used when we :param region: region to allocate temporary data. Needs to be used when we
want to append a new option to opt_list_out. 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. :return: True on success, False on failure.
""" """
log_info("python: called back while replying.") log_info("python: called back while replying.")
return True return True
def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
region): region, **kwargs):
"""Function that will be registered as an inplace callback function. """
Function that will be registered as an inplace callback function.
It will be called when answering from the cache. It will be called when answering from the cache.
:param qinfo: query_info struct; :param qinfo: query_info struct;
:param qstate: module qstate. None; :param qstate: module qstate. None;
:param rep: reply_info struct; :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; reply. It can be populated with EDNS options;
:param region: region to allocate temporary data. Needs to be used when we :param region: region to allocate temporary data. Needs to be used when we
want to append a new option to opt_list_out. 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. :return: True on success, False on failure.
For demonstration purposes we want to see if EDNS option 65002 is present For demonstration purposes we want to see if EDNS option 65002 is present
and reply with a new value. and reply with a new value.
""" """
log_info("python: called back while answering from cache.") log_info("python: called back while answering from cache.")
# Inspect the incoming EDNS options. # 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, def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
region): region, **kwargs):
"""Function that will be registered as an inplace callback function. """
Function that will be registered as an inplace callback function.
It will be called when answering from local data. It will be called when answering from local data.
:param qinfo: query_info struct; :param qinfo: query_info struct;
:param qstate: module qstate. None; :param qstate: module qstate. None;
:param rep: reply_info struct; :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; reply. It can be populated with EDNS options;
:param region: region to allocate temporary data. Needs to be used when we :param region: region to allocate temporary data. Needs to be used when we
want to append a new option to opt_list_out. 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. :return: True on success, False on failure.
""" """
log_info("python: called back while replying with local data or chaos" log_info("python: called back while replying with local data or chaos"
" reply.") " 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, def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
region): region, **kwargs):
"""Function that will be registered as an inplace callback function. """
Function that will be registered as an inplace callback function.
It will be called when answering with SERVFAIL. It will be called when answering with SERVFAIL.
:param qinfo: query_info struct; :param qinfo: query_info struct;
:param qstate: module qstate. If not None the relevant opt_lists are :param qstate: module qstate. If not None the relevant opt_lists are
available here; 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; reply. It can be populated with EDNS options;
:param region: region to allocate temporary data. Needs to be used when we :param region: region to allocate temporary data. Needs to be used when we
want to append a new option to opt_list_out. 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. :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.") log_info("python: called back while servfail.")
# Append the example ENDS option
b = bytearray.fromhex("") b = bytearray.fromhex("")
edns_opt_list_append(opt_list_out, 65003, b, region) 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 return True
def init_standard(id, env): 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 The function's signature is the same as the C counterpart and allows for
extra functionality during init. extra functionality during init.
..note:: This function is preferred by unbound over the old init function. ..note:: This function is preferred by unbound over the old init function.
..note:: The previously accessible configuration options can now be found in ..note:: The previously accessible configuration options can now be found in
env.cgf. env.cgf.
""" """
log_info("python: inited script {}".format(env.cfg.python_script)) log_info("python: inited script {}".format(env.cfg.python_script))
@ -215,11 +285,14 @@ def init_standard(id, env):
def init(id, cfg): def init(id, cfg):
"""Previous version init function. """
Previous version of the init function.
..note:: This function is still supported for backwards compatibility when ..note:: This function is still supported for backwards compatibility when
the init_standard function is missing. When init_standard is the init_standard function is missing. When init_standard is
present this function SHOULD be omitted to avoid confusion to the present this function SHOULD be omitted to avoid confusion to the
reader. reader.
""" """
return True return True

View file

@ -47,7 +47,7 @@ def deinit(id): return True
def inform_super(id, qstate, superqstate, qdata): return True def inform_super(id, qstate, superqstate, qdata): return True
def operate(id, event, qstate, qdata): 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 # 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, # to validate or iterator to lookup or spawn a subquery to look up,

View 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, int python_inplace_cb_reply_generic(struct query_info* qinfo,
struct module_qstate* qstate, struct reply_info* rep, int rcode, struct module_qstate* qstate, struct reply_info* rep, int rcode,
struct edns_data* edns, struct edns_option** opt_list_out, 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 *func, *py_edns, *py_qstate, *py_opt_list_out, *py_qinfo;
PyObject *py_rep, *py_region; PyObject *py_rep, *py_repinfo, *py_region;
PyObject *result; PyObject *py_args, *py_kwargs, *result;
int res = 0; int res = 0;
PyGILState_STATE gstate = PyGILState_Ensure(); 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); SWIGTYPE_p_p_edns_option, 0);
py_qinfo = SWIG_NewPointerObj((void*) qinfo, SWIGTYPE_p_query_info, 0); py_qinfo = SWIG_NewPointerObj((void*) qinfo, SWIGTYPE_p_query_info, 0);
py_rep = SWIG_NewPointerObj((void*) rep, SWIGTYPE_p_reply_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); py_region = SWIG_NewPointerObj((void*) region, SWIGTYPE_p_regional, 0);
result = PyObject_CallFunction(func, "OOOiOOO", py_qinfo, py_qstate, py_args = Py_BuildValue("(OOOiOOO)", py_qinfo, py_qstate, py_rep,
py_rep, rcode, py_edns, py_opt_list_out, py_region); 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_edns);
Py_XDECREF(py_qstate); Py_XDECREF(py_qstate);
Py_XDECREF(py_opt_list_out); Py_XDECREF(py_opt_list_out);
Py_XDECREF(py_qinfo); Py_XDECREF(py_qinfo);
Py_XDECREF(py_rep); Py_XDECREF(py_rep);
Py_XDECREF(py_repinfo);
Py_XDECREF(py_region); Py_XDECREF(py_region);
Py_XDECREF(py_args);
Py_XDECREF(py_kwargs);
if (result) { if (result) {
res = PyInt_AsLong(result); res = PyInt_AsLong(result);
} }

View 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, int python_inplace_cb_reply_generic(struct query_info* qinfo,
struct module_qstate* qstate, struct reply_info* rep, int rcode, struct module_qstate* qstate, struct reply_info* rep, int rcode,
struct edns_data* edns, struct edns_option** opt_list_out, 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 */ #endif /* PYTHONMOD_H */

View file

@ -3169,8 +3169,8 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
/** encode auth answer */ /** encode auth answer */
static void static void
auth_answer_encode(struct query_info* qinfo, struct module_env* env, auth_answer_encode(struct query_info* qinfo, struct module_env* env,
struct edns_data* edns, sldns_buffer* buf, struct regional* temp, struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
struct dns_msg* msg) struct regional* temp, struct dns_msg* msg)
{ {
uint16_t udpsize; uint16_t udpsize;
udpsize = edns->udp_size; udpsize = edns->udp_size;
@ -3180,7 +3180,7 @@ auth_answer_encode(struct query_info* qinfo, struct module_env* env,
edns->bits &= EDNS_DO; edns->bits &= EDNS_DO;
if(!inplace_cb_reply_local_call(env, qinfo, NULL, msg->rep, 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, || !reply_info_answer_encode(qinfo, msg->rep,
*(uint16_t*)sldns_buffer_begin(buf), *(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2), 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 */ /** encode auth error answer */
static void static void
auth_error_encode(struct query_info* qinfo, struct module_env* env, auth_error_encode(struct query_info* qinfo, struct module_env* env,
struct edns_data* edns, sldns_buffer* buf, struct regional* temp, struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
int rcode) struct regional* temp, int rcode)
{ {
edns->edns_version = EDNS_ADVERTISED_VERSION; edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE; 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; edns->bits &= EDNS_DO;
if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL, if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
rcode, edns, temp)) rcode, edns, repinfo, temp))
edns->opt_list = NULL; edns->opt_list = NULL;
error_encode(buf, rcode|BIT_AA, qinfo, error_encode(buf, rcode|BIT_AA, qinfo,
*(uint16_t*)sldns_buffer_begin(buf), *(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, 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 query_info* qinfo, struct edns_data* edns,
struct regional* temp) struct comm_reply* repinfo, struct sldns_buffer* buf, struct regional* temp)
{ {
struct dns_msg* msg = NULL; struct dns_msg* msg = NULL;
struct auth_zone* z; struct auth_zone* z;
@ -3261,9 +3261,9 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
/* encode answer */ /* encode answer */
if(!r) if(!r)
auth_error_encode(qinfo, env, edns, buf, temp, auth_error_encode(qinfo, env, edns, repinfo, buf, temp,
LDNS_RCODE_SERVFAIL); 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; return 1;
} }

View file

@ -512,12 +512,13 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
* @param qinfo: query info (parsed). * @param qinfo: query info (parsed).
* @param edns: edns info (parsed). * @param edns: edns info (parsed).
* @param buf: buffer with query ID and flags, also for reply. * @param buf: buffer with query ID and flags, also for reply.
* @param repinfo: reply information for a communication point.
* @param temp: temporary storage region. * @param temp: temporary storage region.
* @return false if not answered * @return false if not answered
*/ */
int auth_zones_answer(struct auth_zones* az, 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 query_info* qinfo, struct edns_data* edns,
struct regional* temp); struct comm_reply* repinfo, struct sldns_buffer* buf, struct regional* temp);
/** /**
* Find the auth zone that is above the given qname. * Find the auth zone that is above the given qname.

View file

@ -1146,8 +1146,9 @@ void local_zones_print(struct local_zones* zones)
/** encode answer consisting of 1 rrset */ /** encode answer consisting of 1 rrset */
static int static int
local_encode(struct query_info* qinfo, struct module_env* env, local_encode(struct query_info* qinfo, struct module_env* env,
struct edns_data* edns, sldns_buffer* buf, struct regional* temp, struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
struct ub_packed_rrset_key* rrset, int ansec, int rcode) struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec,
int rcode)
{ {
struct reply_info rep; struct reply_info rep;
uint16_t udpsize; uint16_t udpsize;
@ -1165,23 +1166,22 @@ local_encode(struct query_info* qinfo, struct module_env* env,
edns->udp_size = EDNS_ADVERTISED_SIZE; edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0; edns->ext_rcode = 0;
edns->bits &= EDNS_DO; edns->bits &= EDNS_DO;
if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns, temp) if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns,
|| !reply_info_answer_encode(qinfo, &rep, repinfo, temp) || !reply_info_answer_encode(qinfo, &rep,
*(uint16_t*)sldns_buffer_begin(buf), *(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2),
sldns_buffer_read_u16_at(buf, 2), buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) {
buf, 0, 0, temp, udpsize, edns,
(int)(edns->bits&EDNS_DO), 0))
error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo, error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
*(uint16_t*)sldns_buffer_begin(buf), *(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2), edns); sldns_buffer_read_u16_at(buf, 2), edns);
}
return 1; return 1;
} }
/** encode local error answer */ /** encode local error answer */
static void static void
local_error_encode(struct query_info* qinfo, struct module_env* env, local_error_encode(struct query_info* qinfo, struct module_env* env,
struct edns_data* edns, sldns_buffer* buf, struct regional* temp, struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
int rcode, int r) struct regional* temp, int rcode, int r)
{ {
edns->edns_version = EDNS_ADVERTISED_VERSION; edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE; 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; edns->bits &= EDNS_DO;
if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL, if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
rcode, edns, temp)) rcode, edns, repinfo, temp))
edns->opt_list = NULL; edns->opt_list = NULL;
error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf), error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2), edns); 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 */ /** answer local data match */
static int static int
local_data_answer(struct local_zone* z, struct module_env* env, 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, struct regional* temp, int labs, struct local_data** ldp,
enum localzone_type lz_type, int tag, struct config_strlist** tag_datas, enum localzone_type lz_type, int tag, struct config_strlist** tag_datas,
size_t tag_datas_size, char** tagname, int num_tags) 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. */ * chain. */
if(qinfo->local_alias) if(qinfo->local_alias)
return 1; return 1;
return local_encode(qinfo, env, edns, buf, temp, return local_encode(qinfo, env, edns, repinfo, buf, temp,
&r, 1, LDNS_RCODE_NOERROR); &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; struct ub_packed_rrset_key r = *lr->rrset;
r.rk.dname = qinfo->qname; r.rk.dname = qinfo->qname;
r.rk.dname_len = qinfo->qname_len; 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); 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); LDNS_RCODE_NOERROR);
} }
/** /**
* answer in case where no exact match is found * Answer in case where no exact match is found.
* @param z: zone for query * @param z: zone for query.
* @param env: module environment * @param env: module environment.
* @param qinfo: query * @param qinfo: query.
* @param edns: edns from query * @param edns: edns from query.
* @param repinfo: source address for checks. may be NULL.
* @param buf: buffer for answer. * @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 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. * @return 1 if a reply is to be sent, 0 if not.
*/ */
static int static int
lz_zone_answer(struct local_zone* z, struct module_env* env, lz_zone_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 regional* temp, struct local_data* ld, enum localzone_type lz_type) 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) { if(lz_type == local_zone_deny || lz_type == local_zone_inform_deny) {
/** no reply at all, signal caller by clearing buffer. */ /** 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; return 1;
} else if(lz_type == local_zone_refuse } else if(lz_type == local_zone_refuse
|| lz_type == local_zone_always_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)); LDNS_RCODE_REFUSED, (LDNS_RCODE_REFUSED|BIT_AA));
return 1; return 1;
} else if(lz_type == local_zone_static || } 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)? int rcode = (ld || lz_type == local_zone_redirect)?
LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN; LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
if(z->soa) if(z->soa)
return local_encode(qinfo, env, edns, buf, temp, return local_encode(qinfo, env, edns, repinfo, buf, temp,
z->soa, 0, rcode); 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)); (rcode|BIT_AA));
return 1; return 1;
} else if(lz_type == local_zone_typetransparent } 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) { if(ld && ld->rrsets) {
int rcode = LDNS_RCODE_NOERROR; int rcode = LDNS_RCODE_NOERROR;
if(z->soa) if(z->soa)
return local_encode(qinfo, env, edns, buf, temp, return local_encode(qinfo, env, edns, repinfo, buf, temp,
z->soa, 0, rcode); 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)); (rcode|BIT_AA));
return 1; return 1;
} }
@ -1584,14 +1587,14 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
if(lzt != local_zone_always_refuse if(lzt != local_zone_always_refuse
&& lzt != local_zone_always_transparent && lzt != local_zone_always_transparent
&& lzt != local_zone_always_nxdomain && lzt != local_zone_always_nxdomain
&& local_data_answer(z, env, qinfo, edns, buf, temp, labs, &ld, lzt, && local_data_answer(z, env, qinfo, edns, repinfo, buf, temp, labs,
tag, tag_datas, tag_datas_size, tagname, num_tags)) { &ld, lzt, tag, tag_datas, tag_datas_size, tagname, num_tags)) {
lock_rw_unlock(&z->lock); lock_rw_unlock(&z->lock);
/* We should tell the caller that encode is deferred if we found /* We should tell the caller that encode is deferred if we found
* a local alias. */ * a local alias. */
return !qinfo->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); lock_rw_unlock(&z->lock);
return r && !qinfo->local_alias; /* see above */ return r && !qinfo->local_alias; /* see above */
} }

View file

@ -386,7 +386,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!s) { if(!s) {
log_err("mesh_state_create: out of memory; SERVFAIL"); log_err("mesh_state_create: out of memory; SERVFAIL");
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL, 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; edns->opt_list = NULL;
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL, error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns); 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) { if(!s->s.edns_opts_front_in) {
log_err("mesh_state_create: out of memory; SERVFAIL"); log_err("mesh_state_create: out of memory; SERVFAIL");
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, 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; edns->opt_list = NULL;
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL, error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns); 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)) { if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo)) {
log_err("mesh_new_client: out of memory; SERVFAIL"); log_err("mesh_new_client: out of memory; SERVFAIL");
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s, 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; edns->opt_list = NULL;
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL, error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns); 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) {
if(rcode == LDNS_RCODE_SERVFAIL) { if(rcode == LDNS_RCODE_SERVFAIL) {
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, 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; r->edns.opt_list = NULL;
} else { } else {
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode, 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; r->edns.opt_list = NULL;
} }
fptr_ok(fptr_whitelist_mesh_cb(r->cb)); 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; r->edns.bits &= EDNS_DO;
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, 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, !reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->buf, 0, 1, r->qflags, r->buf, 0, 1,
m->s.env->scratch, udp_size, &r->edns, 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; m->s.qinfo.local_alias = r->local_alias;
if(rcode == LDNS_RCODE_SERVFAIL) { if(rcode == LDNS_RCODE_SERVFAIL) {
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, 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; r->edns.opt_list = NULL;
} else { } else {
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode, 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; r->edns.opt_list = NULL;
} }
error_encode(r->query_reply.c->buffer, rcode, &m->s.qinfo, 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.qname = r->qname;
m->s.qinfo.local_alias = r->local_alias; m->s.qinfo.local_alias = r->local_alias;
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, 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, !apply_edns_options(&r->edns, &edns_bak,
m->s.env->cfg, r->query_reply.c, m->s.env->cfg, r->query_reply.c,
m->s.region) || 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)) (int)(r->edns.bits & EDNS_DO), secure))
{ {
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, 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; r->edns.opt_list = NULL;
error_encode(r->query_reply.c->buffer, error_encode(r->query_reply.c->buffer,
LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid, LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid,

View file

@ -1014,7 +1014,7 @@ static int inplace_cb_reply_call_generic(
struct inplace_cb* callback_list, enum inplace_cb_list_type type, struct inplace_cb* callback_list, enum inplace_cb_list_type type,
struct query_info* qinfo, struct module_qstate* qstate, struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns, 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 inplace_cb* cb;
struct edns_option* opt_list_out = NULL; 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( fptr_ok(fptr_whitelist_inplace_cb_reply_generic(
(inplace_cb_reply_func_type*)cb->cb, type)); (inplace_cb_reply_func_type*)cb->cb, type));
(void)(*(inplace_cb_reply_func_type*)cb->cb)(qinfo, qstate, rep, (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; edns->opt_list = opt_list_out;
return 1; 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, int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
struct module_qstate* qstate, struct reply_info* rep, int rcode, 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( return inplace_cb_reply_call_generic(
env->inplace_cb_lists[inplace_cb_reply], inplace_cb_reply, qinfo, 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, int inplace_cb_reply_cache_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate, struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns, 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( return inplace_cb_reply_call_generic(
env->inplace_cb_lists[inplace_cb_reply_cache], inplace_cb_reply_cache, 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, int inplace_cb_reply_local_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate, struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns, 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( return inplace_cb_reply_call_generic(
env->inplace_cb_lists[inplace_cb_reply_local], inplace_cb_reply_local, 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, int inplace_cb_reply_servfail_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate, struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns, 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. */ /* We are going to servfail. Remove any potential edns options. */
if(qstate) if(qstate)
qstate->edns_opts_front_out = NULL; qstate->edns_opts_front_out = NULL;
return inplace_cb_reply_call_generic( return inplace_cb_reply_call_generic(
env->inplace_cb_lists[inplace_cb_reply_servfail], 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, int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo,

View 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 rep: Reply info. Could be NULL.
* @param rcode: return code. * @param rcode: return code.
* @param edns: edns data of the reply. * @param edns: edns data of the reply.
* @param repinfo: comm_reply. NULL.
* @param region: region to store data. * @param region: region to store data.
* @return false on failure (a callback function returned an error). * @return false on failure (a callback function returned an error).
*/ */
int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo, int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
struct module_qstate* qstate, struct reply_info* rep, int rcode, 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. * 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 rep: Reply info.
* @param rcode: return code. * @param rcode: return code.
* @param edns: edns data of the reply. Edns input can be found here. * @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. * @param region: region to store data.
* @return false on failure (a callback function returned an error). * @return false on failure (a callback function returned an error).
*/ */
int inplace_cb_reply_cache_call(struct module_env* env, int inplace_cb_reply_cache_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate, struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns, 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. * 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 rep: Reply info.
* @param rcode: return code. * @param rcode: return code.
* @param edns: edns data of the reply. Edns input can be found here. * @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. * @param region: region to store data.
* @return false on failure (a callback function returned an error). * @return false on failure (a callback function returned an error).
*/ */
int inplace_cb_reply_local_call(struct module_env* env, int inplace_cb_reply_local_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate, struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns, 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. * 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 rcode: return code. LDNS_RCODE_SERVFAIL.
* @param edns: edns data of the reply. Edns input can be found here if qstate * @param edns: edns data of the reply. Edns input can be found here if qstate
* is NULL. * is NULL.
* @param repinfo: comm_reply. Reply information for a communication point.
* @param region: region to store data. * @param region: region to store data.
* @return false on failure (a callback function returned an error). * @return false on failure (a callback function returned an error).
*/ */
int inplace_cb_reply_servfail_call(struct module_env* env, int inplace_cb_reply_servfail_call(struct module_env* env,
struct query_info* qinfo, struct module_qstate* qstate, struct query_info* qinfo, struct module_qstate* qstate,
struct reply_info* rep, int rcode, struct edns_data* edns, 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. * Call the registered functions in the inplace_cb_query linked list.

View file

@ -236,8 +236,8 @@ struct inplace_cb {
/** /**
* Inplace callback function called before replying. * Inplace callback function called before replying.
* Called as func(edns, qstate, opt_list_out, qinfo, reply_info, rcode, * Called as func(qinfo, qstate, rep, rcode, edns, opt_list_out, repinfo,
* region, python_callback) * region, id, python_callback)
* Where: * Where:
* qinfo: the query info. * qinfo: the query info.
* qstate: the module state. NULL when calling before the query reaches the * 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 * edns: the edns_data of the reply. When qstate is NULL, it is also used as
* the edns input. * the edns input.
* opt_list_out: the edns options list for the reply. * 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. * region: region to store data.
* id: module id.
* python_callback: only used for registering a python callback function. * python_callback: only used for registering a python callback function.
*/ */
typedef int inplace_cb_reply_func_type(struct query_info* qinfo, typedef int inplace_cb_reply_func_type(struct query_info* qinfo,
struct module_qstate* qstate, struct reply_info* rep, int rcode, struct module_qstate* qstate, struct reply_info* rep, int rcode,
struct edns_data* edns, struct edns_option** opt_list_out, struct edns_data* edns, struct edns_option** opt_list_out,
struct regional* region, int id, void* callback); struct comm_reply* repinfo, struct regional* region, int id,
void* callback);
/** /**
* Inplace callback function called before sending the query to a nameserver. * Inplace callback function called before sending the query to a nameserver.
* Called as func(qinfo, flags, qstate, addr, addrlen, zone, zonelen, region, * Called as func(qinfo, flags, qstate, addr, addrlen, zone, zonelen, region,
* python_callback) * id, python_callback)
* Where: * Where:
* qinfo: query info. * qinfo: query info.
* flags: flags of the query. * flags: flags of the query.
@ -270,6 +275,7 @@ typedef int inplace_cb_reply_func_type(struct query_info* qinfo,
* authoritative. * authoritative.
* zonelen: length of zone. * zonelen: length of zone.
* region: region to store data. * region: region to store data.
* id: module id.
* python_callback: only used for registering a python callback function. * python_callback: only used for registering a python callback function.
*/ */
typedef int inplace_cb_query_func_type(struct query_info* qinfo, uint16_t flags, 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. * Inplace callback function called after parsing edns on query reply.
* Called as func(qstate, cb_args) * Called as func(qstate, id, cb_args)
* Where: * Where:
* qstate: the query state * qstate: the query state.
* id: module id * id: module id.
* cb_args: argument passed when registering callback. * cb_args: argument passed when registering callback.
*/ */
typedef int inplace_cb_edns_back_parsed_func_type(struct module_qstate* qstate, 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. * Inplace callback function called after parsing query response.
* Called as func(qstate, id, cb_args) * Called as func(qstate, response, id, cb_args)
* Where: * Where:
* qstate: the query state * qstate: the query state.
* response: query response * response: query response.
* id: module id * id: module id.
* cb_args: argument passed when registering callback. * cb_args: argument passed when registering callback.
*/ */
typedef int inplace_cb_query_response_func_type(struct module_qstate* qstate, typedef int inplace_cb_query_response_func_type(struct module_qstate* qstate,