diff --git a/include/AlertFifoQueue.h b/include/AlertFifoQueue.h index f4635e3ef8..1272b56b36 100644 --- a/include/AlertFifoQueue.h +++ b/include/AlertFifoQueue.h @@ -24,11 +24,6 @@ #include "ntop_includes.h" -typedef struct { - AlertLevel level; - char *alert; -} AlertFifoItem; - class AlertFifoQueue : public FifoQueue { public: AlertFifoQueue(u_int32_t queue_size) : FifoQueue(queue_size) {} @@ -47,7 +42,7 @@ class AlertFifoQueue : public FifoQueue { m.lock(__FILE__, __LINE__); if(q.empty()) { - rv.level = alert_level_none; + rv.alert_severity = alert_level_none; rv.alert = NULL; } else { rv = q.front(); diff --git a/include/Ntop.h b/include/Ntop.h index 91736aadd1..c3d6fb51eb 100644 --- a/include/Ntop.h +++ b/include/Ntop.h @@ -469,8 +469,8 @@ class Ntop { inline void setnDPICleanupNeeded(bool needed) { ndpi_cleanup_needed = needed; } inline FifoSerializerQueue* getInternalAlertsQueue() { return(internal_alerts_queue); } void lua_alert_queues_stats(lua_State* vm); - bool recipient_enqueue(u_int16_t recipient_id, RecipientNotificationPriority prio, const char * const notification); - char* recipient_dequeue(u_int16_t recipient_id, RecipientNotificationPriority prio); + bool recipient_enqueue(u_int16_t recipient_id, RecipientNotificationPriority prio, const AlertFifoItem* const notification); + bool recipient_dequeue(u_int16_t recipient_id, RecipientNotificationPriority prio, AlertFifoItem *notification); void recipient_stats(u_int16_t recipient_id, lua_State* vm); void recipient_delete(u_int16_t recipient_id); void recipient_register(u_int16_t recipient_id); diff --git a/include/RecipientQueues.h b/include/RecipientQueues.h index af384617c0..a3b8be421c 100644 --- a/include/RecipientQueues.h +++ b/include/RecipientQueues.h @@ -42,10 +42,11 @@ class RecipientQueues { /** * @brief Dequeues a notification from a `recipient_id` queue, given a certain priority * @param prio The priority of the notification + * @param notification The dequeued notification * - * @return A pointer to a notification string, or NULL if there was no notification in the queue. The pointer MUST be `free`d after use + * @return Boolean, true if the dequeue was successful and `notification` is populated correctly, false otherwise */ - char *dequeue(RecipientNotificationPriority prio); + bool dequeue(RecipientNotificationPriority prio, AlertFifoItem *notification); /** * @brief Enqueues a notification to a `recipient_id` queue, depending on the priority * @param recipient_id An integer recipient identifier @@ -54,7 +55,7 @@ class RecipientQueues { * * @return True if the enqueue succeeded, false otherwise */ - bool enqueue(RecipientNotificationPriority prio, const char * const notification); + bool enqueue(RecipientNotificationPriority prio, const AlertFifoItem* const notification); /** * @brief Returns queue status (drops and uses) * @param vm A Lua VM instance diff --git a/include/Recipients.h b/include/Recipients.h index aa39342766..5e124feafc 100644 --- a/include/Recipients.h +++ b/include/Recipients.h @@ -37,20 +37,20 @@ class Recipients { /** * @brief Dequeues a notification from a `recipient_id` queue, given a certain priority * @param recipient_id An integer recipient identifier - * @param prio The priority of the notification + * @param notification The dequeued notification * - * @return A pointer to a notification string, or NULL if there was no notification in the queue. The pointer MUST be `free`d after use + * @return Boolean, true if the dequeue was successful and `notification` is populated correctly, false otherwise */ - char *dequeue(u_int16_t recipient_id, RecipientNotificationPriority prio); + bool dequeue(u_int16_t recipient_id, RecipientNotificationPriority prio, AlertFifoItem *notification); /** * @brief Enqueues a notification to a `recipient_id` queue, depending on the priority * @param recipient_id An integer recipient identifier * @param prio The priority of the notification - * @param notification A string containing the notification + * @param notification The notification to be enqueued * * @return True if the enqueue succeeded, false otherwise */ - bool enqueue(u_int16_t recipient_id, RecipientNotificationPriority prio, const char * const notification); + bool enqueue(u_int16_t recipient_id, RecipientNotificationPriority prio, const AlertFifoItem* const notification); /** * @brief Registers a recipient identified with `recipient_id` so its notification can be enqueued/dequeued * @param recipient_id An integer recipient identifier diff --git a/include/ntop_typedefs.h b/include/ntop_typedefs.h index ca4d1c04e5..4fc4e7ff9d 100644 --- a/include/ntop_typedefs.h +++ b/include/ntop_typedefs.h @@ -204,6 +204,12 @@ typedef enum { IPV6 = 6 } IPVersion; +/* Used to queue/dequeue elements in recipient queues via AlertFifoQueue.h */ +typedef struct { + AlertLevel alert_severity; + char *alert; +} AlertFifoItem; + struct zmq_msg_hdr_v0 { char url[32]; u_int32_t version; diff --git a/scripts/lua/modules/alert_consts.lua b/scripts/lua/modules/alert_consts.lua index faf5ea1709..dbe61a8fc5 100644 --- a/scripts/lua/modules/alert_consts.lua +++ b/scripts/lua/modules/alert_consts.lua @@ -541,7 +541,7 @@ end -- ############################################## function alert_consts.alertLevelToSyslogLevel(v) - return alert_severities[v].syslog_severity + return alert_severities[alert_consts.alertSeverityRaw(v)].syslog_severity end -- ################################################################################ diff --git a/scripts/lua/modules/notifications/recipients.lua b/scripts/lua/modules/notifications/recipients.lua index c4042db449..fd95bcffa5 100644 --- a/scripts/lua/modules/notifications/recipients.lua +++ b/scripts/lua/modules/notifications/recipients.lua @@ -644,7 +644,7 @@ function recipients.dispatch_notification(notification, current_script) local is_high_priority = is_notification_high_priority(notification) for _, recipient_id in pairs(recipients) do - ntop.recipient_enqueue(recipient_id, is_high_priority, json_notification) + ntop.recipient_enqueue(recipient_id, is_high_priority, json_notification, notification.alert_severity) end end else diff --git a/scripts/plugins/endpoints/discord_alert_endpoint/alert_endpoints/discord.lua b/scripts/plugins/endpoints/discord_alert_endpoint/alert_endpoints/discord.lua index 03598b1e7c..5b647ba451 100644 --- a/scripts/plugins/endpoints/discord_alert_endpoint/alert_endpoints/discord.lua +++ b/scripts/plugins/endpoints/discord_alert_endpoint/alert_endpoints/discord.lua @@ -143,7 +143,7 @@ function discord.dequeueRecipientAlerts(recipient, budget, high_priority) for i=1, max_alerts_per_request do local notification = ntop.recipient_dequeue(recipient.recipient_id, high_priority) if notification then - notifications[#notifications + 1] = notification + notifications[#notifications + 1] = notification.alert else break end diff --git a/scripts/plugins/endpoints/email_alert_endpoint/alert_endpoints/email.lua b/scripts/plugins/endpoints/email_alert_endpoint/alert_endpoints/email.lua index c16d65a938..290b73e60f 100644 --- a/scripts/plugins/endpoints/email_alert_endpoint/alert_endpoints/email.lua +++ b/scripts/plugins/endpoints/email_alert_endpoint/alert_endpoints/email.lua @@ -131,7 +131,7 @@ function email.dequeueRecipientAlerts(recipient, budget, high_priority) for i = 1, MAX_ALERTS_PER_EMAIL do local notification = ntop.recipient_dequeue(recipient.recipient_id, high_priority) if notification then - notifications[#notifications + 1] = notification + notifications[#notifications + 1] = notification.alert else break end diff --git a/scripts/plugins/endpoints/shell_alert_endpoint/alert_endpoints/shell.lua b/scripts/plugins/endpoints/shell_alert_endpoint/alert_endpoints/shell.lua index 6886dfd813..e55aa75381 100644 --- a/scripts/plugins/endpoints/shell_alert_endpoint/alert_endpoints/shell.lua +++ b/scripts/plugins/endpoints/shell_alert_endpoint/alert_endpoints/shell.lua @@ -164,7 +164,7 @@ function shell.dequeueRecipientAlerts(recipient, budget, high_priority) for i = 1, MAX_ALERTS_PER_REQUEST do local notification = ntop.recipient_dequeue(recipient.recipient_id, high_priority) if notification then - notifications[#notifications + 1] = notification + notifications[#notifications + 1] = notification.alert else break end diff --git a/scripts/plugins/endpoints/slack_alert_endpoint/alert_endpoints/slack.lua b/scripts/plugins/endpoints/slack_alert_endpoint/alert_endpoints/slack.lua index 3a9ea00393..1508755a24 100644 --- a/scripts/plugins/endpoints/slack_alert_endpoint/alert_endpoints/slack.lua +++ b/scripts/plugins/endpoints/slack_alert_endpoint/alert_endpoints/slack.lua @@ -88,7 +88,7 @@ function slack.dequeueRecipientAlerts(recipient, budget, high_priority) for i = 1, budget do local notification = ntop.recipient_dequeue(recipient.recipient_id, high_priority) if notification then - notifications[#notifications + 1] = notification + notifications[#notifications + 1] = notification.alert else break end diff --git a/scripts/plugins/endpoints/sqlite_alert_endpoint/alert_endpoints/sqlite.lua b/scripts/plugins/endpoints/sqlite_alert_endpoint/alert_endpoints/sqlite.lua index 516bbf3dbd..937f505361 100644 --- a/scripts/plugins/endpoints/sqlite_alert_endpoint/alert_endpoints/sqlite.lua +++ b/scripts/plugins/endpoints/sqlite_alert_endpoint/alert_endpoints/sqlite.lua @@ -55,7 +55,7 @@ function sqlite.dequeueRecipientAlerts(recipient, budget, high_priority) for i=1, budget do local notification = ntop.recipient_dequeue(recipient.recipient_id, high_priority) if notification then - notifications[#notifications + 1] = notification + notifications[#notifications + 1] = notification.alert else break end diff --git a/scripts/plugins/endpoints/syslog_alert_endpoint/alert_endpoints/syslog.lua b/scripts/plugins/endpoints/syslog_alert_endpoint/alert_endpoints/syslog.lua index a0cb578872..d9af74e054 100644 --- a/scripts/plugins/endpoints/syslog_alert_endpoint/alert_endpoints/syslog.lua +++ b/scripts/plugins/endpoints/syslog_alert_endpoint/alert_endpoints/syslog.lua @@ -79,24 +79,20 @@ function syslog.sendMessage(settings, notif, severity, syslog_format) local msg if syslog_format and syslog_format == "json" then - -- send out the json message but prepare a nice - -- message - notif.message = alert_utils.formatAlertNotification(notif, { - nohtml = true, - show_severity = false, - show_entity = false}) - msg = json.encode(notif) + -- Send it plain, notif is already a json-encoded string + -- so for efficiency, no decoding is done + msg = notif elseif syslog_format and syslog_format == "ecs" then if ntop.isEnterpriseM() then package.path = dirs.installdir .. "/pro/scripts/lua/modules/?.lua;" .. package.path local ecs_format = require "ecs_format" - msg = json.encode(ecs_format.format(notif)) + msg = json.encode(ecs_format.format(json.decode(notif))) else return false end else -- syslog_format == "plaintext" -- prepare a plaintext message - msg = alert_utils.formatAlertNotification(notif, { + msg = alert_utils.formatAlertNotification(json.decode(notif), { nohtml = true, show_severity = true, show_entity = true}) @@ -147,27 +143,9 @@ function syslog.dequeueRecipientAlerts(recipient, budget, high_priority) return {success = true, more_available = false} end - -- Separate by severity and channel - local alerts_by_types = {} - - for _, json_message in ipairs(notifications) do - local notif = json.decode(json_message) - if notif.alert_entity then - alerts_by_types[notif.alert_entity] = alerts_by_types[notif.alert_entity] or {} - alerts_by_types[notif.alert_entity][notif.alert_severity] = alerts_by_types[notif.alert_entity][notif.alert_severity] or {} - table.insert(alerts_by_types[notif.alert_entity][notif.alert_severity], notif) - end - end - - for _, by_severity in pairs(alerts_by_types) do - for severity, sev_notifications in pairs(by_severity) do - severity = alert_consts.alertSeverityRaw(severity) - - -- Most recent notifications first - for _, notif in pairsByValues(sev_notifications, alert_utils.notification_timestamp_rev) do - syslog.sendMessage(settings, notif, severity, recipient.endpoint_conf.syslog_alert_format) - end - end + -- Most recent notifications first + for _, notification in ipairs(notifications) do + syslog.sendMessage(settings, notification.alert, notification.alert_severity, recipient.endpoint_conf.syslog_alert_format) end return {success = true, more_available = true} diff --git a/scripts/plugins/endpoints/telegram_alert_endpoint/alert_endpoints/telegram.lua b/scripts/plugins/endpoints/telegram_alert_endpoint/alert_endpoints/telegram.lua index 362e81a963..82a7a8fb07 100644 --- a/scripts/plugins/endpoints/telegram_alert_endpoint/alert_endpoints/telegram.lua +++ b/scripts/plugins/endpoints/telegram_alert_endpoint/alert_endpoints/telegram.lua @@ -132,7 +132,7 @@ function telegram.dequeueRecipientAlerts(recipient, budget, high_priority) for i=1, max_alerts_per_request do local notification = ntop.recipient_dequeue(recipient.recipient_id, high_priority) if notification then - notifications[#notifications + 1] = notification + notifications[#notifications + 1] = notification.alert else break end diff --git a/scripts/plugins/endpoints/webhook_alert_endpoint/alert_endpoints/webhook.lua b/scripts/plugins/endpoints/webhook_alert_endpoint/alert_endpoints/webhook.lua index 5d3f2dba45..9ca229f232 100644 --- a/scripts/plugins/endpoints/webhook_alert_endpoint/alert_endpoints/webhook.lua +++ b/scripts/plugins/endpoints/webhook_alert_endpoint/alert_endpoints/webhook.lua @@ -105,7 +105,7 @@ function webhook.dequeueRecipientAlerts(recipient, budget, high_priority) for i = 1, MAX_ALERTS_PER_REQUEST do local notification = ntop.recipient_dequeue(recipient.recipient_id, high_priority) if notification then - notifications[#notifications + 1] = notification + notifications[#notifications + 1] = notification.alert else break end diff --git a/src/LuaEngineNtop.cpp b/src/LuaEngineNtop.cpp index b91830fed4..0f3fb99690 100644 --- a/src/LuaEngineNtop.cpp +++ b/src/LuaEngineNtop.cpp @@ -5409,6 +5409,8 @@ static int ntop_recipient_enqueue(lua_State* vm) { bool high_priority; const char *alert; bool rv = false; + AlertFifoItem notification; + AlertLevel alert_severity; if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR); recipient_id = lua_tointeger(vm, 1); @@ -5419,9 +5421,16 @@ static int ntop_recipient_enqueue(lua_State* vm) { if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR); alert = lua_tostring(vm, 3); - rv = ntop->recipient_enqueue(recipient_id, - high_priority ? recipient_notification_priority_high : recipient_notification_priority_low, - alert); + if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR); + alert_severity = (AlertLevel)lua_tonumber(vm, 4); + + if((notification.alert = strdup(alert))) { + notification.alert_severity = alert_severity; + + rv = ntop->recipient_enqueue(recipient_id, + high_priority ? recipient_notification_priority_high : recipient_notification_priority_low, + ¬ification); + } if(!rv) { NetworkInterface *iface = getCurrentInterface(vm); @@ -5431,6 +5440,9 @@ static int ntop_recipient_enqueue(lua_State* vm) { if(ctx->threaded_activity_stats) ctx->threaded_activity_stats->setAlertsDrops(); } + + if(notification.alert) + free(notification.alert); } lua_pushboolean(vm, rv); @@ -5442,7 +5454,8 @@ static int ntop_recipient_enqueue(lua_State* vm) { static int ntop_recipient_dequeue(lua_State* vm) { u_int16_t recipient_id; bool high_priority; - char *alert; + AlertFifoItem notification; + bool res; if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR); recipient_id = lua_tointeger(vm, 1); @@ -5450,12 +5463,17 @@ static int ntop_recipient_dequeue(lua_State* vm) { if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_ERROR); high_priority = lua_toboolean(vm, 2); - alert = ntop->recipient_dequeue(recipient_id, - high_priority ? recipient_notification_priority_high : recipient_notification_priority_low); + res = ntop->recipient_dequeue(recipient_id, + high_priority ? recipient_notification_priority_high : recipient_notification_priority_low, + ¬ification); - if(alert) { - lua_pushstring(vm, alert); - free(alert); + if(res && notification.alert) { + lua_newtable(vm); + + lua_push_str_table_entry(vm, "alert", notification.alert); + lua_push_uint64_table_entry(vm, "alert_severity", notification.alert_severity); + + free(notification.alert); } else lua_pushnil(vm); diff --git a/src/Ntop.cpp b/src/Ntop.cpp index a2484b6a8d..b63b8b0faf 100644 --- a/src/Ntop.cpp +++ b/src/Ntop.cpp @@ -982,14 +982,14 @@ void Ntop::lua_alert_queues_stats(lua_State* vm) { /* ******************************************* */ -bool Ntop::recipient_enqueue(u_int16_t recipient_id, RecipientNotificationPriority prio, const char * const notification) { +bool Ntop::recipient_enqueue(u_int16_t recipient_id, RecipientNotificationPriority prio, const AlertFifoItem* const notification) { return recipients.enqueue(recipient_id, prio, notification); } /* ******************************************* */ -char* Ntop::recipient_dequeue(u_int16_t recipient_id, RecipientNotificationPriority prio) { - return recipients.dequeue(recipient_id, prio); +bool Ntop::recipient_dequeue(u_int16_t recipient_id, RecipientNotificationPriority prio, AlertFifoItem *notification) { + return recipients.dequeue(recipient_id, prio, notification); } /* ******************************************* */ diff --git a/src/RecipientQueues.cpp b/src/RecipientQueues.cpp index 19922bae52..516786d5ad 100644 --- a/src/RecipientQueues.cpp +++ b/src/RecipientQueues.cpp @@ -40,49 +40,39 @@ RecipientQueues::~RecipientQueues() { /* *************************************** */ -char* RecipientQueues::dequeue(RecipientNotificationPriority prio) { - AlertFifoItem res; +bool RecipientQueues::dequeue(RecipientNotificationPriority prio, AlertFifoItem *notification) { + if(prio >= RECIPIENT_NOTIFICATION_MAX_NUM_PRIORITIES + || !queues_by_prio[prio] + || !notification) + return false; - if(prio >= RECIPIENT_NOTIFICATION_MAX_NUM_PRIORITIES || - !queues_by_prio[prio]) - return NULL; + *notification = queues_by_prio[prio]->dequeue(); - res = queues_by_prio[prio]->dequeue(); - - if(res.alert) + if(notification->alert) { last_use = time(NULL); + return true; + } - /* TODO return severity level */ - - return res.alert; + return false; } /* *************************************** */ -bool RecipientQueues::enqueue(RecipientNotificationPriority prio, const char * const notification) { +bool RecipientQueues::enqueue(RecipientNotificationPriority prio, const AlertFifoItem* const notification) { bool res = false; - AlertFifoItem item; - if(prio >= RECIPIENT_NOTIFICATION_MAX_NUM_PRIORITIES || - (!queues_by_prio[prio] && - !(queues_by_prio[prio] = new (nothrow) AlertFifoQueue(ALERTS_NOTIFICATIONS_QUEUE_SIZE)))) { + if(prio >= RECIPIENT_NOTIFICATION_MAX_NUM_PRIORITIES + || !notification + || !notification->alert + || (!queues_by_prio[prio] && + !(queues_by_prio[prio] = new (nothrow) AlertFifoQueue(ALERTS_NOTIFICATIONS_QUEUE_SIZE)))) { /* Queue not available */ drops_by_prio[prio]++; return false; } - /* Qnqueue the notification */ - - item.level = alert_level_none; /* TODO set severity level */ - item.alert = strdup(notification); - - if(item.alert) { - - res = queues_by_prio[prio]->enqueue(item); - - if (!res) - free(item.alert); - } + /* Enqueue the notification */ + res = queues_by_prio[prio]->enqueue(*notification); if(!res) drops_by_prio[prio]++; diff --git a/src/Recipients.cpp b/src/Recipients.cpp index aa141fc3c9..bfd62e93bc 100644 --- a/src/Recipients.cpp +++ b/src/Recipients.cpp @@ -38,11 +38,12 @@ Recipients::~Recipients() { /* *************************************** */ -char* Recipients::dequeue(u_int16_t recipient_id, RecipientNotificationPriority prio) { - char * res = NULL; +bool Recipients::dequeue(u_int16_t recipient_id, RecipientNotificationPriority prio, AlertFifoItem *notification) { + bool res = false; - if(recipient_id >= MAX_NUM_RECIPIENTS) - return NULL; + if(recipient_id >= MAX_NUM_RECIPIENTS + || !notification) + return false; m.lock(__FILE__, __LINE__); @@ -50,7 +51,7 @@ char* Recipients::dequeue(u_int16_t recipient_id, RecipientNotificationPriority /* Dequeue the notification for a given priority */ - res = recipient_queues[recipient_id]->dequeue(prio); + res = recipient_queues[recipient_id]->dequeue(prio, notification); } m.unlock(__FILE__, __LINE__); @@ -60,10 +61,11 @@ char* Recipients::dequeue(u_int16_t recipient_id, RecipientNotificationPriority /* *************************************** */ -bool Recipients::enqueue(u_int16_t recipient_id, RecipientNotificationPriority prio, const char * const notification) { +bool Recipients::enqueue(u_int16_t recipient_id, RecipientNotificationPriority prio, const AlertFifoItem* const notification) { bool res = false; - if(recipient_id >= MAX_NUM_RECIPIENTS) + if(recipient_id >= MAX_NUM_RECIPIENTS + || !notification) return false; m.lock(__FILE__, __LINE__);