diff --git a/src/ckdb.c b/src/ckdb.c index 7790fa30..2ee050bd 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -1248,7 +1248,13 @@ static void alloc_storage() ips_free = k_new_list("IPs", sizeof(IPS), ALLOC_IPS, LIMIT_IPS, true); ips_store = k_new_store(ips_free); ips_root = new_ktree(NULL, cmp_ips, ips_free); - ips_add(IPS_GROUP_OK, "127.0.0.1", "local", false, true, 0, false); + // Always default to allow localhost + K_WLOCK(ips_free); + ips_add(IPS_GROUP_OK, "127.0.0.1", EVENTNAME_ALL, true, "localhost", + false, true, 0, true); + ips_add(IPS_GROUP_OK, "127.0.0.1", OVENTNAME_ALL, false, "localhost", + false, true, 0, true); + K_WUNLOCK(ips_free); events_free = k_new_list("Events", sizeof(EVENTS), ALLOC_EVENTS, LIMIT_EVENTS, true); @@ -2785,8 +2791,7 @@ static enum cmd_values breakdown(K_ITEM **ml_item, char *buf, tv_t *now, TRANSFER *transfer; K_TREE_CTX ctx[1]; MSGLINE *msgline; - K_ITEM *t_item = NULL, *cd_item = NULL, *seqall, *i_item; - IPS *ips; + K_ITEM *t_item = NULL, *cd_item = NULL, *seqall; char *cmdptr, *idptr, *next, *eq, *end, *was; char *data = NULL, *st = NULL, *st2 = NULL, *ip = NULL; bool noid = false; @@ -3106,27 +3111,12 @@ static enum cmd_values breakdown(K_ITEM **ml_item, char *buf, tv_t *now, free(cmdptr); if (!seqall && ip) { - bool alert = false; + bool alert, is_event; K_WLOCK(ips_free); - i_item = find_ips(IPS_GROUP_BAN, ip); - if (i_item) { - DATA_IPS(ips, i_item); - // 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) { - LIST_MEM_SUB(ips_free, ips->description); - FREENULL(ips->description); - } - k_add_head(ips_free, i_item); - } else - alert = true; - } + alert = banned_ips(ip, now, &is_event); K_WUNLOCK(ips_free); if (alert) - return CMD_ALERT; + return is_event ? CMD_ALERTEVENT : CMD_ALERTOVENT; } return ckdb_cmds[msgline->which_cmds].cmd_val; @@ -4322,12 +4312,16 @@ static void *socketer(__maybe_unused void *arg) now.tv_sec); send_unix_msg(sockd, reply); break; - case CMD_ALERT: + case CMD_ALERTEVENT: + case CMD_ALERTOVENT: snprintf(reply, sizeof(reply), "%s.%ld.failed.ERR", msgline->id, now.tv_sec); - tmp = reply_event(EVENTID_NONE, reply); + if (cmdnum == CMD_ALERTEVENT) + tmp = reply_event(EVENTID_NONE, reply); + else + tmp = reply_ovent(OVENTID_NONE, reply); send_unix_msg(sockd, tmp); FREENULL(tmp); break; @@ -4654,7 +4648,8 @@ static void reload_line(PGconn *conn, char *filename, uint64_t count, char *buf) switch (cmdnum) { // Ignore case CMD_REPLY: - case CMD_ALERT: + case CMD_ALERTEVENT: + case CMD_ALERTOVENT: break; // Shouldn't be there case CMD_TERMINATE: diff --git a/src/ckdb.h b/src/ckdb.h index b8e69370..bd3a27cb 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.953" +#define CKDB_VERSION DB_VERSION"-1.954" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -632,7 +632,8 @@ enum cmd_values { CMD_UNSET, CMD_DUPSEQ, // Ignore, we've already got it CMD_REPLY, // Means something was wrong - send back reply - CMD_ALERT, // Means reply with the buf passed + CMD_ALERTEVENT, // Means reply with the buf passed + CMD_ALERTOVENT, // Means reply with the buf passed CMD_TERMINATE, CMD_PING, CMD_VERSION, @@ -1962,6 +1963,8 @@ extern K_LIST *process_pplns_free; typedef struct ips { char group[TXT_SML+1]; char ip[TXT_MED+1]; + char eventname[TXT_SML+1]; + bool is_event; int lifetime; bool log; char *description; @@ -1978,6 +1981,13 @@ extern K_TREE *ips_root; extern K_LIST *ips_free; extern K_STORE *ips_store; +// Only used by OK +#define EVENTNAME_ALL "*E" +#define OVENTNAME_ALL "*O" + +// All eventnames will be less than this +#define EVENTNAME_MAX "~" + #define IPS_GROUP_OK "OK" #define IPS_GROUP_BAD "BAD" #define IPS_GROUP_BAN "BAN" @@ -2823,7 +2833,15 @@ extern K_ITEM *find_payouts_wid(int64_t workinfoidend, K_TREE_CTX *ctx); extern double payout_stats(PAYOUTS *payouts, char *statname); extern bool process_pplns(int32_t height, char *blockhash, tv_t *now); extern cmp_t cmp_ips(K_ITEM *a, K_ITEM *b); -extern K_ITEM *find_ips(char *group, char *ip); +extern bool _is_limitname(bool is_event, char *eventname, bool allow_all); +#define is_elimitname(_name, _all) _is_limitname(true, _name, _all) +#define is_olimitname(_name, _all) _is_limitname(false, _name, _all) +extern K_ITEM *find_ips(char *group, char *ip, char *eventname, K_TREE_CTX *ctx); +extern K_ITEM *last_ips(char *group, char *ip, K_TREE_CTX *ctx); +extern bool _ok_ips(bool is_event, char *ip, char *eventname, tv_t *now); +#define ok_ips_event(_ip, _name, _now) _ok_ips(true, _ip, _name, _now) +#define ok_ips_ovent(_ip, _name, _now) _ok_ips(false, _ip, _name, _now) +extern bool banned_ips(char *ip, tv_t *now, bool *is_event); extern cmp_t cmp_events_user(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_events_ip(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_events_ipc(K_ITEM *a, K_ITEM *b); @@ -2833,9 +2851,11 @@ extern K_ITEM *last_events_ip(int id, char *ip, K_TREE_CTX *ctx); extern K_ITEM *last_events_ipc(int id, char *ipc, K_TREE_CTX *ctx); extern K_ITEM *last_events_hash(int id, char *hash, K_TREE_CTX *ctx); extern int check_events(EVENTS *events); -extern char *_reply_event(int event, char *buf, bool fre); -#define reply_event(_event, _buf) _reply_event(_event, _buf, false) -#define reply_event_free(_event, _buf) _reply_event(_event, _buf, true) +extern char *_reply_event(bool is_event, int event, char *buf, bool fre); +#define reply_event(_event, _buf) _reply_event(true, _event, _buf, false) +#define reply_event_free(_event, _buf) _reply_event(true, _event, _buf, true) +#define reply_ovent(_event, _buf) _reply_event(false, _event, _buf, false) +#define reply_ovent_free(_event, _buf) _reply_event(false, _event, _buf, true) extern cmp_t cmp_ovents(K_ITEM *a, K_ITEM *b); extern K_ITEM *find_ovents(char *key, int hour, K_TREE_CTX *ctx); extern K_ITEM *last_ovents(char *key, K_TREE_CTX *ctx); @@ -3048,8 +3068,8 @@ extern bool payouts_add(PGconn *conn, bool add, K_ITEM *p_item, extern K_ITEM *payouts_full_expire(PGconn *conn, int64_t payoutid, tv_t *now, bool lock); extern bool payouts_fill(PGconn *conn); -extern void ips_add(char *group, char *ip, char *des, bool log, bool cclass, - int life, bool locked); +extern void ips_add(char *group, char *ip, char *eventname, bool is_event, + char *des, bool log, bool cclass, int life, bool locked); extern int _events_add(int id, char *by, char *inet, tv_t *cd, K_TREE *trf_root); #define events_add(_id, _trf_root) _events_add(_id, NULL, NULL, NULL, _trf_root) extern bool auths_add(PGconn *conn, char *poolinstance, char *username, diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 7587a427..1dc377aa 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -7537,10 +7537,11 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id, __maybe_unused char *code, __maybe_unused char *inet, __maybe_unused tv_t *cd, K_TREE *trf_root) { - K_ITEM *i_action, *i_cmd, *i_list, *i_ip, *i_lifetime, *i_des, *i_item; + K_ITEM *i_action, *i_cmd, *i_list, *i_ip, *i_eventname, *i_lifetime; + K_ITEM *i_des, *i_item; K_TREE_CTX ctx[1]; IPS *ips; - char *action, *alert_cmd, *list, *ip, *des; + char *action, *alert_cmd, *list, *ip, *eventname, *des; char reply[1024] = ""; size_t siz = sizeof(reply); char tmp[1024] = ""; @@ -7683,7 +7684,7 @@ 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 eventname and lifetime * N.B. this doesn't survive a CKDB restart * use just cmd_setopts for permanent bans */ bool found = false; @@ -7692,6 +7693,14 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id, if (!i_ip) return strdup(reply); ip = transfer_data(i_ip); + i_eventname = optional_name(trf_root, "eventname", 1, NULL, reply, siz); + if (i_eventname) + eventname = transfer_data(i_eventname); + else { + if (*reply) + return strdup(reply); + eventname = EVENTNAME_ALL; + } i_lifetime = optional_name(trf_root, "lifetime", 1, (char *)intpatt, reply, siz); if (i_lifetime) @@ -7711,10 +7720,10 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id, des = NULL; } K_WLOCK(ips_free); - i_item = find_ips(IPS_GROUP_BAN, ip); + i_item = find_ips(IPS_GROUP_BAN, ip, eventname, NULL); if (i_item) { - found = true; DATA_IPS(ips, i_item); + found = true; oldlife = ips->lifetime; ips->lifetime = lifetime; // Don't change it if it's not supplied @@ -7725,20 +7734,23 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id, LIST_MEM_ADD(ips_free, ips->description); } } else { - ips_add(IPS_GROUP_BAN, ip, des, true, false, - lifetime, true); + ips_add(IPS_GROUP_BAN, ip, eventname, + is_elimitname(eventname, true), des, true, + false, lifetime, true); } K_WUNLOCK(ips_free); APPEND_REALLOC_INIT(buf, off, len); APPEND_REALLOC(buf, off, len, "ok."); if (found) { - snprintf(tmp, sizeof(tmp), "already %s %d->%d", - ip, oldlife, lifetime); - } else - snprintf(tmp, sizeof(tmp), "ban %s %d", ip, lifetime); + snprintf(tmp, sizeof(tmp), "already %s/%s %d->%d", + ip, eventname, oldlife, lifetime); + } else { + snprintf(tmp, sizeof(tmp), "ban %s/%s %d", + ip, eventname, lifetime); + } APPEND_REALLOC(buf, off, len, tmp); } else if (strcasecmp(action, "unban") == 0) { - /* Unban the ip - sets lifetime to 1 meaning + /* Unban the ip+eventname - sets lifetime to 1 meaning * 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 @@ -7752,8 +7764,12 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id, if (!i_ip) return strdup(reply); ip = transfer_data(i_ip); + i_eventname = require_name(trf_root, "eventname", 1, NULL, reply, siz); + if (!i_eventname) + return strdup(reply); + eventname = transfer_data(i_eventname); K_WLOCK(ips_free); - i_item = find_ips(IPS_GROUP_BAN, ip); + i_item = find_ips(IPS_GROUP_BAN, ip, eventname, NULL); if (i_item) { found = true; DATA_IPS(ips, i_item); @@ -7764,9 +7780,13 @@ static char *cmd_events(__maybe_unused PGconn *conn, char *cmd, char *id, if (found) { APPEND_REALLOC(buf, off, len, "ok."); APPEND_REALLOC(buf, off, len, ip); + APPEND_REALLOC(buf, off, len, "/"); + APPEND_REALLOC(buf, off, len, eventname); APPEND_REALLOC(buf, off, len, " unbanned"); - } else - APPEND_REALLOC(buf, off, len, "ERR.unknown ip"); + } else { + APPEND_REALLOC(buf, off, len, + "ERR.unknown ip+eventname"); + } } else { snprintf(reply, siz, "unknown action '%s'", action); LOGERR("%s() %s.%s", __func__, id, reply); diff --git a/src/ckdb_data.c b/src/ckdb_data.c index 8464b77e..86dfcddb 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -4273,7 +4273,7 @@ oku: return ok; } -// order by group asc,ip asc,expirydate desc +// order by group asc,ip asc,eventname asc,expirydate desc cmp_t cmp_ips(K_ITEM *a, K_ITEM *b) { IPS *ia, *ib; @@ -4282,21 +4282,52 @@ cmp_t cmp_ips(K_ITEM *a, K_ITEM *b) cmp_t c = CMP_STR(ia->group, ib->group); if (c == 0) { c = CMP_STR(ia->ip, ib->ip); - if (c == 0) - c = CMP_TV(ib->expirydate, ia->expirydate); + if (c == 0) { + c = CMP_STR(ia->eventname, ib->eventname); + if (c == 0) + c = CMP_TV(ib->expirydate, ia->expirydate); + } } return c; } +bool _is_limitname(bool is_event, char *eventname, bool allow_all) +{ + int i; + + if (is_event) { + if (allow_all && strcmp(eventname, EVENTNAME_ALL) == 0) + return true; + i = -1; + while (e_limits[++i].name) { + if (strcmp(eventname, e_limits[i].name) == 0) + return true; + } + } else { + if (allow_all && strcmp(eventname, OVENTNAME_ALL) == 0) + return true; + i = -1; + while (o_limits[++i].name) { + if (strcmp(eventname, o_limits[i].name) == 0) + return true; + } + } + return false; +} + // Must be R or W locked before call -K_ITEM *find_ips(char *group, char *ip) +K_ITEM *find_ips(char *group, char *ip, char *eventname, K_TREE_CTX *ctx) { - K_TREE_CTX ctx[1]; + K_TREE_CTX ctx0[1]; K_ITEM look; IPS ips; + if (ctx == NULL) + ctx = ctx0; + STRNCPY(ips.group, group); STRNCPY(ips.ip, ip); + STRNCPY(ips.eventname, eventname); ips.expirydate.tv_sec = default_expiry.tv_sec; ips.expirydate.tv_usec = default_expiry.tv_usec; @@ -4305,6 +4336,104 @@ K_ITEM *find_ips(char *group, char *ip) return find_in_ktree(ips_root, &look, ctx); } +K_ITEM *last_ips(char *group, char *ip, K_TREE_CTX *ctx) +{ + K_TREE_CTX ctx0[1]; + K_ITEM look; + IPS ips; + + if (ctx == NULL) + ctx = ctx0; + + STRNCPY(ips.group, group); + STRNCPY(ips.ip, ip); + STRNCPY(ips.eventname, EVENTNAME_MAX); + copy_tv(&(ips.expirydate), &default_expiry); + + INIT_IPS(&look); + look.data = (void *)(&ips); + return find_before_in_ktree(ips_root, &look, ctx); +} + +// IPS override checking eventname +bool _ok_ips(bool is_event, char *ip, char *eventname, tv_t *now) +{ + K_TREE_CTX ctx[1]; + K_ITEM *i_item = NULL, *prev_item; + bool ret = false; + IPS *ips; + + i_item = last_ips(IPS_GROUP_OK, ip, ctx); + DATA_IPS_NULL(ips, i_item); + while (i_item && strcmp(ips->group, IPS_GROUP_OK) == 0 && + strcmp(ips->ip, ip) == 0) { + if (CURRENT(&(ips->expirydate)) && + (strcmp(ips->eventname, eventname) == 0 || + (is_event && strcmp(ips->eventname, EVENTNAME_ALL) == 0) || + (!is_event && strcmp(ips->eventname, OVENTNAME_ALL) == 0))) { + if (ips->lifetime == 0 || + (int)tvdiff(now, &(ips->createdate)) <= ips->lifetime) { + ret = true; + break; + } + // The OK has expired, so remove it + prev_item = prev_in_ktree(ctx); + k_unlink_item(ips_store, i_item); + if (ips->description) { + LIST_MEM_SUB(ips_free, ips->description); + FREENULL(ips->description); + } + k_add_head(ips_free, i_item); + i_item = prev_item; + DATA_IPS_NULL(ips, i_item); + continue; + } + i_item = prev_in_ktree(ctx); + DATA_IPS_NULL(ips, i_item); + } + return ret; +} + +/* Must be W locked before call + * N.B. a ban will ban an OK ip if both BAN and OK exist */ +bool banned_ips(char *ip, tv_t *now, bool *is_event) +{ + K_TREE_CTX ctx[1]; + K_ITEM *i_item = NULL, *prev_item; + bool ret = false; + IPS *ips; + + i_item = last_ips(IPS_GROUP_BAN, ip, ctx); + DATA_IPS_NULL(ips, i_item); + while (i_item && strcmp(ips->group, IPS_GROUP_BAN) == 0 && + strcmp(ips->ip, ip) == 0) { + if (CURRENT(&(ips->expirydate))) { + // Any current unexpired ban + if (ips->lifetime == 0 || + (int)tvdiff(now, &(ips->createdate)) <= ips->lifetime) { + if (is_event) + *is_event = ips->is_event; + ret = true; + break; + } + // The ban has expired, so remove it + prev_item = prev_in_ktree(ctx); + k_unlink_item(ips_store, i_item); + if (ips->description) { + LIST_MEM_SUB(ips_free, ips->description); + FREENULL(ips->description); + } + k_add_head(ips_free, i_item); + i_item = prev_item; + DATA_IPS_NULL(ips, i_item); + continue; + } + i_item = prev_in_ktree(ctx); + DATA_IPS_NULL(ips, i_item); + } + return ret; +} + // order by createby asc,id asc,expirydate desc, createdate asc cmp_t cmp_events_user(K_ITEM *a, K_ITEM *b) { @@ -4498,13 +4627,13 @@ static const char *cause_str(enum event_cause cause) } } -// return EVENT_OK or -timeout seconds +// return EVENT_OK or timeout seconds int check_events(EVENTS *events) { - bool alert = false, user1, user2; + bool alert = false, ok, user1, user2; char createby[TXT_SML+1], *st = NULL; enum event_cause cause = CAUSE_NONE; - K_ITEM *i_item, *e_item = NULL, *tmp_item, *u_item; + K_ITEM *e_item = NULL, *tmp_item, *u_item; K_TREE_CTX ctx[1]; EVENTS *e = NULL; char cmd[MAX_ALERT_CMD+1]; @@ -4524,16 +4653,17 @@ int check_events(EVENTS *events) if (!cmd[0]) return EVENT_OK; - K_RLOCK(ips_free); - i_item = find_ips(IPS_GROUP_OK, events->createinet); - if (!i_item) - i_item = find_ips(IPS_GROUP_OK, events->ipc); - K_RUNLOCK(ips_free); - if (i_item) + setnow(&now); + + K_WLOCK(ips_free); + ok = ok_ips_event(events->createinet, e_limits[events->id].name, &now); + if (!ok) + ok = ok_ips_event(events->ipc, e_limits[events->id].name, &now); + K_WUNLOCK(ips_free); + if (ok) return EVENT_OK; // All tests below always run all full checks to clean up old events - setnow(&now); K_WLOCK(events_free); K_RLOCK(event_limits_free); // Check hash - same hash passfail on more than one valid User @@ -4765,7 +4895,7 @@ int check_events(EVENTS *events) st = safe_text_nonull(events->createby), cause_str(cause)); FREENULL(st); - ips_add(IPS_GROUP_BAN, events->createinet, + ips_add(IPS_GROUP_BAN, events->createinet, name, true, (char *)cause_str(cause), true, false, lifetime, false); pid = fork(); if (pid < 0) { @@ -4788,7 +4918,7 @@ int check_events(EVENTS *events) exit(0); } } - return -lifetime; + return lifetime; } return EVENT_OK; } @@ -4796,11 +4926,11 @@ int check_events(EVENTS *events) static char lurt[] = "alert="; static size_t lurtsiz = sizeof(lurt); static char tmf[] = "Too many failures, come back later"; -static size_t tmfsiz = sizeof(tmf); +static size_t tmfsiz = sizeof(tmf); // includes null static char tma[] = "Too many accesses, come back later"; -static size_t tmasiz = sizeof(tma); +static size_t tmasiz = sizeof(tma); // includes null -char *_reply_event(int event, char *buf, bool fre) +char *_reply_event(bool is_event, int event, char *buf, bool fre) { size_t len; char *reply; @@ -4818,7 +4948,7 @@ char *_reply_event(int event, char *buf, bool fre) len = strlen(buf); len += 1 + lurtsiz; - if (event < 0) + if (is_event) len += tmfsiz; else len += tmasiz; @@ -4826,7 +4956,7 @@ char *_reply_event(int event, char *buf, bool fre) if (!reply) quithere(1, "malloc (%d) OOM", (int)len); snprintf(reply, len, "%s%c%s%s", buf, FLDSEP, lurt, - event < 0 ? tmf : tma); + is_event ? tmf : tma); if (fre) free(buf); return reply; @@ -4959,9 +5089,8 @@ static enum was_alert check_one_ovent(int id, char *key, tv_t *now, // return OVENT_OK or +timeout seconds int check_ovents(int id, char *u_key, char *i_key, char *c_key, tv_t *now) { - K_ITEM *i_item; enum was_alert was; - bool alert = false; + bool alert = false, ok; char *st = NULL; enum event_cause cause = CAUSE_NONE; char cmd[MAX_ALERT_CMD+1]; @@ -4980,12 +5109,12 @@ int check_ovents(int id, char *u_key, char *i_key, char *c_key, tv_t *now) return OVENT_OK; if (i_key[0]) { - K_RLOCK(ips_free); - i_item = find_ips(IPS_GROUP_OK, i_key); - if (!i_item) - i_item = find_ips(IPS_GROUP_OK, i_key); - K_RUNLOCK(ips_free); - if (i_item) + K_WLOCK(ips_free); + ok = ok_ips_ovent(i_key, o_limits[id].name, now); + if (!ok && c_key[0]) + ok = ok_ips_ovent(c_key, o_limits[id].name, now); + K_WUNLOCK(ips_free); + if (ok) return OVENT_OK; } @@ -5076,8 +5205,9 @@ int check_ovents(int id, char *u_key, char *i_key, char *c_key, tv_t *now) __func__, id, st = safe_text(u_key)); FREENULL(st); } else { - ips_add(IPS_GROUP_BAN, i_key, (char *)cause_str(cause), - true, false, lifetime, false); + ips_add(IPS_GROUP_BAN, i_key, name, false, + (char *)cause_str(cause), true, false, + lifetime, false); pid = fork(); if (pid < 0) { LOGERR("%s() OLERT failed to fork (%d)", diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index 6e1ff7ee..77286392 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -2457,7 +2457,7 @@ void oc_diff_percent(OPTIONCONTROL *oc, __maybe_unused const char *from) * Item is one of the field names in event_limits * e.g. user_low_time, user_low_time_limit etc * as below in the if tests - * lifetime values can't = -EVENT_OK */ + * lifetime values can't = EVENT_OK */ void oc_event_limits(OPTIONCONTROL *oc, const char *from) { bool processed = false; @@ -2491,12 +2491,12 @@ void oc_event_limits(OPTIONCONTROL *oc, const char *from) } else if (strcmp(ptr2, "ip_hi_time_limit") == 0) { e_limits[i].ip_hi_time_limit = val; } else if (strcmp(ptr2, "lifetime") == 0) { - if (val != -(EVENT_OK)) + if (val != EVENT_OK) e_limits[i].lifetime = val; else { LOGERR("%s(%s): ERR: lifetime can't be" " %d in '%s'", - from, __func__, -(EVENT_OK), + from, __func__, EVENT_OK, oc->optionname); } } else { @@ -2511,12 +2511,12 @@ void oc_event_limits(OPTIONCONTROL *oc, const char *from) } if (!processed) { if (strcmp(ptr, "hash_lifetime") == 0) { - if (val != -(EVENT_OK)) + if (val != EVENT_OK) event_limits_hash_lifetime = val; else { LOGERR("%s(%s): ERR: lifetime can't be" " %d in '%s'", - from, __func__, -(EVENT_OK), + from, __func__, EVENT_OK, oc->optionname); } processed = true; @@ -2610,18 +2610,36 @@ void oc_ovent_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 + * optionvalue: is the IP address:EVENTNAME * 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) { + char *colon; + IPS ips; + bool e; + + colon = strchr(oc->optionvalue, ':'); + if (!colon) { + LOGERR("%s(%s): ERR: Missing ':' after IP '%s' name '%s'", + from, __func__, oc->optionvalue, oc->optionname); + } + STRNCPY(ips.eventname, colon+1); + + STRNCPY(ips.ip, oc->optionvalue); + colon = strchr(ips.ip, ':'); + if (colon) + *colon = '\0'; + 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); + e = is_elimitname(ips.eventname, true); + ips_add(IPS_GROUP_OK, ips.ip, ips.eventname, e, + 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); + e = is_elimitname(ips.eventname, true); + ips_add(IPS_GROUP_BAN, ips.ip, ips.eventname, e, + oc->optionname, false, false, 0, false); } else { LOGERR("%s(%s): ERR: Unknown %s name '%s'", from, __func__, OC_IPS, oc->optionname); @@ -6642,8 +6660,8 @@ int _ovents_add(int id, char *by, char *inet, tv_t *cd, K_TREE *trf_root) return check_ovents(id, u_key, i_key, c_key, &(ovents.createdate)); } -void ips_add(char *group, char *ip, char *des, bool log, bool cclass, int life, - bool locked) +void ips_add(char *group, char *ip, char *eventname, bool is_event, char *des, + bool log, bool cclass, int life, bool locked) { K_ITEM *i_item, *i2_item; IPS *ips, *ips2; @@ -6651,6 +6669,20 @@ void ips_add(char *group, char *ip, char *des, bool log, bool cclass, int life, tv_t now; bool ok; + if (is_event) { + if (!is_elimitname(eventname, true)) { + LOGERR("%s() invalid Event name '%s' - ignored", + __func__, eventname); + return; + } + } else { + if (!is_olimitname(eventname, true)) { + LOGERR("%s() invalid Ovent name '%s' - ignored", + __func__, eventname); + return; + } + } + setnow(&now); if (!locked) K_WLOCK(ips_free); @@ -6658,7 +6690,8 @@ void ips_add(char *group, char *ip, char *des, bool log, bool cclass, int life, DATA_IPS(ips, i_item); STRNCPY(ips->group, group); STRNCPY(ips->ip, ip); - ips->lifetime = life; + STRNCPY(ips->eventname, eventname); + ips->is_event = is_event; if (des) { ips->description = strdup(des); if (!ips->description) @@ -6666,6 +6699,7 @@ void ips_add(char *group, char *ip, char *des, bool log, bool cclass, int life, LIST_MEM_ADD(ips_free, ips->description); } ips->log = log; + ips->lifetime = life; HISTORYDATEDEFAULT(ips, &now); add_to_ktree(ips_root, i_item); k_add_head(ips_store, i_item);