Initial handling for environment events

This commit is contained in:
Davidson Francis 2024-07-17 22:41:58 -03:00
parent 25bc29f174
commit 17c7f129e3
9 changed files with 145 additions and 30 deletions

View File

@ -5,7 +5,6 @@
#define _POSIX_C_SOURCE 200809L #define _POSIX_C_SOURCE 200809L
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <pthread.h> #include <pthread.h>
#include "alertik.h" #include "alertik.h"
@ -15,35 +14,32 @@
#include "notifiers.h" #include "notifiers.h"
#include "syslog.h" #include "syslog.h"
/* Misc. */ /*
#define LAST_SENT_THRESHOLD_SECS 10 /* Minimum time (in secs) between two */ * Alertik
time_t time_last_sent_notify; /* notifications. */ */
static void *handle_messages(void *p) static void *handle_messages(void *p)
{ {
((void)p); ((void)p);
size_t i;
int handled = 0;
struct log_event ev = {0}; struct log_event ev = {0};
while (syslog_pop_msg_from_fifo(&ev) >= 0) { while (syslog_pop_msg_from_fifo(&ev) >= 0) {
print_log_event(&ev); print_log_event(&ev);
if ((time(NULL) - time_last_sent_notify) <= LAST_SENT_THRESHOLD_SECS) { if (!is_within_notify_threshold()) {
log_msg("ignoring, reason: too many notifications!\n"); log_msg("ignoring, reason: too many notifications!\n");
continue; continue;
} }
/* Check if it belongs to any of our desired events. */ handled = process_static_event(&ev);
for (i = 0; i < NUM_EVENTS; i++) { handled += process_environment_event(&ev);
if (strstr(ev.msg, handlers[i].str)) {
handlers[i].hnd(&ev);
break;
}
}
if (i == NUM_EVENTS) if (handled)
log_msg("> No match!\n"); update_notify_last_sent();
else
log_msg("> Not handled!\n");
} }
return NULL; return NULL;
} }
@ -53,6 +49,10 @@ int main(void)
pthread_t handler; pthread_t handler;
int fd; int fd;
/* TODO: remove setup_notifiers()..
* think about env vars for the static events too, like enable/disable
*/
log_init(); log_init();
setup_notifiers(); setup_notifiers();
init_environment_events(); init_environment_events();

View File

@ -10,7 +10,6 @@
#define MIN(a,b) (((a)<(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b))
extern time_t time_last_sent_notify;
extern char *get_formatted_time(time_t time, char *time_str); extern char *get_formatted_time(time_t time, char *time_str);
extern void log_msg(const char *fmt, ...); extern void log_msg(const char *fmt, ...);
extern int send_telegram_notification(const char *msg); extern int send_telegram_notification(const char *msg);

View File

@ -11,6 +11,7 @@
#include <string.h> #include <string.h>
#include "log.h" #include "log.h"
#include "events.h"
#include "env_events.h" #include "env_events.h"
#include "alertik.h" #include "alertik.h"
#include "notifiers.h" #include "notifiers.h"
@ -20,6 +21,7 @@
static const char *const match_types[] = {"substr", "regex"}; static const char *const match_types[] = {"substr", "regex"};
/* Environment events list. */ /* Environment events list. */
static int num_env_events;
struct env_event env_events[MAX_ENV_EVENTS] = {0}; struct env_event env_events[MAX_ENV_EVENTS] = {0};
/** /**
@ -80,30 +82,89 @@ get_event_idx(int ev_num, char *str, const char *const *str_list, int size)
panic("String parameter (%s) invalid for %s\n", env, str); panic("String parameter (%s) invalid for %s\n", env, str);
} }
/**/
static int handle_regex(struct log_event *ev, int idx_env)
{
((void)ev);
((void)idx_env);
return 0;
}
/**/
static int handle_substr(struct log_event *ev, int idx_env)
{
int notif_idx;
char time_str[32] = {0};
struct env_event *env_ev;
char notification_message[2048] = {0};
env_ev = &env_events[idx_env];
notif_idx = env_ev->ev_notifier_idx;
if (!strstr(ev->msg, env_ev->ev_match_str))
return 0;
log_msg("> Environment event detected!\n");
log_msg("> type: substr, match: (%s), notifier: %s\n",
env_ev->ev_match_str, notifiers_str[notif_idx]);
/* Format the message. */
snprintf(
notification_message,
sizeof notification_message - 1,
"%s, at: %s",
env_ev->ev_mask_msg,
get_formatted_time(ev->timestamp, time_str)
);
if (notifiers[notif_idx].send_notification(notification_message) < 0)
log_msg("unable to send the notification through %s\n",
notifiers_str[notif_idx]);
return 1;
}
/**
* @brief Given an environment-variable event, checks if it
* belongs to one of the registered events and then, handle
* it.
*
* @param ev Event to be processed.
*
* @return Returns the amount of matches, 0 if none (not handled).
*/
int process_environment_event(struct log_event *ev)
{
int i;
int handled;
for (i = 0, handled = 0; i < num_env_events; i++) {
if (env_events[i].ev_match_type == EVNT_SUBSTR)
handled += handle_substr(ev, i);
else
handled += handle_regex(ev, i);
}
return handled;
}
/**/ /**/
int init_environment_events(void) int init_environment_events(void)
{ {
char *tmp; char *tmp;
int events;
tmp = getenv("ENV_EVENTS"); tmp = getenv("ENV_EVENTS");
if (!tmp || (str2int(&events, tmp) < 0) || events <= 0) {
if (!tmp || (str2int(&num_env_events, tmp) < 0) || num_env_events <= 0) {
log_msg("Environment events not detected, disabling...\n"); log_msg("Environment events not detected, disabling...\n");
return (0); return (0);
} }
if (events >= MAX_ENV_EVENTS) if (num_env_events >= MAX_ENV_EVENTS)
panic("Environment events exceeds the maximum supported (%d/%d)\n", panic("Environment ENV_EVENTS exceeds the maximum supported (%d/%d)\n",
events, MAX_ENV_EVENTS); num_env_events, MAX_ENV_EVENTS);
log_msg("%d environment events found, registering...\n"); log_msg("%d environment events found, registering...\n");
for (int i = 0; i < events; i++) { for (int i = 0; i < num_env_events; i++) {
/* EVENTn_MATCH_TYPE. */ /* EVENTn_MATCH_TYPE. */
env_events[i].ev_match_type = get_event_idx(i, "MATCH_TYPE", env_events[i].ev_match_type = get_event_idx(i, "MATCH_TYPE",
match_types, MATCH_TYPES_LEN); match_types, MATCH_TYPES_LEN);
@ -117,7 +178,7 @@ int init_environment_events(void)
} }
log_msg("Environment events summary:\n"); log_msg("Environment events summary:\n");
for (int i = 0; i < events; i++) { for (int i = 0; i < num_env_events; i++) {
printf( printf(
"EVENT%d_MATCH_TYPE: %s\n" "EVENT%d_MATCH_TYPE: %s\n"
"EVENT%d_MATCH_STR: %s\n" "EVENT%d_MATCH_STR: %s\n"
@ -128,7 +189,9 @@ int init_environment_events(void)
i, notifiers_str[env_events[i].ev_notifier_idx], i, notifiers_str[env_events[i].ev_notifier_idx],
i, env_events[i].ev_mask_msg i, env_events[i].ev_mask_msg
); );
}
/* Try to setup notifier if not yet. */
notifiers[env_events[i].ev_notifier_idx].setup();
}
return (0); return (0);
} }

View File

@ -7,6 +7,7 @@
#define ENV_EVENTS_H #define ENV_EVENTS_H
#define MAX_ENV_EVENTS 16 #define MAX_ENV_EVENTS 16
struct log_event;
struct env_event { struct env_event {
int ev_match_type; /* whether regex or str. */ int ev_match_type; /* whether regex or str. */
@ -17,5 +18,6 @@
extern struct env_event env_events[MAX_ENV_EVENTS]; extern struct env_event env_events[MAX_ENV_EVENTS];
extern int init_environment_events(void); extern int init_environment_events(void);
extern int process_environment_event(struct log_event *ev);
#endif /* ENV_EVENTS_H */ #endif /* ENV_EVENTS_H */

View File

@ -21,6 +21,29 @@ struct ev_handler handlers[NUM_EVENTS] = {
/* Add new handlers here. */ /* Add new handlers here. */
}; };
/**
* @brief Given an event, checks if it belongs to one of the
* registered events and then, handle it.
*
* @param ev Event to be processed.
*
* @return Returns the amount of matches, 0 if none (not handled).
*/
int process_static_event(struct log_event *ev)
{
int i;
int handled;
for (i = 0, handled = 0; i < NUM_EVENTS; i++) {
if (strstr(ev->msg, handlers[i].str)) {
handlers[i].hnd(ev);
handled += 1;
}
}
return handled;
}
///////////////////////////// FAILED LOGIN ATTEMPTS /////////////////////////// ///////////////////////////// FAILED LOGIN ATTEMPTS ///////////////////////////
static int static int
parse_login_attempt_msg(const char *msg, char *wifi_iface, char *mac_addr) parse_login_attempt_msg(const char *msg, char *wifi_iface, char *mac_addr)

View File

@ -11,8 +11,8 @@
#define MSG_MAX 2048 #define MSG_MAX 2048
#define NUM_EVENTS 1 #define NUM_EVENTS 1
#define EVNT_SUBSTR 1 #define EVNT_SUBSTR 0
#define EVNT_REGEX 2 #define EVNT_REGEX 1
/* Log event. */ /* Log event. */
struct log_event { struct log_event {
@ -27,5 +27,6 @@
}; };
extern struct ev_handler handlers[NUM_EVENTS]; extern struct ev_handler handlers[NUM_EVENTS];
extern int process_static_event(struct log_event *ev);
#endif /* EVENTS_H */ #endif /* EVENTS_H */

1
log.h
View File

@ -8,6 +8,7 @@
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <sys/types.h> #include <sys/types.h>
struct log_event; struct log_event;

View File

@ -12,6 +12,13 @@
#include "notifiers.h" #include "notifiers.h"
#include "alertik.h" #include "alertik.h"
/*
* Notification handling/notifiers
*/
/* EPOCH in secs of last sent notification. */
static time_t time_last_sent_notify;
/* Just to omit the print to stdout. */ /* Just to omit the print to stdout. */
size_t libcurl_noop_cb(void *ptr, size_t size, size_t nmemb, void *data) { size_t libcurl_noop_cb(void *ptr, size_t size, size_t nmemb, void *data) {
((void)ptr); ((void)ptr);
@ -19,6 +26,16 @@ size_t libcurl_noop_cb(void *ptr, size_t size, size_t nmemb, void *data) {
return size * nmemb; return size * nmemb;
} }
/**/
void update_notify_last_sent(void) {
time_last_sent_notify = time(NULL);
}
/**/
int is_within_notify_threshold(void) {
return (time(NULL) - time_last_sent_notify) > LAST_SENT_THRESHOLD_SECS;
}
//////////////////////////////// TELEGRAM ////////////////////////////////////// //////////////////////////////// TELEGRAM //////////////////////////////////////
/* Telegram & request settings. */ /* Telegram & request settings. */
static char *telegram_bot_token; static char *telegram_bot_token;
@ -26,6 +43,10 @@ static char *telegram_chat_id;
void setup_telegram(void) void setup_telegram(void)
{ {
static int setup = 0;
if (setup)
return;
telegram_bot_token = getenv("TELEGRAM_BOT_TOKEN"); telegram_bot_token = getenv("TELEGRAM_BOT_TOKEN");
telegram_chat_id = getenv("TELEGRAM_CHAT_ID"); telegram_chat_id = getenv("TELEGRAM_CHAT_ID");
if (!telegram_bot_token || !telegram_chat_id) { if (!telegram_bot_token || !telegram_chat_id) {
@ -36,6 +57,7 @@ void setup_telegram(void)
"- TELEGRAM_CHAT_ID\n" "- TELEGRAM_CHAT_ID\n"
); );
} }
setup = 1;
} }
int send_telegram_notification(const char *msg) int send_telegram_notification(const char *msg)
@ -87,8 +109,7 @@ int send_telegram_notification(const char *msg)
log_msg("> Unable to send request!\n"); log_msg("> Unable to send request!\n");
goto error; goto error;
} else { } else {
time_last_sent_notify = time(NULL); /* Update the time of our last sent */ log_msg("> Done!\n");
log_msg("> Done!\n"); /* notification. */
} }
#endif #endif

View File

@ -16,6 +16,9 @@
#define NUM_NOTIFIERS 1 #define NUM_NOTIFIERS 1
/* Minimum time (in secs) between two */
#define LAST_SENT_THRESHOLD_SECS 10
/* Notifiers list, like: /* Notifiers list, like:
* - Telegram * - Telegram
* - Slack * - Slack
@ -32,5 +35,7 @@
extern struct notifier notifiers[NUM_NOTIFIERS]; extern struct notifier notifiers[NUM_NOTIFIERS];
extern void setup_notifiers(void); extern void setup_notifiers(void);
extern int is_within_notify_threshold(void);
extern void update_notify_last_sent(void);
#endif /* NOTIFIERS_H */ #endif /* NOTIFIERS_H */