Home | History | Annotate | Download | only in dns

Lines Matching refs:rrl

1 /*	$NetBSD: rrl.c,v 1.12 2025/07/17 19:01:45 christos Exp $	*/
39 #include <dns/rrl.h>
44 log_end(dns_rrl_t *rrl, dns_rrl_entry_t *e, bool early, char *log_buf,
143 get_age(const dns_rrl_t *rrl, const dns_rrl_entry_t *e, isc_stdtime_t now) {
147 return delta_rrl_time(e->ts + rrl->ts_bases[e->ts_gen], now);
151 set_age(dns_rrl_t *rrl, dns_rrl_entry_t *e, isc_stdtime_t now) {
156 ts_gen = rrl->ts_gen;
157 ts = now - rrl->ts_bases[ts_gen];
180 for (e_old = ISC_LIST_TAIL(rrl->lru), i = 0;
191 "rrl new time base scanned %d entries"
193 i, now, rrl->ts_bases[ts_gen],
194 rrl->ts_bases[(ts_gen + 1) % DNS_RRL_TS_BASES],
195 rrl->ts_bases[(ts_gen + 2) % DNS_RRL_TS_BASES],
196 rrl->ts_bases[(ts_gen + 3) % DNS_RRL_TS_BASES]);
198 rrl->ts_gen = ts_gen;
199 rrl->ts_bases[ts_gen] = now;
209 expand_entries(dns_rrl_t *rrl, int newsize) {
216 if (rrl->num_entries + newsize >= rrl->max_entries &&
217 rrl->max_entries != 0)
219 newsize = rrl->max_entries - rrl->num_entries;
229 if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DROP) && rrl->hash != NULL) {
230 rate = rrl->probes;
231 if (rrl->searches != 0) {
232 rate /= rrl->searches;
236 "increase from %d to %d RRL entries with"
238 rrl->num_entries, rrl->num_entries + newsize,
239 rrl->hash->length, rate);
244 b = isc_mem_cget(rrl->mctx, 1, bsize);
250 ISC_LIST_INITANDAPPEND(rrl->lru, e, lru);
252 rrl->num_entries += newsize;
253 ISC_LIST_INITANDAPPEND(rrl->blocks, b, link);
265 free_old_hash(dns_rrl_t *rrl) {
270 old_hash = rrl->old_hash;
280 isc_mem_put(rrl->mctx, old_hash,
284 rrl->old_hash = NULL;
288 expand_rrl_hash(dns_rrl_t *rrl, isc_stdtime_t now) {
293 if (rrl->old_hash != NULL) {
294 free_old_hash(rrl);
301 old_bins = (rrl->hash == NULL) ? 0 : rrl->hash->length;
303 if (new_bins < rrl->num_entries) {
304 new_bins = rrl->num_entries;
310 hash = isc_mem_cget(rrl->mctx, 1, hsize);
312 rrl->hash_gen ^= 1;
313 hash->gen = rrl->hash_gen;
316 rate = rrl->probes;
317 if (rrl->searches != 0) {
318 rate /= rrl->searches;
322 "increase from %d to %d RRL bins for"
324 old_bins, new_bins, rrl->num_entries, rate);
327 rrl->old_hash = rrl->hash;
328 if (rrl->old_hash != NULL) {
329 rrl->old_hash->check_time = now;
331 rrl->hash = hash;
337 ref_entry(dns_rrl_t *rrl, dns_rrl_entry_t *e, int probes, isc_stdtime_t now) {
341 if (ISC_LIST_HEAD(rrl->lru) != e) {
342 if (e == rrl->last_logged) {
343 rrl->last_logged = ISC_LIST_PREV(e, lru);
345 ISC_LIST_UNLINK(rrl->lru, e, lru);
346 ISC_LIST_PREPEND(rrl->lru, e, lru);
355 rrl->probes += probes;
356 ++rrl->searches;
357 if (rrl->searches > 100 &&
358 delta_rrl_time(rrl->hash->check_time, now) > 1)
360 if (rrl->probes / rrl->searches > 2) {
361 expand_rrl_hash(rrl, now);
363 rrl->hash->check_time = now;
364 rrl->probes = 0;
365 rrl->searches = 0;
399 make_key(const dns_rrl_t *rrl, dns_rrl_key_t *key,
454 rrl->ipv4_mask);
461 key->s.ip[i] &= rrl->ipv6_mask[i];
468 get_rate(dns_rrl_t *rrl, dns_rrl_rtype_t rtype) {
471 return &rrl->responses_per_second;
473 return &rrl->referrals_per_second;
475 return &rrl->nodata_per_second;
477 return &rrl->nxdomains_per_second;
479 return &rrl->errors_per_second;
481 return &rrl->all_per_second;
488 response_balance(dns_rrl_t *rrl, const dns_rrl_entry_t *e, int age) {
495 ratep = get_rate(rrl, e->key.s.rtype);
510 get_entry(dns_rrl_t *rrl, const isc_sockaddr_t *client_addr, dns_zone_t *zone,
521 make_key(rrl, &key, client_addr, zone, qtype, qname, qclass, rtype);
527 new_bin = get_bin(rrl->hash, hval);
532 ref_entry(rrl, e, probes, now);
542 if (rrl->old_hash != NULL) {
543 old_bin = get_bin(rrl->old_hash, hval);
549 e->hash_gen = rrl->hash_gen;
550 ref_entry(rrl, e, probes, now);
559 age = delta_rrl_time(rrl->old_hash->check_time, now);
560 if (age > rrl->window) {
561 free_old_hash(rrl);
575 for (e = ISC_LIST_TAIL(rrl->lru); e != NULL; e = ISC_LIST_PREV(e, lru))
580 age = get_age(rrl, e, now);
585 if (!e->logged && response_balance(rrl, e, age) > 0) {
590 expand_entries(rrl, ISC_MIN((rrl->num_entries + 1) / 2, 1000));
591 e = ISC_LIST_TAIL(rrl->lru);
594 log_end(rrl, e, true, log_buf, log_buf_len);
597 if (e->hash_gen == rrl->hash_gen) {
598 hash = rrl->hash;
600 hash = rrl->old_hash;
606 e->hash_gen = rrl->hash_gen;
609 ref_entry(rrl, e, probes, now);
625 DNS_RRL_LOG_DEBUG3, "rrl %08x %6s responses=%-3d %s",
630 debit_rrl_entry(dns_rrl_t *rrl, dns_rrl_entry_t *e, double qps, double scale,
641 ratep = get_rate(rrl, e->key.s.rtype);
652 rrl, client_addr, NULL, 0, dns_rdatatype_none, NULL,
655 age = get_age(rrl, e, now);
656 if (age < rrl->window) {
678 min = -rrl->window * rate;
685 age = get_age(rrl, e, now);
690 if (age > rrl->window) {
717 set_age(rrl, e, now);
736 slip = rrl->slip.r;
742 if (rrl->slip.scaled != new_slip) {
749 rrl->slip.scaled = slip;
773 get_qname(dns_rrl_t *rrl, const dns_rrl_entry_t *e) {
776 qbuf = rrl->qnames[e->log_qname];
784 free_qname(dns_rrl_t *rrl, dns_rrl_entry_t *e) {
787 qbuf = get_qname(rrl, e);
790 ISC_LIST_APPEND(rrl->qname_free, qbuf, link);
815 make_log_buf(dns_rrl_t *rrl, dns_rrl_entry_t *e, const char *str1,
891 snprintf(strbuf, sizeof(strbuf), "/%d", rrl->ipv6_prefixlen);
896 snprintf(strbuf, sizeof(strbuf), "/%d", rrl->ipv4_prefixlen);
911 qbuf = get_qname(rrl, e);
918 qbuf = ISC_LIST_TAIL(rrl->qname_free);
920 ISC_LIST_UNLINK(rrl->qname_free, qbuf, link);
921 } else if (rrl->num_qnames < DNS_RRL_QNAMES) {
922 qbuf = isc_mem_get(rrl->mctx, sizeof(*qbuf));
924 .index = rrl->num_qnames,
927 rrl->qnames[rrl->num_qnames++] = qbuf;
967 log_end(dns_rrl_t *rrl, dns_rrl_entry_t *e, bool early, char *log_buf,
970 make_log_buf(rrl, e, early ? "*" : NULL,
971 rrl->log_only ? "would stop limiting "
978 free_qname(rrl, e);
980 --rrl->num_logged;
988 log_stops(dns_rrl_t *rrl, isc_stdtime_t now, int limit, char *log_buf,
993 for (e = rrl->last_logged; e != NULL; e = ISC_LIST_PREV(e, lru)) {
998 age = get_age(rrl, e, now);
1000 response_balance(rrl, e, age) < 0)
1006 log_end(rrl, e, now == 0, log_buf, log_buf_len);
1007 if (rrl->num_logged <= 0) {
1015 rrl->last_logged = ISC_LIST_PREV(e, lru);
1020 INSIST(rrl->num_logged == 0);
1021 rrl->log_stops_time = now;
1023 rrl->last_logged = e;
1034 dns_rrl_t *rrl;
1046 rrl = view->rrl;
1047 if (rrl->exempt != NULL) {
1049 result = dns_acl_match(&netclient, NULL, rrl->exempt,
1056 LOCK(&rrl->lock);
1061 if (rrl->qps_scale == 0) {
1065 ++rrl->qps_responses;
1066 secs = delta_rrl_time(rrl->qps_time, now);
1068 qps = rrl->qps;
1070 qps = (1.0 * rrl->qps_responses) / secs;
1071 if (secs >= rrl->window) {
1081 rrl->qps_responses, secs,
1084 rrl->qps = qps;
1085 rrl->qps_responses = 0;
1086 rrl->qps_time = now;
1087 } else if (qps < rrl->qps) {
1088 qps = rrl->qps;
1091 scale = rrl->qps_scale / qps;
1097 if (rrl->num_logged > 0 && rrl->log_stops_time != now) {
1098 log_stops(rrl, now, 8, log_buf, log_buf_len);
1107 e = get_entry(rrl, client_addr, NULL, 0,
1112 e->responses = -(rrl->window + 1);
1113 set_age(rrl, e, now);
1116 UNLOCK(&rrl->lock);
1141 e = get_entry(rrl, client_addr, zone, qclass, qtype, qname, rtype, now,
1144 UNLOCK(&rrl->lock);
1153 make_log_buf(rrl, e, "consider limiting ", NULL, false, qname,
1161 rrl_result = debit_rrl_entry(rrl, e, qps, scale, client_addr, now,
1164 if (rrl->all_per_second.r != 0) {
1176 e_all = get_entry(rrl, client_addr, zone, 0, dns_rdatatype_none,
1180 UNLOCK(&rrl->lock);
1183 rrl_all_result = debit_rrl_entry(rrl, e_all, qps, scale,
1190 make_log_buf(rrl, e,
1204 UNLOCK(&rrl->lock);
1214 make_log_buf(rrl, e, rrl->log_only ? "would " : NULL,
1220 if (++rrl->num_logged <= 1) {
1221 rrl->last_logged = e;
1230 UNLOCK(&rrl->lock);
1242 make_log_buf(rrl, e,
1243 rrl->log_only ? "would rate limit "
1255 free_qname(rrl, e);
1257 UNLOCK(&rrl->lock);
1265 dns_rrl_t *rrl;
1271 rrl = view->rrl;
1272 if (rrl == NULL) {
1275 view->rrl = NULL;
1281 if (rrl->num_logged > 0) {
1282 log_stops(rrl, 0, INT32_MAX, log_buf, sizeof(log_buf));
1286 if (rrl->qnames[i] == NULL) {
1289 isc_mem_put(rrl->mctx, rrl->qnames[i], sizeof(*rrl->qnames[i]));
1292 if (rrl->exempt != NULL) {
1293 dns_acl_detach(&rrl->exempt);
1296 isc_mutex_destroy(&rrl->lock);
1298 while (!ISC_LIST_EMPTY(rrl->blocks)) {
1299 b = ISC_LIST_HEAD(rrl->blocks);
1300 ISC_LIST_UNLINK(rrl->blocks, b, link);
1301 isc_mem_put(rrl->mctx, b, b->size);
1304 h = rrl->hash;
1306 isc_mem_put(rrl->mctx, h,
1311 h = rrl->old_hash;
1313 isc_mem_put(rrl->mctx, h,
1318 isc_mem_putanddetach(&rrl->mctx, rrl, sizeof(*rrl));
1323 dns_rrl_t *rrl;
1328 rrl = isc_mem_get(view->mctx, sizeof(*rrl));
1329 *rrl = (dns_rrl_t){
1332 isc_mem_attach(view->mctx, &rrl->mctx);
1333 isc_mutex_init(&rrl->lock);
1335 view->rrl = rrl;
1337 result = expand_entries(rrl, min_entries);
1342 result = expand_rrl_hash(rrl, 0);
1348 *rrlp = rrl;