summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bsnmp-regex.c179
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, &regex_config)) != SNMP_ERR_NOERROR)
- return r;
- if (config_parse () < 0) {
- string_rollback (ctx, &regex_config);
- return SNMP_ERR_GENERR;
+ if ((r = string_save (value, ctx, -1, &regex_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, &regex_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, &regex_fifo)) != SNMP_ERR_NOERROR)
- return r;
- /* TODO: Make and open the FIFO here....
- if (config_parse () < 0) {
+ if ((r = string_save (value, ctx, -1, &regex_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, &regex_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;
}