qinfo.local_alias = NULL;
mesh_remove_callback(mesh, &qinfo, qflags,
- &auth_zonemd_dnskey_lookup_callback, z);
+ &auth_zonemd_dnskey_lookup_callback, z,
+ z->zonemd_callback_unique_info);
}
/** Pick up the auth zone locks. */
- Fix that misconfigured `iter-scrub-ns: 0` causes request
failures. Thanks to Qifan Zhang, Palo Alto Networks,
for the report.
+ - Fix that fast_reload when a zonemd verification lookup
+ it in progress with subnet loaded, deregisters the
+ callback. Thanks to Qifan Zhang, Palo Alto Networks,
+ for the report.
12 June 2026: Wouter
- Fix that for auth-zone and rpz zones the allow-notify
ub_event_callback_type cb_event;
/** for async query, the callback user arg */
void* cb_arg;
+ /** for async query the unique info */
+ void* unique_info;
/** answer message, result from resolver lookup. */
uint8_t* msg;
}
/* process new query */
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
- w->back->udp_buff, qid, libworker_fg_done_cb, q, 0)) {
+ w->back->udp_buff, qid, libworker_fg_done_cb, q, 0,
+ &q->unique_info)) {
free(qinfo.qname);
return UB_NOMEM;
}
if(async_id)
*async_id = q->querynum;
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
- w->back->udp_buff, qid, libworker_event_done_cb, q, 0)) {
+ w->back->udp_buff, qid, libworker_event_done_cb, q, 0,
+ &q->unique_info)) {
free(qinfo.qname);
return UB_NOMEM;
}
q->w = w;
/* process new query */
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
- w->back->udp_buff, qid, libworker_bg_done_cb, q, 0)) {
+ w->back->udp_buff, qid, libworker_bg_done_cb, q, 0,
+ &q->unique_info)) {
add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0);
}
free(qinfo.qname);
* called straight away */
lock_basic_unlock(&xfr->lock);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
- &auth_xfer_transfer_lookup_callback, xfr, 0)) {
+ &auth_xfer_transfer_lookup_callback, xfr, 0,
+ &xfr->task_transfer->lookup_unique_info)) {
lock_basic_lock(&xfr->lock);
log_err("out of memory lookup up master %s", master->host);
return 0;
* called straight away */
lock_basic_unlock(&xfr->lock);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
- &auth_xfer_probe_lookup_callback, xfr, 0)) {
+ &auth_xfer_probe_lookup_callback, xfr, 0,
+ &xfr->task_probe->lookup_unique_info)) {
lock_basic_lock(&xfr->lock);
log_err("out of memory lookup up master %s", master->host);
return 0;
/* the callback can be called straight away */
lock_rw_unlock(&z->lock);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
- &auth_zonemd_dnskey_lookup_callback, z, 0)) {
+ &auth_zonemd_dnskey_lookup_callback, z, 0,
+ &z->zonemd_callback_unique_info)) {
lock_rw_wrlock(&z->lock);
log_err("out of memory lookup of %s for zonemd",
(fetch_ds?"DS":"DNSKEY"));
struct module_env* zonemd_callback_env;
/** for the zonemd callback, the type of data looked up */
uint16_t zonemd_callback_qtype;
+ /** for the zonemd callback, the unique info */
+ void* zonemd_callback_unique_info;
/** zone has been deleted */
int zone_deleted;
/** deletelist pointer, unused normally except during delete */
/** for the hostname lookups, which master is current */
struct auth_master* lookup_target;
+ /** for the lookup, the callback unique info */
+ void* lookup_unique_info;
/** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
int lookup_aaaa;
/** we only want to do lookups for making config work (for notify),
/** for the hostname lookups, which master is current */
struct auth_master* lookup_target;
+ /** for the lookup, the callback unique info */
+ void* lookup_unique_info;
/** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
int lookup_aaaa;
int
mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
- uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru)
+ uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru,
+ void** unique_info)
{
struct mesh_state* s = NULL;
int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
mesh->num_reply_states ++;
}
mesh->num_reply_addrs++;
+ if(unique_info)
+ *unique_info = s->unique;
if(added)
mesh_run(mesh, s, module_event_new, NULL);
return 1;
return result;
}
+struct mesh_state* mesh_area_find_unique(struct mesh_area* mesh,
+ struct respip_client_info* cinfo, struct query_info* qinfo,
+ uint16_t qflags, int prime, int valrec, void* unique_info)
+{
+ struct mesh_state key;
+ struct mesh_state* result;
+
+ key.node.key = &key;
+ key.s.is_priming = prime;
+ key.s.is_valrec = valrec;
+ key.s.qinfo = *qinfo;
+ key.s.query_flags = qflags;
+ key.unique = (struct mesh_state*)unique_info;
+ key.s.client_info = cinfo;
+
+ result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
+ return result;
+}
+
/** remove mesh state callback */
int mesh_state_del_cb(struct mesh_state* s, mesh_cb_func_type cb, void* cb_arg)
{
}
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
- uint16_t qflags, mesh_cb_func_type cb, void* cb_arg)
+ uint16_t qflags, mesh_cb_func_type cb, void* cb_arg, void* unique_info)
{
struct mesh_state* s = NULL;
s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
- if(!s) return;
- if(!mesh_state_del_cb(s, cb, cb_arg)) return;
+ if(s && mesh_state_del_cb(s, cb, cb_arg))
+ goto removed;
+ if(unique_info) {
+ s = mesh_area_find_unique(mesh, NULL, qinfo,
+ qflags&(BIT_RD|BIT_CD), 0, 0, unique_info);
+ if(s && mesh_state_del_cb(s, cb, cb_arg))
+ goto removed;
+ }
+ /* mesh_area_find builds key.unique=NULL and cannot match a state
+ * created with mesh_state_make_unique (e.g. subnetcache sets
+ * env->unique_mesh). Fall back to a linear scan; cb+cb_arg is an
+ * exact key (mesh_state_del_cb compares both).
+ * This works for both lookups for zonemd and for hostname authzone. */
+ RBTREE_FOR(s, struct mesh_state*, &mesh->all) {
+ if(s->cb_list && mesh_state_del_cb(s, cb, cb_arg))
+ goto removed;
+ }
+ return;
+removed:
/* It was in the list and removed. */
log_assert(mesh->num_reply_addrs > 0);
mesh->num_reply_addrs--;
* @param cb_arg: callback user arg.
* @param rpz_passthru: if true, the rpz passthru was previously found and
* further rpz processing is stopped.
+ * @param unique_info: if nonnull, unique info is passed back to be used
+ * for the callback remove call. It does not need to be deallocated.
* @return 0 on error.
*/
int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, struct sldns_buffer* buf,
- uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru);
+ uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru,
+ void** unique_info);
/**
* New prefetch message. Create new query state if needed.
struct respip_client_info* cinfo, struct query_info* qinfo,
uint16_t qflags, int prime, int valrec);
+/**
+ * Find a unique mesh state in the mesh area. Pass relevant flags.
+ *
+ * @param mesh: the mesh area to look in.
+ * @param cinfo: if non-NULL client specific info that may affect IP-based
+ * actions that apply to the query result.
+ * @param qinfo: what query
+ * @param qflags: if RD / CD bit is set or not.
+ * @param prime: if it is a priming query.
+ * @param valrec: if it is a validation-recursion query.
+ * @param unique_info: the unique info for the state. NULL can be passed.
+ * @return: mesh state or NULL if not found.
+ */
+struct mesh_state* mesh_area_find_unique(struct mesh_area* mesh,
+ struct respip_client_info* cinfo, struct query_info* qinfo,
+ uint16_t qflags, int prime, int valrec, void* unique_info);
+
/**
* Setup attachment super/sub relation between super and sub mesh state.
* The relation must not be present when calling the function.
* @param qflags: flags from client query.
* @param cb: callback function.
* @param cb_arg: callback user arg.
+ * @param unique_info: if not NULL, used to find a unique state for removal.
*/
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
- uint16_t qflags, mesh_cb_func_type cb, void* cb_arg);
+ uint16_t qflags, mesh_cb_func_type cb, void* cb_arg, void* unique_info);
#endif /* SERVICES_MESH_H */
qinfo.qclass);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
- &probe_answer_cb, env, 0)) {
+ &probe_answer_cb, env, 0, NULL)) {
log_err("out of memory making 5011 probe");
}
}