bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
0ed36079905646682119839c2fbbbcd98444bd3dTimo Sirainen/* The idea behind checksums is that the same username+password doesn't
0ed36079905646682119839c2fbbbcd98444bd3dTimo Sirainen increase the penalty, because it's most likely a user with a misconfigured
0ed36079905646682119839c2fbbbcd98444bd3dTimo Sirainen account. */
0ed36079905646682119839c2fbbbcd98444bd3dTimo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen#include "lib.h"
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen#include "ioloop.h"
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen#include "hash.h"
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen#include "str.h"
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen#include "strescape.h"
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen#include "llist.h"
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen#include "ostream.h"
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen#include "penalty.h"
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen#include <time.h>
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen#define PENALTY_DEFAULT_EXPIRE_SECS (60*60)
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen#define PENALTY_CHECKSUM_SAVE_COUNT
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen#define CHECKSUM_VALUE_COUNT 2
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen#define CHECKSUM_VALUE_PTR_COUNT 10
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen#define LAST_UPDATE_BITS 15
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainenstruct penalty_rec {
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen /* ordered by last_update */
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen struct penalty_rec *prev, *next;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen char *ident;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int last_penalty;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int penalty:16;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int last_update:LAST_UPDATE_BITS; /* last_penalty + n */
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool checksum_is_pointer:1;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen /* we use value up to two different checksums.
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen after that switch to pointer. */
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen union {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int value[CHECKSUM_VALUE_COUNT];
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int *value_ptr;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen } checksum;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen};
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainenstruct penalty {
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen /* ident => penalty_rec */
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen HASH_TABLE(char *, struct penalty_rec *) hash;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen struct penalty_rec *oldest, *newest;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen unsigned int expire_secs;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen struct timeout *to;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen};
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainenstruct penalty *penalty_init(void)
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen{
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen struct penalty *penalty;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen penalty = i_new(struct penalty, 1);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen hash_table_create(&penalty->hash, default_pool, 0, str_hash, strcmp);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen penalty->expire_secs = PENALTY_DEFAULT_EXPIRE_SECS;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen return penalty;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen}
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainenstatic void penalty_rec_free(struct penalty *penalty, struct penalty_rec *rec)
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen{
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen DLLIST2_REMOVE(&penalty->oldest, &penalty->newest, rec);
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (rec->checksum_is_pointer)
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen i_free(rec->checksum.value_ptr);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen i_free(rec->ident);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen i_free(rec);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen}
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainenvoid penalty_deinit(struct penalty **_penalty)
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen{
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen struct penalty *penalty = *_penalty;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen *_penalty = NULL;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen while (penalty->oldest != NULL)
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen penalty_rec_free(penalty, penalty->oldest);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen hash_table_destroy(&penalty->hash);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&penalty->to);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen i_free(penalty);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen}
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainenvoid penalty_set_expire_secs(struct penalty *penalty, unsigned int expire_secs)
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen{
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen penalty->expire_secs = expire_secs;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen}
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainenstatic bool
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainenpenalty_bump_checksum(struct penalty_rec *rec, unsigned int checksum)
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen{
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int *checksums;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int i, count;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (!rec->checksum_is_pointer) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen checksums = rec->checksum.value;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen count = CHECKSUM_VALUE_COUNT;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen } else {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen checksums = rec->checksum.value_ptr;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen count = CHECKSUM_VALUE_PTR_COUNT;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen for (i = 0; i < count; i++) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (checksums[i] == checksum) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (i > 0) {
7f29b324658de9e42e75af45e2a198f3ba300031Timo Sirainen memmove(checksums + 1, checksums,
7f29b324658de9e42e75af45e2a198f3ba300031Timo Sirainen sizeof(checksums[0]) * i);
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen checksums[0] = checksum;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen return TRUE;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen return FALSE;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen}
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainenstatic void penalty_add_checksum(struct penalty_rec *rec, unsigned int checksum)
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen{
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int *checksums;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen i_assert(checksum != 0);
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (!rec->checksum_is_pointer) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (rec->checksum.value[CHECKSUM_VALUE_COUNT-1] == 0) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen memcpy(rec->checksum.value + 1, rec->checksum.value,
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen sizeof(rec->checksum.value[0]) *
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen (CHECKSUM_VALUE_COUNT-1));
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec->checksum.value[0] = checksum;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen return;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen /* switch to using a pointer */
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen checksums = i_new(unsigned int, CHECKSUM_VALUE_PTR_COUNT);
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen memcpy(checksums, rec->checksum.value,
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen sizeof(checksums[0]) * CHECKSUM_VALUE_COUNT);
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec->checksum.value_ptr = checksums;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec->checksum_is_pointer = TRUE;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
4633993e0e102636ba923e327138069a04a5304dTimo Sirainen memmove(rec->checksum.value_ptr + 1, rec->checksum.value_ptr,
4633993e0e102636ba923e327138069a04a5304dTimo Sirainen sizeof(rec->checksum.value_ptr[0]) *
4633993e0e102636ba923e327138069a04a5304dTimo Sirainen (CHECKSUM_VALUE_PTR_COUNT-1));
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec->checksum.value_ptr[0] = checksum;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen}
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainenunsigned int penalty_get(struct penalty *penalty, const char *ident,
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen time_t *last_penalty_r)
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen{
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen struct penalty_rec *rec;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen rec = hash_table_lookup(penalty->hash, ident);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen if (rec == NULL) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen *last_penalty_r = 0;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen return 0;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen *last_penalty_r = rec->last_penalty;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen return rec->penalty;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen}
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainenstatic void penalty_timeout(struct penalty *penalty)
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen{
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen struct penalty_rec *rec;
5e0d4b90ef697b8ccc2889eeb6035b27b50baff5Timo Sirainen time_t rec_last_update, expire_time;
5e0d4b90ef697b8ccc2889eeb6035b27b50baff5Timo Sirainen unsigned int diff;
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
37508ba28df9f6cdd4031624fcae658b40a6c795Timo Sirainen timeout_remove(&penalty->to);
37508ba28df9f6cdd4031624fcae658b40a6c795Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen expire_time = ioloop_time - penalty->expire_secs;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen while (penalty->oldest != NULL) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec = penalty->oldest;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5e0d4b90ef697b8ccc2889eeb6035b27b50baff5Timo Sirainen rec_last_update = rec->last_penalty + rec->last_update;
5e0d4b90ef697b8ccc2889eeb6035b27b50baff5Timo Sirainen if (rec_last_update > expire_time) {
5e0d4b90ef697b8ccc2889eeb6035b27b50baff5Timo Sirainen diff = rec_last_update - expire_time;
5e0d4b90ef697b8ccc2889eeb6035b27b50baff5Timo Sirainen penalty->to = timeout_add(diff * 1000,
5e0d4b90ef697b8ccc2889eeb6035b27b50baff5Timo Sirainen penalty_timeout, penalty);
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen break;
5e0d4b90ef697b8ccc2889eeb6035b27b50baff5Timo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen hash_table_remove(penalty->hash, rec->ident);
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen penalty_rec_free(penalty, rec);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen }
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen}
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainenvoid penalty_inc(struct penalty *penalty, const char *ident,
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int checksum, unsigned int value)
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen{
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen struct penalty_rec *rec;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen time_t diff;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen i_assert(value > 0 || checksum == 0);
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen i_assert(value <= INT_MAX);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen rec = hash_table_lookup(penalty->hash, ident);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen if (rec == NULL) {
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen rec = i_new(struct penalty_rec, 1);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen rec->ident = i_strdup(ident);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen hash_table_insert(penalty->hash, rec->ident, rec);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen } else {
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen DLLIST2_REMOVE(&penalty->oldest, &penalty->newest, rec);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (checksum == 0) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec->penalty = value;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec->last_penalty = ioloop_time;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen } else {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (penalty_bump_checksum(rec, checksum))
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec->penalty = value - 1;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen else {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen penalty_add_checksum(rec, checksum);
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec->penalty = value;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec->last_penalty = ioloop_time;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen diff = ioloop_time - rec->last_penalty;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (diff >= (1 << LAST_UPDATE_BITS)) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec->last_update = (1 << LAST_UPDATE_BITS) - 1;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec->last_penalty = ioloop_time - rec->last_update;
c829a47fe0dc63400cbd54a1e6d2e209ee2deebcTimo Sirainen } else {
c829a47fe0dc63400cbd54a1e6d2e209ee2deebcTimo Sirainen rec->last_update = diff;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen DLLIST2_APPEND(&penalty->oldest, &penalty->newest, rec);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen if (penalty->to == NULL) {
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen penalty->to = timeout_add(penalty->expire_secs * 1000,
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen penalty_timeout, penalty);
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen }
7e7cdca78e6a67757188406c8de9db42fcd17881Timo Sirainen}
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainenbool penalty_has_checksum(struct penalty *penalty, const char *ident,
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int checksum)
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen{
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen struct penalty_rec *rec;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen const unsigned int *checksums;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen unsigned int i, count;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen rec = hash_table_lookup(penalty->hash, ident);
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (rec == NULL)
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen return FALSE;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (!rec->checksum_is_pointer) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen checksums = rec->checksum.value;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen count = CHECKSUM_VALUE_COUNT;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen } else {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen checksums = rec->checksum.value_ptr;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen count = CHECKSUM_VALUE_PTR_COUNT;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen for (i = 0; i < count; i++) {
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen if (checksums[i] == checksum)
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen return TRUE;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen }
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen return FALSE;
5566faf0b48f0b77b0134f34130bdc7842c844ebTimo Sirainen}
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainenvoid penalty_dump(struct penalty *penalty, struct ostream *output)
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen{
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen const struct penalty_rec *rec;
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen string_t *str = t_str_new(256);
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen for (rec = penalty->oldest; rec != NULL; rec = rec->next) {
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen str_truncate(str, 0);
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(str, rec->ident);
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen str_printfa(str, "\t%u\t%u\t%u\n",
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen rec->penalty, rec->last_penalty,
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen rec->last_penalty + rec->last_update);
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen if (o_stream_send(output, str_data(str), str_len(str)) < 0)
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen break;
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(output, "\n", 1);
8825740187b8aaca9c39c4fd6a0b79d480eb143fTimo Sirainen}