#define MODULE_LOG_PREFIX "failban" #include "globals.h" #include "module-anticasc.h" #include "oscam-net.h" #include "oscam-string.h" #include "oscam-time.h" static int32_t cs_check_v(IN_ADDR_T ip, int32_t port, int32_t add, char *info, int32_t acosc_penalty_duration) { int32_t result = 0; if(!(cfg.failbantime || acosc_enabled())) return 0; if(!cfg.v_list) { cfg.v_list = ll_create("v_list"); } struct timeb (now); cs_ftime(&now); LL_ITER itr = ll_iter_create(cfg.v_list); V_BAN *v_ban_entry; int32_t ftime = cfg.failbantime * 60 * 1000; // run over all banned entries to do housekeeping: while((v_ban_entry = ll_iter_next(&itr))) { // housekeeping: int64_t gone = comp_timeb(&now, &v_ban_entry->v_time); if(((gone >= ftime) && !v_ban_entry->acosc_entry) || (v_ban_entry->acosc_entry && ((gone/1000) >= v_ban_entry->acosc_penalty_dur))) // entry out of time->remove { NULLFREE(v_ban_entry->info); ll_iter_remove_data(&itr); continue; } if(IP_EQUAL(ip, v_ban_entry->v_ip) && port == v_ban_entry->v_port) { result = 1; if(!info) { info = v_ban_entry->info; } else if(!v_ban_entry->info) { v_ban_entry->info = cs_strdup(info); } if(!add) { if(v_ban_entry->v_count >= cfg.failbancount) { if(!v_ban_entry->acosc_entry) { cs_log_dbg(D_TRACE, "failban: banned ip %s:%d - %"PRId64" seconds left %s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, (ftime - gone) / 1000, info ? ", info: " : "", info ? info : ""); } else { cs_log_dbg(D_TRACE, "failban: banned ip %s:%d - %"PRId64" seconds left %s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, (v_ban_entry->acosc_penalty_dur - (gone / 1000)), info ? ", info: " : "", info ? info : ""); } } else { cs_log_dbg(D_TRACE, "failban: ip %s:%d chance %d of %d%s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, v_ban_entry->v_count, cfg.failbancount, info ? ", info: " : "", info ? info : ""); v_ban_entry->v_count++; } } else { cs_log_dbg(D_TRACE, "failban: banned ip %s:%d - already exist in list %s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, info ? ", info: " : "", info ? info : ""); } } } if(add && !result) { if(cs_malloc(&v_ban_entry, sizeof(V_BAN))) { cs_ftime(&v_ban_entry->v_time); v_ban_entry->v_ip = ip; v_ban_entry->v_port = port; v_ban_entry->v_count = 1; v_ban_entry->acosc_entry = false; v_ban_entry->acosc_penalty_dur = 0; if(acosc_penalty_duration > 0) { v_ban_entry->v_count = cfg.failbancount +1; // set it to a higher level v_ban_entry->acosc_entry = true; v_ban_entry->acosc_penalty_dur = acosc_penalty_duration; } if(info) { v_ban_entry->info = cs_strdup(info); } ll_iter_insert(&itr, v_ban_entry); cs_log_dbg(D_TRACE, "failban: ban ip %s:%d with timestamp %" PRId64 "%s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, (int64_t)v_ban_entry->v_time.time, info ? ", info: " : "", info ? info : ""); } } return result; } int32_t cs_check_violation(IN_ADDR_T ip, int32_t port) { return cs_check_v(ip, port, 0, NULL, 0); } int32_t cs_add_violation_by_ip(IN_ADDR_T ip, int32_t port, char *info) { return cs_check_v(ip, port, 1, info, 0); } int32_t cs_add_violation_by_ip_acosc(IN_ADDR_T ip, int32_t port, char *info, int32_t acosc_penalty_duration) { return cs_check_v(ip, port, 1, info, acosc_penalty_duration); } void cs_add_violation(struct s_client *cl, char *info) { struct s_module *module = get_module(cl); cs_add_violation_by_ip(cl->ip, module->ptab.ports[cl->port_idx].s_port, info); } void cs_add_violation_acosc(struct s_client *cl, char *info, int32_t acosc_penalty_duration) { struct s_module *module = get_module(cl); cs_add_violation_by_ip_acosc(cl->ip, module->ptab.ports[cl->port_idx].s_port, info, acosc_penalty_duration); }