mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
- 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.
This commit is contained in:
+2
-1
@@ -7612,7 +7612,8 @@ auth_zone_zonemd_stop_lookup(struct auth_zone* z, struct mesh_area* mesh)
|
||||
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. */
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
- 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
|
||||
|
||||
@@ -167,6 +167,8 @@ struct ctx_query {
|
||||
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;
|
||||
|
||||
@@ -642,7 +642,8 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
@@ -723,7 +724,8 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
|
||||
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;
|
||||
}
|
||||
@@ -861,7 +863,8 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
||||
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);
|
||||
|
||||
+6
-3
@@ -5558,7 +5558,8 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
||||
* 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;
|
||||
@@ -6804,7 +6805,8 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
||||
* 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;
|
||||
@@ -8640,7 +8642,8 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
|
||||
/* 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"));
|
||||
|
||||
@@ -144,6 +144,8 @@ struct auth_zone {
|
||||
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 */
|
||||
@@ -344,6 +346,8 @@ struct auth_probe {
|
||||
|
||||
/** 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),
|
||||
@@ -402,6 +406,8 @@ struct auth_transfer {
|
||||
|
||||
/** 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;
|
||||
|
||||
|
||||
+43
-4
@@ -662,7 +662,8 @@ servfail_mem:
|
||||
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);
|
||||
@@ -751,6 +752,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
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;
|
||||
@@ -1969,6 +1972,25 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
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)
|
||||
{
|
||||
@@ -2700,13 +2722,30 @@ int mesh_jostle_exceeded(struct mesh_area* mesh)
|
||||
}
|
||||
|
||||
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--;
|
||||
|
||||
+23
-2
@@ -342,11 +342,14 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
* @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.
|
||||
@@ -543,6 +546,23 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
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.
|
||||
@@ -736,8 +756,9 @@ void mesh_respond_serve_expired(struct mesh_state* mstate);
|
||||
* @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 */
|
||||
|
||||
@@ -2431,7 +2431,7 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp)
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user