#include <ns/interfacemgr.h>
#include <ns/log.h>
#include <ns/notify.h>
-#include <ns/query.h>
#include <ns/server.h>
#include <ns/stats.h>
#include <ns/update.h>
* fetch_callback(), but if we're shutting down and canceling then
* it might not have happened.
*/
- if (client->recursionquota != NULL) {
- isc_quota_detach(&client->recursionquota);
- if (FETCH_RECTYPE_PREFETCH(client) == NULL) {
+ for (int i = 0; i < RECTYPE_COUNT; i++) {
+ if (client->query.recursions[i].quota != NULL) {
+ isc_quota_detach(&client->query.recursions[i].quota);
ns_stats_decrement(client->manager->sctx->nsstats,
ns_statscounter_recursclients);
}
}
client->state = NS_CLIENTSTATE_READY;
- INSIST(client->recursionquota == NULL);
+ for (int i = 0; i < RECTYPE_COUNT; i++) {
+ INSIST(client->query.recursions[i].quota == NULL);
+ }
#ifdef WANT_SINGLETRACE
isc_log_setforcelog(false);
client->attributes |= NS_CLIENTATTR_TCP;
}
- INSIST(client->recursionquota == NULL);
+ for (int i = 0; i < RECTYPE_COUNT; i++) {
+ INSIST(client->query.recursions[i].quota == NULL);
+ }
INSIST(client->state == NS_CLIENTSTATE_READY);
#define FETCH_RECTYPE_HOOK(client) \
((client)->query.recursions[RECTYPE_HOOK].fetch)
+/*%
+ * Helper macros for accessing isc_quota_t pointers for a specific recursion a
+ * given client is associated with.
+ */
+#define QUOTA_RECTYPE_NORMAL(client) \
+ ((client)->query.recursions[RECTYPE_NORMAL].quota)
+#define QUOTA_RECTYPE_PREFETCH(client) \
+ ((client)->query.recursions[RECTYPE_PREFETCH].quota)
+#define QUOTA_RECTYPE_RPZ(client) \
+ ((client)->query.recursions[RECTYPE_RPZ].quota)
+#define QUOTA_RECTYPE_HOOK(client) \
+ ((client)->query.recursions[RECTYPE_HOOK].quota)
+
/*%
* nameserver recursion parameters, to uniquely identify a recursion
* query; this is used to detect a recursion loop
struct {
isc_nmhandle_t *handle;
dns_fetch_t *fetch;
+ isc_quota_t *quota;
} recursions[RECTYPE_COUNT];
ns_query_recparam_t recparam;
}
static isc_result_t
-recursionquota_attach(ns_client_t *client, bool soft_limit) {
+recursionquotatype_attach(ns_client_t *client,
+ ns_query_rectype_t recursion_type, bool soft_limit) {
+ isc_quota_t **quotap = &client->query.recursions[recursion_type].quota;
isc_result_t result;
- if (client->recursionquota != NULL) {
+ if (*quotap != NULL) {
return (ISC_R_SUCCESS);
}
result = isc_quota_attach(&client->manager->sctx->recursionquota,
- &client->recursionquota);
+ quotap);
switch (result) {
case ISC_R_SUCCESS:
break;
break;
}
- isc_quota_detach(&client->recursionquota);
+ isc_quota_detach(quotap);
FALLTHROUGH;
default:
return (result);
}
static isc_result_t
-recursionquota_attach_hard(ns_client_t *client) {
- return (recursionquota_attach(client, false));
+recursionquotatype_attach_hard(ns_client_t *client,
+ ns_query_rectype_t recursion_type) {
+ return (recursionquotatype_attach(client, recursion_type, false));
}
static isc_result_t
-recursionquota_attach_soft(ns_client_t *client) {
- return (recursionquota_attach(client, true));
+recursionquotatype_attach_soft(ns_client_t *client,
+ ns_query_rectype_t recursion_type) {
+ return (recursionquotatype_attach(client, recursion_type, true));
}
static void
-recursionquota_detach(ns_client_t *client) {
- if (client->recursionquota != NULL) {
- isc_quota_detach(&client->recursionquota);
+recursionquotatype_detach(ns_client_t *client,
+ ns_query_rectype_t recursion_type) {
+ if (client->query.recursions[recursion_type].quota != NULL) {
+ isc_quota_detach(
+ &client->query.recursions[recursion_type].quota);
}
ns_stats_decrement(client->manager->sctx->nsstats,
}
UNLOCK(&client->query.fetchlock);
- recursionquota_detach(client);
+ recursionquotatype_detach(client, recursion_type);
free_devent(client, &event, &devent);
isc_nmhandle_detach(handlep);
dns_fetch_t **fetchp;
isc_result_t result;
- result = recursionquota_attach_hard(client);
+ result = recursionquotatype_attach_hard(client, recursion_type);
if (result != ISC_R_SUCCESS) {
return;
}
* the manager's recursing-clients list.
*/
- recursionquota_detach(client);
+ recursionquotatype_detach(client, RECTYPE_NORMAL);
LOCK(&client->manager->reclock);
if (ISC_LINK_LINKED(client, rlink)) {
* Check recursion quota before making the current client "recursing".
*/
static isc_result_t
-check_recursionquota(ns_client_t *client) {
+check_recursionquota(ns_client_t *client, ns_query_rectype_t recursion_type) {
+ isc_quota_t **quotap = &client->query.recursions[recursion_type].quota;
isc_result_t result = ISC_R_SUCCESS;
/*
* because those have already been replaced when the
* connection was accepted (if allowed by the TCP quota).
*/
- if (client->recursionquota == NULL) {
- result = recursionquota_attach_soft(client);
+ if (*quotap == NULL) {
+ result = recursionquotatype_attach_soft(client, recursion_type);
if (result == ISC_R_SOFTQUOTA) {
isc_stdtime_t now;
isc_stdtime_get(&now);
"recursive-clients soft limit "
"exceeded (%u/%u/%u), "
"aborting oldest query",
- isc_quota_getused(
- client->recursionquota),
- isc_quota_getsoft(
- client->recursionquota),
- isc_quota_getmax(
- client->recursionquota));
+ isc_quota_getused(*quotap),
+ isc_quota_getsoft(*quotap),
+ isc_quota_getmax(*quotap));
}
ns_client_killoldestquery(client);
result = ISC_R_SUCCESS;
inc_stats(client, ns_statscounter_recursion);
}
- result = check_recursionquota(client);
+ result = check_recursionquota(client, RECTYPE_NORMAL);
if (result != ISC_R_SUCCESS) {
return (result);
}
UNLOCK(&client->query.fetchlock);
SAVE(hctx, rev->ctx);
- recursionquota_detach(client);
+ recursionquotatype_detach(client, RECTYPE_HOOK);
LOCK(&client->manager->reclock);
if (ISC_LINK_LINKED(client, rlink)) {
REQUIRE(client->query.hookactx == NULL);
REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL);
- result = check_recursionquota(client);
+ result = check_recursionquota(client, RECTYPE_HOOK);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}