diff --git a/src/ckdb.c b/src/ckdb.c index 6d982f59..7dd25cb7 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -3070,8 +3070,9 @@ static enum cmd_values breakdown(K_ITEM **ml_item, char *buf, tv_t *now, i_item = find_ips(IPS_GROUP_BAN, ip); if (i_item) { DATA_IPS(ips, i_item); - // Has the ban expired? - if ((int)tvdiff(now, &(ips->createdate)) > ips->lifetime) { + // Has the ban expired? 0=eternal + if (ips->lifetime > 0 && + (int)tvdiff(now, &(ips->createdate)) > ips->lifetime) { remove_from_ktree(ips_root, i_item); k_unlink_item(ips_store, i_item); if (ips->description) { diff --git a/src/ckdb.h b/src/ckdb.h index 987dbf25..dd87b0fc 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -51,7 +51,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.4" -#define CKDB_VERSION DB_VERSION"-1.951" +#define CKDB_VERSION DB_VERSION"-1.952" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -1982,6 +1982,11 @@ extern K_STORE *ips_store; #define IPS_GROUP_BAD "BAD" #define IPS_GROUP_BAN "BAN" +// OptionControl records for IPS_GROUP_OK +#define OC_IPS "ips_" +#define OC_IPS_OK OC_IPS "ok_" +#define OC_IPS_BAN OC_IPS "ban_" + // EVENTS RAM only typedef struct events { int id; diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 7545635a..7587a427 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -7683,7 +7683,9 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id, snprintf(tmp, sizeof(tmp), "rows=%d", rows); APPEND_REALLOC(buf, off, len, tmp); } else if (strcasecmp(action, "ban") == 0) { - // Ban the ip with optional lifetime + /* Ban the ip with optional lifetime + * N.B. this doesn't survive a CKDB restart + * use just cmd_setopts for permanent bans */ bool found = false; oldlife = 0; i_ip = require_name(trf_root, "ip", 1, NULL, reply, siz); @@ -7737,7 +7739,14 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id, APPEND_REALLOC(buf, off, len, tmp); } else if (strcasecmp(action, "unban") == 0) { /* Unban the ip - sets lifetime to 1 meaning - * it expires 1s after it was created */ + * it expires 1 second after it was created + * so next access will remove the ban and succeed + * N.B. if it was a permanent 'cmd_setopts' ban, the unban + * won't survive a CKDB restart. + * You need to BOTH use this AND remove the optioncontrol + * record from the database to permanently remove a ban + * (since there's no cmd_expopts ... yet) */ + bool found = false; i_ip = require_name(trf_root, "ip", 1, NULL, reply, siz); if (!i_ip) diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index b7b77695..ae6535e3 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -2514,10 +2514,31 @@ void oc_event_limits(OPTIONCONTROL *oc, const char *from) } } +/* IPS for IPS_GROUP_OK/BAN look like: + * optionname: (OC_IPS_OK or OC_IPS_BAN) + description + * optionvalue: is the IP address + * If you want to add the cclass subnet of an IP then add it separately + * 127.0.0.1 is hard coded OK in ckdb.c */ +void oc_ips(OPTIONCONTROL *oc, const char *from) +{ + if (strncmp(oc->optionname, OC_IPS_OK, strlen(OC_IPS_OK)) == 0) { + ips_add(IPS_GROUP_OK, oc->optionvalue, oc->optionname, + false, false, 0, false); + } else if (strncmp(oc->optionname, OC_IPS_BAN, + strlen(OC_IPS_BAN)) == 0) { + ips_add(IPS_GROUP_BAN, oc->optionvalue, oc->optionname, + true, false, 0, false); + } else { + LOGERR("%s(%s): ERR: Unknown %s name '%s'", + from, __func__, OC_IPS, oc->optionname); + } +} + OC_TRIGGER oc_trigger[] = { { SWITCH_STATE_NAME, true, oc_switch_state }, { DIFF_PERCENT_NAME, true, oc_diff_percent }, { OC_LIMITS, false, oc_event_limits }, + { OC_IPS, false, oc_ips }, { NULL, 0, NULL } };