int want_dnssec, int nocaps, int check_ratelimit,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
- struct module_qstate* q, int* was_ratelimited)
+ struct module_qstate* q, int* was_ratelimited,
+ int* ratelimit_incremented)
{
struct worker* worker = q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
want_dnssec, nocaps, check_ratelimit, tcp_upstream,
ssl_upstream, tls_auth_name, addr, addrlen, zone, zonelen, q,
worker_handle_service_reply, e, worker->back->udp_buff, q->env,
- was_ratelimited);
+ was_ratelimited, ratelimit_incremented);
if(!e->qsent) {
return NULL;
}
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
- struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
+ struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
+ int* ATTR_UNUSED(ratelimit_incremented))
{
log_assert(0);
return 0;
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
- struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
+ struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
+ int* ATTR_UNUSED(ratelimit_incremented))
{
log_assert(0);
return 0;
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
- struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
+ struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
+ int* ATTR_UNUSED(ratelimit_incremented))
{
log_assert(0);
return 0;
for the report.
- Fix to limit the DSNS per-label walk in the iterator. Thanks
to Qifan Zhang, Palo Alto Networks, for the report.
+ - Fix that the ratelimit is decremented on successful
+ referrals. Thanks to Qifan Zhang, Palo Alto Networks, for
+ the report.
26 May 2026: Wouter
- Fix for mesh new client and mesh new callback to rollback the
/* Do not check ratelimit for forwarding queries or if we already got a
* pass. */
- sq_check_ratelimit = (!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok);
+ sq_check_ratelimit = ((!(iq->chase_flags & BIT_RD) &&
+ !iq->ratelimit_ok));
+ iq->ratelimit_incremented = 0;
/* We have a valid target. */
if(verbosity >= VERB_QUERY) {
log_query_info(VERB_QUERY, "sending query:", &iq->qinfo_out);
iq->dp->name, iq->dp->namelen,
(iq->dp->tcp_upstream || qstate->env->cfg->tcp_upstream),
(iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream),
- target->tls_auth_name, qstate, &sq_was_ratelimited);
+ target->tls_auth_name, qstate, &sq_was_ratelimited,
+ &iq->ratelimit_incremented);
if(!outq) {
if(sq_was_ratelimited) {
lock_basic_lock(&ie->queries_ratelimit_lock);
iq->deleg_msg = iq->response;
/* Keep current delegation point for label comparison */
old_dp = iq->dp;
+ /* A referral reply is "pleasant", refund the
+ * parent dp's rate charge before descending to the child. */
+ if(iq->ratelimit_incremented)
+ infra_ratelimit_dec(qstate->env->infra_cache,
+ old_dp->name, old_dp->namelen,
+ *qstate->env->now);
iq->dp = delegpt_from_message(iq->response, qstate->region);
if (qstate->env->cfg->qname_minimisation)
iq->minimisation_state = INIT_MINIMISE_STATE;
/** if true, already tested for ratelimiting and passed the test */
int ratelimit_ok;
+ /** If the last query, that may be a referral, incremented the
+ * ratelimit counter. */
+ int ratelimit_incremented;
+
/**
* The query must store NS records from referrals as parentside RRs
* Enabled once it hits resolution problems, to throttle retries.
int check_ratelimit,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
- struct module_qstate* q, int* was_ratelimited)
+ struct module_qstate* q, int* was_ratelimited,
+ int* ratelimit_incremented)
{
struct libworker* w = (struct libworker*)q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
want_dnssec, nocaps, check_ratelimit, tcp_upstream, ssl_upstream,
tls_auth_name, addr, addrlen, zone, zonelen, q,
libworker_handle_service_reply, e, w->back->udp_buff, q->env,
- was_ratelimited);
+ was_ratelimited, ratelimit_incremented);
if(!e->qsent) {
return NULL;
}
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
- struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
+ struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
+ int* ATTR_UNUSED(ratelimit_incremented))
{
log_assert(0);
return 0;
* @param q: which query state to reactivate upon return.
* @param was_ratelimited: it will signal back if the query failed to pass the
* ratelimit check.
+ * @param ratelimit_incremented: set to true if the ratelimit counter
+ * was increased.
* @return: false on failure (memory or socket related). no query was
* sent.
*/
int check_ratelimit,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
- struct module_qstate* q, int* was_ratelimited);
+ struct module_qstate* q, int* was_ratelimited,
+ int* ratelimit_incremented);
/** process incoming serviced query replies from the network */
int libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
* @param q: which query state to reactivate upon return.
* @param was_ratelimited: it will signal back if the query failed to pass the
* ratelimit check.
+ * @param ratelimit_incremented: set to true if the ratelimit counter
+ * was increased.
* @return: false on failure (memory or socket related). no query was
* sent.
*/
int check_ratelimit,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
- struct module_qstate* q, int* was_ratelimited);
+ struct module_qstate* q, int* was_ratelimited,
+ int* ratelimit_incremented);
/**
* process control messages from the main thread. Frees the control
int check_ratelimit,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream,
- char* tls_auth_name, struct module_qstate* q, int* was_ratelimited);
+ char* tls_auth_name, struct module_qstate* q, int* was_ratelimited,
+ int* ratelimit_incremented);
void (*detach_subs)(struct module_qstate* qstate);
int (*attach_sub)(struct module_qstate* qstate,
struct query_info* qinfo, struct respip_client_info* cinfo,
char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
comm_point_callback_type* callback, void* callback_arg,
- sldns_buffer* buff, struct module_env* env, int* was_ratelimited)
+ sldns_buffer* buff, struct module_env* env, int* was_ratelimited,
+ int* ratelimit_incremented)
{
struct serviced_query* sq;
struct service_callback* cb;
"delegation point", zone,
LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
}
+ *ratelimit_incremented = 1;
}
/* make new serviced query entry */
sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps,
* @param env: the module environment.
* @param was_ratelimited: it will signal back if the query failed to pass the
* ratelimit check.
+ * @param ratelimit_incremented: set to true if the ratelimit counter
+ * was increased.
* @return 0 on error, or pointer to serviced query that is used to answer
* this serviced query may be shared with other callbacks as well.
*/
char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
comm_point_callback_type* callback, void* callback_arg,
- struct sldns_buffer* buff, struct module_env* env, int* was_ratelimited);
+ struct sldns_buffer* buff, struct module_env* env, int* was_ratelimited,
+ int* ratelimit_incremented);
/**
* Remove service query callback.
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q),
- int* ATTR_UNUSED(was_ratelimited))
+ int* ATTR_UNUSED(was_ratelimited), int* ATTR_UNUSED(ratelimit_incremented))
{
log_assert(0);
return 0;
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q),
- int* ATTR_UNUSED(was_ratelimited))
+ int* ATTR_UNUSED(was_ratelimited), int* ATTR_UNUSED(ratelimit_incremented))
{
log_assert(0);
return 0;
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
- struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
+ struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
+ int* ATTR_UNUSED(ratelimit_incremented))
{
log_assert(0);
return 0;
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
- struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
+ struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
+ int* ATTR_UNUSED(ratelimit_incremented))
{
log_assert(0);
return 0;
socklen_t addrlen, uint8_t* zone, size_t zonelen,
struct module_qstate* qstate, comm_point_callback_type* callback,
void* callback_arg, sldns_buffer* ATTR_UNUSED(buff),
- struct module_env* env, int* ATTR_UNUSED(was_ratelimited))
+ struct module_env* env, int* ATTR_UNUSED(was_ratelimited),
+ int* ATTR_UNUSED(ratelimit_incremented))
{
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
struct fake_pending* pend = (struct fake_pending*)calloc(1,
int nocaps, int check_ratelimit, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen, int tcp_upstream,
int ssl_upstream, char* tls_auth_name, struct module_qstate* q,
- int* was_ratelimited))
+ int* was_ratelimited, int* ratelimit_incremented))
{
if(fptr == &worker_send_query) return 1;
else if(fptr == &libworker_send_query) return 1;
int nocaps, int check_ratelimit, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen, int tcp_upstream,
int ssl_upstream, char* tls_auth_name, struct module_qstate* q,
- int* was_ratelimited));
+ int* was_ratelimited, int* ratelimit_incremented));
/**
* Check function pointer whitelist for module_env detach_subs callback values.
* @param q: which query state to reactivate upon return.
* @param was_ratelimited: it will signal back if the query failed to pass the
* ratelimit check.
+ * @param ratelimit_incremented: set to true if the ratelimit counter
+ * was increased.
* @return: false on failure (memory or socket related). no query was
* sent. Or returns an outbound entry with qsent and qstate set.
* This outbound_entry will be used on later module invocations
int check_ratelimit,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream,
- char* tls_auth_name, struct module_qstate* q, int* was_ratelimited);
+ char* tls_auth_name, struct module_qstate* q, int* was_ratelimited,
+ int* ratelimit_incremented);
/**
* Detach-subqueries.