summaryrefslogtreecommitdiff
path: root/module
diff options
context:
space:
mode:
Diffstat (limited to 'module')
-rw-r--r--module/bsnmp-regex.c243
-rw-r--r--module/regex-tree.def2
2 files changed, 185 insertions, 60 deletions
diff --git a/module/bsnmp-regex.c b/module/bsnmp-regex.c
index 98a94a9..4a75a7c 100644
--- a/module/bsnmp-regex.c
+++ b/module/bsnmp-regex.c
@@ -1,10 +1,49 @@
+/*
+ * Copyright (c) 2006, Nate Nielsen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ *
+ * CONTRIBUTORS
+ * Nate Nielsen <nielsen@memberwebs.com>
+ */
#include "usuals.h"
+#include <sys/types.h>
+#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/un.h>
#include <syslog.h>
#include <unistd.h>
#include <stdarg.h>
@@ -23,7 +62,7 @@
#include "regex_oid.h"
#define DEFAULT_CONFIG CONF_PREFIX "/rrdbot"
-#define DEFAULT_FIFO "/var/run/snmp-regex.fifo"
+#define DEFAULT_SOCKET "/var/run/snmp-regex.sock"
/* our module handle */
static struct lmodule *module;
@@ -62,23 +101,32 @@ struct data_entry {
TAILQ_HEAD(data_entry_list, data_entry);
-/* list of peers */
+/* list of regexes */
static struct data_entry_list entries = TAILQ_HEAD_INITIALIZER(entries);
static uint32_t entry_count = 0;
-
/* 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;
+/* The socket to read from */
+static u_char *regex_sock = NULL;
+static int sock_fd = -1;
+static void *sock_sel = NULL;
-/* Buffer for parsing logs */
#define LINE_LENGTH 1024
-static char line_buffer[LINE_LENGTH];
+
+struct connection {
+ int fd;
+ void *sel;
+ char line_buffer[LINE_LENGTH];
+ TAILQ_ENTRY(connection) link;
+};
+
+TAILQ_HEAD(connection_list, connection);
+
+/* List of connections */
+static struct connection_list connections = TAILQ_HEAD_INITIALIZER(connections);
/* -----------------------------------------------------------------------------
* HELPERS
@@ -377,42 +425,55 @@ process_log (char *line, int len)
}
/* -----------------------------------------------------------------------------
- * LOG READING
+ * SOCKET HANDLING
*/
static void
-close_fifo ()
+close_connection (struct connection *conn)
{
- if (fifo_sel) {
- fd_deselect (fifo_sel);
- fifo_sel = NULL;
- }
+ if (conn->sel)
+ fd_deselect (conn->sel);
+ conn->sel = NULL;
- if (fifo_fd != -1) {
- close (fifo_fd);
- fifo_fd = -1;
- }
+ if (conn->fd >= 0)
+ close (conn->fd);
+ conn->fd = -1;
- memset (line_buffer, 0, sizeof (line_buffer));
+ free (conn);
+ TAILQ_REMOVE (&connections, conn, link);
}
static void
-receive_log (int fd, void *data)
+io_data (int fd, void *user_data)
{
+ struct connection *conn = (struct connection*)user_data;
+ char *line_buffer;
char *t;
int len;
int r, l;
- ASSERT (fd == fifo_fd);
+ fprintf(stderr, "io data\n");
+
+ ASSERT (fd == conn->fd);
+ line_buffer = conn->line_buffer;
len = strlen (line_buffer);
ASSERT (len < LINE_LENGTH);
+fprintf (stderr, "going to read: ");
do {
r = read (fd, line_buffer + len, (LINE_LENGTH - 1) - len);
+fprintf (stderr, "done: %d\n", r);
+ /* An error, close */
if (r < 0 && errno != EAGAIN) {
- emsg ("couldn't read from fifo: %s: %s", regex_fifo, strerror (errno));
+ emsg ("couldn't read from socket: %s: %s", regex_sock, strerror (errno));
+ close_connection (conn);
+ return;
+
+ /* Connection is finished, close */
+ } else if (r == 0) {
+ close_connection (conn);
return;
/* Got data, null terminate */
@@ -449,47 +510,114 @@ receive_log (int fd, void *data)
} while (r > 0);
}
+static void
+io_accept (int fd, void *unused)
+{
+ struct connection *conn;
+ int nfd;
+
+fprintf(stderr, "accepting sock\n");
+
+ nfd = accept (fd, NULL, NULL);
+ if (nfd < 0) {
+ if (errno != EAGAIN || errno != EINTR)
+ emsg ("couldn't accept socket connection: %s: %s", regex_sock, strerror (errno));
+ return;
+ }
+
+ fcntl (nfd, F_SETFL, O_NONBLOCK | fcntl(nfd, F_GETFL, 0));
+
+ conn = calloc (1, sizeof (*conn));
+ if (!conn) {
+ emsg ("out of memory");
+ close (nfd);
+ return;
+ }
+
+ conn->fd = nfd;
+ TAILQ_INSERT_HEAD (&connections, conn, link);
+
+ conn->sel = fd_select (nfd, io_data, conn, module);
+ if (!conn->sel) {
+ emsg ("couldn't list on socket connection: %s: %s", regex_sock, strerror (errno));
+ close_connection (conn);
+ }
+}
+
+static void
+close_sock ()
+{
+ struct connection *conn;
+
+ if (sock_sel)
+ fd_deselect (sock_sel);
+ sock_sel = NULL;
+
+ if (sock_fd != -1)
+ close (sock_fd);
+ sock_fd = -1;
+
+ while ((conn = TAILQ_FIRST(&connections)) != NULL)
+ close_connection (conn);
+}
+
static int
-open_fifo ()
+open_sock ()
{
struct stat sb;
+ struct sockaddr_un addr;
+ int len;
- close_fifo ();
+ close_sock ();
- ASSERT (regex_fifo && regex_fifo[0]);
+ ASSERT (regex_sock && regex_sock[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);
+ if (stat (regex_sock, &sb) == 0) {
+ /* Complain if it's not a sock */
+ if (!S_ISSOCK (sb.st_mode)) {
+ emsg ("file or directory already exists: %s", regex_sock);
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;
- }
+ /* If it's a socket delete */
+ unlink (regex_sock);
+
+ } else if (errno != ENOENT) {
+ emsg ("couldn't access file: %s: %s", regex_sock, strerror (errno));
+ return -1;
+ }
- } else {
- emsg ("couldn't access fifo: %s: %s", regex_fifo, strerror (errno));
+ /* Create socket and ... */
+ sock_fd = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (sock_fd < 0) {
+ emsg ("couldn't create socket: %s", strerror (errno));
return -1;
}
- fifo_fd = open (regex_fifo, O_RDONLY | O_NONBLOCK);
- if (fifo_fd < 0) {
- emsg ("couldn't open fifo: %s: %s", regex_fifo, strerror (errno));
+ memset (&addr, 0, sizeof (addr));
+ addr.sun_family = AF_UNIX;
+ strlcpy (addr.sun_path, regex_sock, sizeof (addr.sun_path));
+ len = sizeof(addr) - (sizeof(addr.sun_path) - strlen (addr.sun_path));
+
+ /* ... bind and ... */
+ if (bind (sock_fd, (struct sockaddr*)&addr, len) != 0) {
+ emsg ("couldn't bind to socket: %s: %s", regex_sock, 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));
+ /* ... listen to it ... */
+ if (listen (sock_fd, 5) < 0) {
+ emsg ("couldn't listen on socket: %s: %s", regex_sock, strerror (errno));
+ return -1;
+ }
+
+ /* ... watch for new connections ... */
+ sock_sel = fd_select (sock_fd, io_accept, NULL, module);
+ if (!sock_sel) {
+ emsg ("couldn't listen on socket: %s: %s", regex_sock, strerror (errno));
return -1;
}
- memset (line_buffer, 0, sizeof (line_buffer));
return 0;
}
@@ -816,10 +944,10 @@ op_regexconfig (struct snmp_context *ctx, struct snmp_value *value,
return r;
- case LEAF_regexFifo:
+ case LEAF_regexSocket:
if (op == SNMP_OP_GET)
- return string_get (value, regex_fifo, -1);
+ return string_get (value, regex_sock, -1);
/* Remainder only at initialization */
if (community != COMM_INITIALIZE)
@@ -827,10 +955,10 @@ 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) {
- if (!regex_fifo[0])
+ if ((r = string_save (value, ctx, -1, &regex_sock)) == SNMP_ERR_NOERROR) {
+ if (!regex_sock[0])
r = SNMP_ERR_WRONG_VALUE;
- else if (open_fifo () < 0)
+ else if (open_sock () < 0)
r = SNMP_ERR_GENERR;
}
if (r != SNMP_ERR_NOERROR)
@@ -840,7 +968,7 @@ op_regexconfig (struct snmp_context *ctx, struct snmp_value *value,
string_commit (ctx);
break;
case SNMP_OP_ROLLBACK:
- string_rollback (ctx, &regex_fifo);
+ string_rollback (ctx, &regex_sock);
break;
default:
ASSERT(0);
@@ -975,8 +1103,8 @@ module_init (struct lmodule *mod, int argc, char *argv[])
if (!regex_config)
return ENOMEM;
- regex_fifo = strdup (DEFAULT_FIFO);
- if (!regex_fifo) {
+ regex_sock = strdup (DEFAULT_SOCKET);
+ if (!regex_sock) {
free (regex_config);
return ENOMEM;
}
@@ -989,9 +1117,6 @@ static void
module_start (void)
{
reg_index = or_register (&oid_regex, "The MIB for regex data.", module);
-
- /* Initial reads */
- receive_log (fifo_fd, NULL);
}
/* Called, when the module is to be unloaded after it was successfully loaded */
@@ -1004,10 +1129,10 @@ module_fini (void)
ASSERT (regex_config);
free (regex_config);
- ASSERT (regex_fifo);
- free (regex_fifo);
+ ASSERT (regex_sock);
+ free (regex_sock);
- close_fifo ();
+ close_sock ();
config_free_all ();
return 0;
diff --git a/module/regex-tree.def b/module/regex-tree.def
index aaab8bb..366dc0e 100644
--- a/module/regex-tree.def
+++ b/module/regex-tree.def
@@ -6,7 +6,7 @@
(203 regexData
# Valid only during configuration
(0 regexConfig OCTETSTRING op_regexconfig GET SET)
- (1 regexFifo OCTETSTRING op_regexconfig GET SET)
+ (1 regexSocket OCTETSTRING op_regexconfig GET SET)
(10 regexCount INTEGER op_regex GET)
(11 regexEntry : INTEGER op_regexentry