+15 October 2020: George
+ - Fix that if there are reply callbacks for the given rcode, those
+ are called per reply and a new message created if that was modified
+ by the call.
+ - Pass the comm_reply information to the inplace_cb_reply* functions
+ during the mesh state and update the documentation on that.
+
15 October 2020: Wouter
- Merge PR #326 from netblue30: DoH: implement content-length
header field
: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.
: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.
: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.
: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.
Inplace callbacks
-----------------
-.. function:: inplace_cb_reply(qinfo, qstate, rep, rcode, edns, opt_list_out, region)
+.. function:: inplace_cb_reply(qinfo, qstate, rep, rcode, edns, opt_list_out, region, \*\*kwargs)
Function prototype for callback functions used in
`register_inplace_cb_reply`_, `register_inplace_cb_reply_cache`_,
:param edns: :class:`edns_data`
:param opt_list_out: :class:`edns_option`. EDNS option list to append options to.
:param region: :class:`regional`
+ :param \*\*kwargs: Dictionary that may contain parameters added in a future
+ release. Current parameters:
+ ``repinfo``: :class:`comm_reply`. Reply information for a communication point.
.. function:: inplace_cb_query(qinfo, flags, qstate, addr, zone, region)
# 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
+# Unbound will also log the source address of the client that made
# the request.
# (unbound needs to be validating for this example to work)
: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.
: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.
: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.
: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).
+ and log the IP address of the client.
"""
log_info("python: called back while servfail.")
b = bytearray.fromhex("")
edns_opt_list_append(opt_list_out, 65003, b, region)
- # Log the client(s) IP address(es)
+ # Log the client's IP address
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
r->h2_stream->mesh_state = NULL;
}
/* send the reply */
- /* We don't reuse the encoded answer if either the previous or current
- * response has a local alias. We could compare the alias records
- * and still reuse the previous answer if they are the same, but that
- * would be complicated and error prone for the relatively minor case.
- * So we err on the side of safety. */
- if(prev && prev_buffer && prev->qflags == r->qflags &&
+ /* We don't reuse the encoded answer if:
+ * - either the previous or current response has a local alias. We could
+ * compare the alias records and still reuse the previous answer if they
+ * are the same, but that would be complicated and error prone for the
+ * relatively minor case. So we err on the side of safety.
+ * - there are registered callback functions for the given rcode, as these
+ * need to be called for each reply. */
+ if(((rcode != LDNS_RCODE_SERVFAIL &&
+ !m->s.env->inplace_cb_lists[inplace_cb_reply]) ||
+ (rcode == LDNS_RCODE_SERVFAIL &&
+ !m->s.env->inplace_cb_lists[inplace_cb_reply_servfail])) &&
+ prev && prev_buffer && prev->qflags == r->qflags &&
!prev->local_alias && !r->local_alias &&
- prev->edns.edns_present == r->edns.edns_present &&
- prev->edns.bits == r->edns.bits &&
+ prev->edns.edns_present == r->edns.edns_present &&
+ prev->edns.bits == r->edns.bits &&
prev->edns.udp_size == r->edns.udp_size &&
edns_opt_list_compare(prev->edns.opt_list, r->edns.opt_list)
- == 0 && !m->s.env->inplace_cb_lists[inplace_cb_reply]) {
+ == 0) {
/* if the previous reply is identical to this one, fix ID */
if(prev_buffer != r_buffer)
sldns_buffer_copy(r_buffer, prev_buffer);
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, NULL, m->s.region))
+ rep, rcode, &r->edns, &r->query_reply, 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, NULL, m->s.region))
+ &r->edns, &r->query_reply, m->s.region))
r->edns.opt_list = NULL;
}
error_encode(r_buffer, rcode, &m->s.qinfo, r->qid,
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, NULL, m->s.region) ||
+ LDNS_RCODE_NOERROR, &r->edns, &r->query_reply, m->s.region) ||
!apply_edns_options(&r->edns, &edns_bak,
m->s.env->cfg, r->query_reply.c,
m->s.region) ||
secure))
{
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
- rep, LDNS_RCODE_SERVFAIL, &r->edns, NULL, m->s.region))
+ rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region))
r->edns.opt_list = NULL;
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
&m->s.qinfo, r->qid, r->qflags, &r->edns);
* @param rep: Reply info. Could be NULL.
* @param rcode: return code.
* @param edns: edns data of the reply.
- * @param repinfo: comm_reply. 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).
*/