accurate ratelimit calculation.
struct outbound_entry*
worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
- int want_dnssec, int nocaps, 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 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 worker* worker = q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
return NULL;
e->qstate = q;
e->qsent = outnet_serviced_query(worker->back, qinfo, flags, dnssec,
- want_dnssec, nocaps, tcp_upstream,
+ 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);
+ worker_handle_service_reply, e, worker->back->udp_buff, q->env,
+ was_ratelimited);
if(!e->qsent) {
return NULL;
}
struct query_info* ATTR_UNUSED(qinfo),
uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec),
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
+ int ATTR_UNUSED(check_ratelimit),
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))
+ struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
{
log_assert(0);
return 0;
struct outbound_entry* worker_send_query(
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit),
+ 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))
+ struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
{
log_assert(0);
return 0;
struct outbound_entry* libworker_send_query(
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit),
+ 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))
+ struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
{
log_assert(0);
return 0;
the nameservers for it, the zone name is used to keep track of the rate.
For example, 1000 may be a suitable value to stop the server from being
overloaded with random names, and keeps Unbound from sending traffic to the
-nameservers for those zones.
+nameservers for those zones. Configured forwarders are excluded from
+ratelimiting.
.TP 5
.B ratelimit\-size: \fI<memory size>
Give the size of the data structure in which the current ongoing rates are
if(!iq->ratelimit_ok && qstate->prefetch_leeway)
iq->ratelimit_ok = 1; /* allow prefetches, this keeps
otherwise valid data in the cache */
- if(!iq->ratelimit_ok && infra_ratelimit_exceeded(
- qstate->env->infra_cache, iq->dp->name,
- iq->dp->namelen, *qstate->env->now)) {
- /* and increment the rate, so that the rate for time
- * now will also exceed the rate, keeping cache fresh */
- (void)infra_ratelimit_inc(qstate->env->infra_cache,
- iq->dp->name, iq->dp->namelen,
- *qstate->env->now, &qstate->qinfo,
- qstate->reply);
- /* see if we are passed through with slip factor */
- if(qstate->env->cfg->ratelimit_factor != 0 &&
- ub_random_max(qstate->env->rnd,
- qstate->env->cfg->ratelimit_factor) == 1) {
- iq->ratelimit_ok = 1;
- log_nametypeclass(VERB_ALGO, "ratelimit allowed through for "
- "delegation point", iq->dp->name,
- LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
- } else {
- lock_basic_lock(&ie->queries_ratelimit_lock);
- ie->num_queries_ratelimited++;
- lock_basic_unlock(&ie->queries_ratelimit_lock);
- log_nametypeclass(VERB_ALGO, "ratelimit exceeded with "
- "delegation point", iq->dp->name,
- LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
- qstate->was_ratelimited = 1;
- errinf(qstate, "query was ratelimited");
- errinf_dname(qstate, "for zone", iq->dp->name);
- return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
- }
- }
/* see if this dp not useless.
* It is useless if:
int auth_fallback = 0;
uint8_t* qout_orig = NULL;
size_t qout_orig_len = 0;
+ int sq_check_ratelimit = 1;
+ int sq_was_ratelimited = 0;
- /* NOTE: a request will encounter this state for each target it
- * needs to send a query to. That is, at least one per referral,
+ /* NOTE: a request will encounter this state for each target it
+ * needs to send a query to. That is, at least one per referral,
* more if some targets timeout or return throwaway answers. */
log_query_info(VERB_QUERY, "processQueryTargets:", &qstate->qinfo);
return 0;
}
- /* if not forwarding, check ratelimits per delegationpoint name */
- if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok) {
- if(!infra_ratelimit_inc(qstate->env->infra_cache, iq->dp->name,
- iq->dp->namelen, *qstate->env->now, &qstate->qinfo,
- qstate->reply)) {
- lock_basic_lock(&ie->queries_ratelimit_lock);
- ie->num_queries_ratelimited++;
- lock_basic_unlock(&ie->queries_ratelimit_lock);
- verbose(VERB_ALGO, "query exceeded ratelimits");
- qstate->was_ratelimited = 1;
- errinf_dname(qstate, "exceeded ratelimit for zone",
- iq->dp->name);
- return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
- }
- }
-
+ /* 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);
/* We have a valid target. */
if(verbosity >= VERB_QUERY) {
log_query_info(VERB_QUERY, "sending query:", &iq->qinfo_out);
}
fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query));
outq = (*qstate->env->send_query)(&iq->qinfo_out,
- iq->chase_flags | (iq->chase_to_rd?BIT_RD:0),
+ iq->chase_flags | (iq->chase_to_rd?BIT_RD:0),
/* unset CD if to forwarder(RD set) and not dnssec retry
* (blacklist nonempty) and no trust-anchors are configured
* above the qname or on the first attempt when dnssec is on */
EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
!qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env,
- &iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
+ &iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
- ie, iq), &target->addr, target->addrlen,
+ ie, iq), sq_check_ratelimit, &target->addr, target->addrlen,
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);
+ target->tls_auth_name, qstate, &sq_was_ratelimited);
if(!outq) {
+ if(sq_was_ratelimited) {
+ lock_basic_lock(&ie->queries_ratelimit_lock);
+ ie->num_queries_ratelimited++;
+ lock_basic_unlock(&ie->queries_ratelimit_lock);
+ verbose(VERB_ALGO, "query exceeded ratelimits");
+ qstate->was_ratelimited = 1;
+ errinf_dname(qstate, "exceeded ratelimit for zone",
+ iq->dp->name);
+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ }
log_addr(VERB_QUERY, "error sending query to auth server",
&target->addr, target->addrlen);
- if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok)
- infra_ratelimit_dec(qstate->env->infra_cache, iq->dp->name,
- iq->dp->namelen, *qstate->env->now);
if(qstate->env->cfg->qname_minimisation)
iq->minimisation_state = SKIP_MINIMISE_STATE;
return next_state(iq, QUERYTARGETS_STATE);
* delegation point, and back to the QUERYTARGETS_STATE. */
verbose(VERB_DETAIL, "query response was REFERRAL");
- if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok) {
- /* we have a referral, no ratelimit, we can send
- * our queries to the given name */
- infra_ratelimit_dec(qstate->env->infra_cache,
- iq->dp->name, iq->dp->namelen,
- *qstate->env->now);
- }
-
/* if hardened, only store referral if we asked for it */
if(!qstate->no_cache_store &&
(!qstate->env->cfg->harden_referral_path ||
/**
* number of labels from QNAME that are always send individually when using
* QNAME minimisation, even when the number of labels of the QNAME is bigger
- * tham MAX_MINIMISE_COUNT */
+ * than MAX_MINIMISE_COUNT */
#define MINIMISE_ONE_LAB 4
#define MINIMISE_MULTIPLE_LABS (MAX_MINIMISE_COUNT - MINIMISE_ONE_LAB)
/** at what query-sent-count to stop target fetch policy */
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
uint16_t flags, int dnssec, 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)
+ struct module_qstate* q, int* was_ratelimited)
{
struct libworker* w = (struct libworker*)q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
return NULL;
e->qstate = q;
e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec,
- want_dnssec, nocaps, tcp_upstream, ssl_upstream,
+ 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);
+ libworker_handle_service_reply, e, w->back->udp_buff, q->env,
+ was_ratelimited);
if(!e->qsent) {
return NULL;
}
struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo),
uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec),
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
+ int ATTR_UNUSED(check_ratelimit),
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))
+ struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
{
log_assert(0);
return 0;
* @param dnssec: if set, EDNS record will have DO bit set.
* @param want_dnssec: signatures needed.
* @param nocaps: ignore capsforid(if in config), do not perturb qname.
+ * @param check_ratelimit: if set, will check ratelimit before sending out.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: delegation point name.
* @param tls_auth_name: if ssl_upstream, use this name with TLS
* authentication.
* @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.
* @return: false on failure (memory or socket related). no query was
* sent.
*/
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
uint16_t flags, int dnssec, 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);
+ struct module_qstate* q, int* was_ratelimited);
/** process incoming serviced query replies from the network */
int libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
* @param dnssec: if set, EDNS record will have DO bit set.
* @param want_dnssec: signatures needed.
* @param nocaps: ignore capsforid(if in config), do not perturb qname.
+ * @param check_ratelimit: if set, will check ratelimit before sending out.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: wireformat dname of the zone.
* @param tls_auth_name: if ssl_upstream, use this name with TLS
* authentication.
* @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.
* @return: false on failure (memory or socket related). no query was
* sent.
*/
struct outbound_entry* worker_send_query(struct query_info* qinfo,
uint16_t flags, int dnssec, 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);
+ struct module_qstate* q, int* was_ratelimited);
/**
* process control messages from the main thread. Frees the control
/* --- services --- */
struct outbound_entry* (*send_query)(struct query_info* qinfo,
uint16_t flags, int dnssec, 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);
+ char* tls_auth_name, struct module_qstate* q, int* was_ratelimited);
void (*detach_subs)(struct module_qstate* qstate);
int (*attach_sub)(struct module_qstate* qstate,
struct query_info* qinfo, uint16_t qflags, int prime,
slabhash_insert(infra->client_ip_rates, h, &k->entry, d, NULL);
}
-/** find the second and return its rate counter, if none, remove oldest */
-static int* infra_rate_find_second(void* data, time_t t)
+/** Find the second and return its rate counter. If none and should_add, remove
+ * oldest to accommodate. Else return none. */
+static int* infra_rate_find_second_or_none(void* data, time_t t, int should_add)
{
struct rate_data* d = (struct rate_data*)data;
int i, oldest;
if(d->timestamp[i] == t)
return &(d->qps[i]);
}
+ if(!should_add) return NULL;
/* remove oldest timestamp, and insert it at t with 0 qps */
oldest = 0;
for(i=0; i<RATE_WINDOW; i++) {
return &(d->qps[oldest]);
}
+/** find the second and return its rate counter, if none, remove oldest to
+ * accommodate */
+static int* infra_rate_give_second(void* data, time_t t)
+{
+ return infra_rate_find_second_or_none(data, t, 1);
+}
+
+/** find the second and return its rate counter only if it exists. Caller
+ * should check for NULL return value */
+static int* infra_rate_get_second(void* data, time_t t)
+{
+ return infra_rate_find_second_or_none(data, t, 0);
+}
+
int infra_rate_max(void* data, time_t now)
{
struct rate_data* d = (struct rate_data*)data;
int i, max = 0;
for(i=0; i<RATE_WINDOW; i++) {
- if(now-d->timestamp[i] <= RATE_WINDOW) {
- if(d->qps[i] > max)
- max = d->qps[i];
+ if(now == d->timestamp[i]) {
+ return d->qps[i];
}
}
return max;
entry = infra_find_ratedata(infra, name, namelen, 1);
if(entry) {
int premax = infra_rate_max(entry->data, timenow);
- int* cur = infra_rate_find_second(entry->data, timenow);
+ int* cur = infra_rate_give_second(entry->data, timenow);
(*cur)++;
max = infra_rate_max(entry->data, timenow);
lock_rw_unlock(&entry->lock);
- if(premax < lim && max >= lim) {
+ if(premax <= lim && max > lim) {
char buf[257], qnm[257], ts[12], cs[12], ip[128];
dname_str(name, buf);
dname_str(qinfo->qname, qnm);
verbose(VERB_OPS, "ratelimit exceeded %s %d query %s %s %s", buf, lim, qnm, cs, ts);
}
}
- return (max < lim);
+ return (max <= lim);
}
/* create */
infra_create_ratedata(infra, name, namelen, timenow);
- return (1 < lim);
+ return (1 <= lim);
}
void infra_ratelimit_dec(struct infra_cache* infra, uint8_t* name,
return; /* not enabled */
entry = infra_find_ratedata(infra, name, namelen, 1);
if(!entry) return; /* not cached */
- cur = infra_rate_find_second(entry->data, timenow);
+ cur = infra_rate_get_second(entry->data, timenow);
+ if(cur == NULL) {
+ /* our timenow is not available anymore; nothing to decrease */
+ lock_rw_unlock(&entry->lock);
+ return;
+ }
if((*cur) > 0)
(*cur)--;
lock_rw_unlock(&entry->lock);
}
int infra_ip_ratelimit_inc(struct infra_cache* infra,
- struct comm_reply* repinfo, time_t timenow, struct sldns_buffer* buffer)
+ struct comm_reply* repinfo, time_t timenow, struct sldns_buffer* buffer)
{
int max;
struct lruhash_entry* entry;
entry = infra_find_ip_ratedata(infra, repinfo, 1);
if(entry) {
int premax = infra_rate_max(entry->data, timenow);
- int* cur = infra_rate_find_second(entry->data, timenow);
+ int* cur = infra_rate_give_second(entry->data, timenow);
(*cur)++;
max = infra_rate_max(entry->data, timenow);
lock_rw_unlock(&entry->lock);
int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
size_t namelen, time_t timenow);
-/** find the maximum rate stored, not too old. 0 if no information. */
+/** find the maximum rate stored. 0 if no information. */
int infra_rate_max(void* data, time_t now);
/** find the ratelimit in qps for a domain. 0 if no limit for domain. */
struct serviced_query*
outnet_serviced_query(struct outside_network* outnet,
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
- int nocaps, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
- struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, struct module_qstate* qstate,
+ int nocaps, int check_ratelimit, int tcp_upstream, int ssl_upstream,
+ 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)
+ sldns_buffer* buff, struct module_env* env, int* was_ratelimited)
{
struct serviced_query* sq;
struct service_callback* cb;
struct regional* region;
struct edns_option* backed_up_opt_list = qstate->edns_opts_back_out;
struct edns_option* per_upstream_opt_list = NULL;
+ time_t timenow = 0;
/* If we have an already populated EDNS option list make a copy since
* we may now add upstream specific EDNS options. */
sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen,
per_upstream_opt_list);
if(!sq) {
+ /* Check ratelimit only for new serviced_query */
+ if(check_ratelimit) {
+ timenow = *env->now;
+ if(!infra_ratelimit_inc(env->infra_cache, zone,
+ zonelen, timenow, &qstate->qinfo,
+ qstate->reply)) {
+ /* Can we pass through with slip factor? */
+ if(env->cfg->ratelimit_factor == 0 ||
+ ub_random_max(env->rnd,
+ env->cfg->ratelimit_factor) != 1) {
+ *was_ratelimited = 1;
+ alloc_reg_release(env->alloc, region);
+ return NULL;
+ }
+ log_nametypeclass(VERB_ALGO,
+ "ratelimit allowed through for "
+ "delegation point", zone,
+ LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
+ }
+ }
/* make new serviced query entry */
sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps,
tcp_upstream, ssl_upstream, tls_auth_name, addr,
? env->cfg->pad_queries_block_size : 0 ),
env->alloc, region);
if(!sq) {
+ if(check_ratelimit) {
+ infra_ratelimit_dec(env->infra_cache,
+ zone, zonelen, timenow);
+ }
alloc_reg_release(env->alloc, region);
return NULL;
}
if(!(cb = (struct service_callback*)regional_alloc(
sq->region, sizeof(*cb)))) {
+ if(check_ratelimit) {
+ infra_ratelimit_dec(env->infra_cache,
+ zone, zonelen, timenow);
+ }
(void)rbtree_delete(outnet->serviced, sq);
serviced_node_del(&sq->node, NULL);
return NULL;
* @param want_dnssec: signatures are needed, without EDNS the answer is
* likely to be useless.
* @param nocaps: ignore use_caps_for_id and use unperturbed qname.
+ * @param check_ratelimit: if set, will check ratelimit before sending out.
* @param tcp_upstream: use TCP for upstream queries.
* @param ssl_upstream: use SSL for upstream queries.
* @param tls_auth_name: when ssl_upstream is true, use this name to check
* @param callback_arg: user argument to callback function.
* @param buff: scratch buffer to create query contents in. Empty on exit.
* @param env: the module environment.
+ * @param was_ratelimited: it will signal back if the query failed to pass the
+ * ratelimit check.
* @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.
*/
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
- int nocaps, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
- struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, struct module_qstate* qstate,
+ int nocaps, int check_ratelimit, int tcp_upstream, int ssl_upstream,
+ 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);
+ struct sldns_buffer* buff, struct module_env* env, int* was_ratelimited);
/**
* Remove service query callback.
struct outbound_entry* worker_send_query(
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit),
+ 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))
+ char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q),
+ int* ATTR_UNUSED(was_ratelimited))
{
log_assert(0);
return 0;
struct outbound_entry* libworker_send_query(
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit),
+ 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))
+ char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q),
+ int* ATTR_UNUSED(was_ratelimited))
{
log_assert(0);
return 0;
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
struct query_info* qinfo, uint16_t flags, int dnssec,
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
+ int ATTR_UNUSED(check_ratelimit),
int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
char* ATTR_UNUSED(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* ATTR_UNUSED(buff),
- struct module_env* env)
+ struct module_env* env, int* ATTR_UNUSED(was_ratelimited))
{
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
struct fake_pending* pend = (struct fake_pending*)calloc(1,
int
fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
- int nocaps, 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 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))
{
if(fptr == &worker_send_query) return 1;
else if(fptr == &libworker_send_query) return 1;
*/
int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
- int nocaps, 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 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));
/**
* Check function pointer whitelist for module_env detach_subs callback values.
* EDNS, the answer is likely to be useless for this domain.
* @param nocaps: do not use caps_for_id, use the qname as given.
* (ignored if caps_for_id is disabled).
+ * @param check_ratelimit: if set, will check ratelimit before sending out.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: delegation point name.
* @param tls_auth_name: if ssl_upstream, use this name with TLS
* authentication.
* @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.
* @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
*/
struct outbound_entry* (*send_query)(struct query_info* qinfo,
uint16_t flags, int dnssec, 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);
+ char* tls_auth_name, struct module_qstate* q, int* was_ratelimited);
/**
* Detach-subqueries.