diff options
-rw-r--r-- | src/bsnmp-regex.c | 179 |
1 files changed, 159 insertions, 20 deletions
diff --git a/src/bsnmp-regex.c b/src/bsnmp-regex.c index 785659b..93b9ac2 100644 --- a/src/bsnmp-regex.c +++ b/src/bsnmp-regex.c @@ -3,10 +3,12 @@ #include <sys/queue.h> #include <sys/select.h> +#include <sys/stat.h> #include <syslog.h> #include <unistd.h> #include <stdarg.h> #include <ctype.h> +#include <fcntl.h> #include <bsnmp/snmpmod.h> #include <pcre.h> @@ -15,6 +17,7 @@ #include "regex_oid.h" #define DEFAULT_CONFIG CONF_PREFIX "/rrdbot" +#define DEFAULT_FIFO "/var/run/snmp-regex.fifo" /* TODO: Configure this properly */ /* our module handle */ static struct lmodule *module; @@ -53,11 +56,19 @@ TAILQ_HEAD(data_entry_list, data_entry); static struct data_entry_list entries = TAILQ_HEAD_INITIALIZER(entries); static uint32_t entry_count = 0; -static char *config_memory = NULL; /* configuration */ static u_char *regex_config = NULL; +static char *config_memory = NULL; + +/* The FIFO log */ static u_char *regex_fifo = NULL; +static int fifo_fd = -1; +static void *fifo_sel = NULL; + +/* Buffer for parsing logs */ +#define LINE_LENGTH 1024 +static char line_buffer[LINE_LENGTH]; /* ----------------------------------------------------------------------------- * HELPERS @@ -112,6 +123,129 @@ strtrim (char* data) } /* ----------------------------------------------------------------------------- + * LOG READING AND MATCHING + */ + +static void +close_fifo () +{ + if (fifo_sel) { + fd_deselect (fifo_sel); + fifo_sel = NULL; + } + + if (fifo_fd != -1) { + close (fifo_fd); + fifo_fd = -1; + } + + memset (line_buffer, 0, sizeof (line_buffer)); +} + +static void +process_log (char *line) +{ + fprintf (stderr, "log line: %s\n", line); +} + +static void +receive_log (int fd, void *data) +{ + char *t; + int len; + int r, l; + + ASSERT (fd == fifo_fd); + + len = strlen (line_buffer); + ASSERT (len < LINE_LENGTH); + + do { + r = read (fd, line_buffer + len, (LINE_LENGTH - 1) - len); + + if (r < 0 && errno != EAGAIN) { + emsg ("couldn't read from fifo: %s: %s", regex_fifo, strerror (errno)); + return; + + /* Got data, null terminate */ + } else if (r > 0) { + len += r; + ASSERT (len < LINE_LENGTH); + line_buffer[len] = 0; + } + + /* Break really long lines */ + if (len >= LINE_LENGTH - 1) + line_buffer[len - 1] = '\n'; + + for (;;) { + t = strchr (line_buffer, '\n'); + if (t == NULL) + break; + + /* Break line (also DOS line) */ + *t = 0; + if (line_buffer != t && *(t - 1) == '\r') + *(t - 1) = 0; + + /* Send it off */ + process_log (line_buffer); + + /* Move data to front of buffer */ + l = (t + 1) - line_buffer; + ASSERT (l <= len); + memmove (line_buffer, t + 1, (len - l) + 1); + len -= l; + } + + } while (r > 0); +} + +static int +open_fifo () +{ + struct stat sb; + + close_fifo (); + + ASSERT (regex_fifo && regex_fifo[0]); + + if (stat (regex_fifo, &sb) == 0) { + /* Complain if it's not a FIFO */ + if (!S_ISFIFO (sb.st_mode)) { + emsg ("file or directory already exists: %s", regex_fifo); + return -1; + } + + } else if (errno != ENOENT) { + /* Try and create it */ + if (mkfifo (regex_fifo, S_IRWXU | S_IRWXG | S_IRWXO) < 0) { + emsg ("couldn't create fifo: %s: %s", regex_fifo, strerror (errno)); + return -1; + } + + } else { + emsg ("couldn't access fifo: %s: %s", regex_fifo, strerror (errno)); + return -1; + } + + fifo_fd = open (regex_fifo, O_RDONLY); + if (fifo_fd < 0) { + emsg ("couldn't open fifo: %s: %s", regex_fifo, strerror (errno)); + return -1; + } + + fifo_sel = fd_select (fifo_fd, receive_log, NULL, module); + if (!fifo_sel) { + emsg ("couldn't listen on fifo: %s: %s", regex_fifo, strerror (errno)); + return -1; + } + + memset (line_buffer, 0, sizeof (line_buffer)); + return 0; +} + +/* ----------------------------------------------------------------------------- * CONFIG PARSING */ @@ -271,9 +405,7 @@ config_read () FILE *f = NULL; long len; - /* XXXXXXXXXXXxx Move DEFAULT_CONFIG settings to init */ - if (!regex_config || !regex_config[0]) - regex_config = DEFAULT_CONFIG; + ASSERT (regex_config && regex_config[0]); f = fopen (regex_config, "r"); if (f == NULL) { @@ -378,7 +510,7 @@ op_regexconfig (struct snmp_context *ctx, struct snmp_value *value, u_int sub, u_int iidx, enum snmp_op op) { asn_subid_t which = value->var.subs[sub - 1]; - int r; + int r = SNMP_ERR_NOERROR; switch (which) { case LEAF_regexConfig: @@ -392,12 +524,14 @@ op_regexconfig (struct snmp_context *ctx, struct snmp_value *value, switch (op) { case SNMP_OP_SET: - if ((r = string_save (value, ctx, -1, ®ex_config)) != SNMP_ERR_NOERROR) - return r; - if (config_parse () < 0) { - string_rollback (ctx, ®ex_config); - return SNMP_ERR_GENERR; + if ((r = string_save (value, ctx, -1, ®ex_config)) == SNMP_ERR_NOERROR) { + if (!regex_config[0]) + r = SNMP_ERR_WRONG_VALUE; + else if (config_parse () < 0) + r = SNMP_ERR_GENERR; } + if (r != SNMP_ERR_NOERROR) + string_rollback (ctx, ®ex_config); break; case SNMP_OP_COMMIT: string_commit (ctx); @@ -410,7 +544,7 @@ op_regexconfig (struct snmp_context *ctx, struct snmp_value *value, break; } - return SNMP_ERR_NOERROR; + return r; case LEAF_regexFifo: @@ -424,13 +558,14 @@ op_regexconfig (struct snmp_context *ctx, struct snmp_value *value, switch (op) { case SNMP_OP_SET: - if ((r = string_save (value, ctx, -1, ®ex_fifo)) != SNMP_ERR_NOERROR) - return r; - /* TODO: Make and open the FIFO here.... - if (config_parse () < 0) { + if ((r = string_save (value, ctx, -1, ®ex_fifo)) == SNMP_ERR_NOERROR) { + if (!regex_fifo[0]) + r = SNMP_ERR_WRONG_VALUE; + else if (open_fifo () < 0) + r = SNMP_ERR_GENERR; + } + if (r != SNMP_ERR_NOERROR) string_rollback (ctx, ®ex_config); - return SNMP_ERR_GENERR; - } */ break; case SNMP_OP_COMMIT: string_commit (ctx); @@ -443,7 +578,7 @@ op_regexconfig (struct snmp_context *ctx, struct snmp_value *value, break; } - return SNMP_ERR_NOERROR; + return r; } ASSERT(0); @@ -559,11 +694,11 @@ module_init (struct lmodule *mod, int argc, char *argv[]) return EINVAL; } - regex_config = strdup (""); + regex_config = strdup (DEFAULT_CONFIG); if (!regex_config) return ENOMEM; - regex_fifo = strdup (""); + regex_fifo = strdup (DEFAULT_FIFO); if (!regex_fifo) { free (regex_config); return ENOMEM; @@ -592,6 +727,10 @@ module_fini (void) ASSERT (regex_fifo); free (regex_fifo); + close_fifo (); + config_free_all (); + + return 0; } |