summaryrefslogtreecommitdiff
path: root/accel-pppd/logs
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/logs')
-rw-r--r--accel-pppd/logs/CMakeLists.txt38
-rw-r--r--accel-pppd/logs/log_syslog.c194
2 files changed, 226 insertions, 6 deletions
diff --git a/accel-pppd/logs/CMakeLists.txt b/accel-pppd/logs/CMakeLists.txt
index ce909b67..b10163f4 100644
--- a/accel-pppd/logs/CMakeLists.txt
+++ b/accel-pppd/logs/CMakeLists.txt
@@ -1,11 +1,37 @@
-ADD_LIBRARY(log_file SHARED log_file.c)
-TARGET_LINK_LIBRARIES(log_file rt)
+IF(NOT DEFINED LOG_FILE)
+ SET(LOG_FILE TRUE)
+ENDIF(NOT DEFINED LOG_FILE)
-ADD_LIBRARY(log_tcp SHARED log_tcp.c)
+IF(NOT DEFINED LOG_TCP)
+ SET(LOG_TCP TRUE)
+ENDIF(NOT DEFINED LOG_TCP)
-INSTALL(TARGETS log_file log_tcp
- LIBRARY DESTINATION lib/accel-ppp
-)
+IF(NOT DEFINED LOG_SYSLOG)
+ SET(LOG_SYSLOG TRUE)
+ENDIF(NOT DEFINED LOG_SYSLOG)
+
+
+IF(LOG_FILE)
+ ADD_LIBRARY(log_file SHARED log_file.c)
+ TARGET_LINK_LIBRARIES(log_file rt)
+ INSTALL(TARGETS log_file
+ LIBRARY DESTINATION lib/accel-ppp
+ )
+ENDIF(LOG_FILE)
+
+IF(LOG_TCP)
+ ADD_LIBRARY(log_tcp SHARED log_tcp.c)
+ INSTALL(TARGETS log_tcp
+ LIBRARY DESTINATION lib/accel-ppp
+ )
+ENDIF(LOG_TCP)
+
+IF(LOG_SYSLOG)
+ ADD_LIBRARY(log_syslog SHARED log_syslog.c)
+ INSTALL(TARGETS log_syslog
+ LIBRARY DESTINATION lib/accel-ppp
+ )
+ENDIF(LOG_SYSLOG)
IF(LOG_PGSQL)
ADD_LIBRARY(log_pgsql SHARED log_pgsql.c)
diff --git a/accel-pppd/logs/log_syslog.c b/accel-pppd/logs/log_syslog.c
new file mode 100644
index 00000000..7dfa260d
--- /dev/null
+++ b/accel-pppd/logs/log_syslog.c
@@ -0,0 +1,194 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <syslog.h>
+
+#include "triton.h"
+#include "spinlock.h"
+#include "log.h"
+#include "list.h"
+#include "events.h"
+#include "ppp.h"
+
+#include "memdebug.h"
+
+static int conf_queue_max = 1000;
+
+static void syslog_close(struct triton_context_t *ctx);
+
+static struct triton_context_t syslog_ctx = {
+ .close = syslog_close,
+ .before_switch = log_switch,
+};
+
+static LIST_HEAD(msg_queue);
+static int queue_size;
+static int sleeping = 1;
+static spinlock_t queue_lock = SPINLOCK_INITIALIZER;
+static char *log_buf;
+static int need_close;
+static char *ident;
+static int prio_map[] = {LOG_INFO, LOG_ERR, LOG_WARNING, LOG_INFO, LOG_INFO, LOG_DEBUG};
+
+static void unpack_msg(struct log_msg_t *msg)
+{
+ struct log_chunk_t *chunk;
+ int pos;
+
+ strcpy(log_buf, msg->hdr->msg);
+ pos = strlen(log_buf);
+
+ list_for_each_entry(chunk, msg->chunks, entry) {
+ memcpy(log_buf + pos, chunk->msg, chunk->len);
+ pos += chunk->len;
+ }
+
+ if (pos > 1)
+ log_buf[pos - 1] = 0;
+ else
+ log_buf[0] = 0;
+}
+
+static void set_hdr(struct log_msg_t *msg, struct ppp_t *ppp)
+{
+ if (ppp)
+ sprintf(msg->hdr->msg, "%s:%s: ", ppp->ifname, ppp->username ? ppp->username : "");
+ else
+ msg->hdr->msg[0] = 0;
+}
+
+static void do_syslog(void)
+{
+ struct log_msg_t *msg;
+
+ while (1) {
+ spin_lock(&queue_lock);
+ if (list_empty(&msg_queue)) {
+ sleeping = 1;
+ spin_unlock(&queue_lock);
+ if (need_close)
+ triton_context_unregister(&syslog_ctx);
+ return;
+ }
+
+ msg = list_entry(msg_queue.next, typeof(*msg), entry);
+ list_del(&msg->entry);
+ --queue_size;
+ spin_unlock(&queue_lock);
+
+ unpack_msg(msg);
+ syslog(prio_map[msg->level], "%s", log_buf);
+ log_free_msg(msg);
+ }
+}
+
+static void queue_log(struct log_msg_t *msg)
+{
+ int r = 0, f = 0;
+ spin_lock(&queue_lock);
+ if (queue_size < conf_queue_max) {
+ list_add_tail(&msg->entry, &msg_queue);
+ ++queue_size;
+ r = sleeping;
+ sleeping = 0;
+ } else
+ f = 1;
+ spin_unlock(&queue_lock);
+
+ if (r)
+ triton_context_call(&syslog_ctx, (void (*)(void*))do_syslog, NULL);
+ else if (f)
+ log_free_msg(msg);
+}
+
+
+static void general_log(struct log_target_t *t, struct log_msg_t *msg, struct ppp_t *ppp)
+{
+ set_hdr(msg, ppp);
+
+ if (syslog_ctx.tpd)
+ queue_log(msg);
+ else {
+ unpack_msg(msg);
+ syslog(prio_map[msg->level], "%s", log_buf);
+ log_free_msg(msg);
+ }
+}
+
+static void syslog_close(struct triton_context_t *ctx)
+{
+ spin_lock(&queue_lock);
+ if (sleeping) {
+ triton_context_unregister(&syslog_ctx);
+ } else
+ need_close = 1;
+ spin_unlock(&queue_lock);
+}
+
+static struct log_target_t target = {
+ .log = general_log,
+};
+
+static void parse_opt(const char *opt, char **ident, int *facility)
+{
+ char *str = _strdup(opt);
+ char *ptr, *endptr;
+ int n;
+ const char *facility_name[] = {"daemon", "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7"};
+ const int facility_num[] = {LOG_DAEMON, LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7};
+
+ ptr = strchr(str, ',');
+ if (ptr) {
+ *ptr = 0;
+ n = strtol(ptr + 1, &endptr, 10);
+ if (*endptr) {
+ for (n = 0; n < sizeof(facility_name); n++) {
+ if (!strcasecmp(ptr + 1, facility_name[n]))
+ break;
+ }
+ if (n == sizeof(facility_name))
+ log_emerg("log_syslog: unknown facility name '%s'\n", ptr + 1);
+ else
+ *facility = facility_num[n];
+ } else
+ *facility = n;
+ }
+
+ *ident = str;
+}
+
+static void load_config()
+{
+ const char *opt;
+ int facility = LOG_DAEMON;
+
+ if (ident) {
+ closelog();
+ _free(ident);
+ }
+
+ opt = conf_get_opt("log", "syslog");
+ if (opt)
+ parse_opt(opt, &ident, &facility);
+ else
+ ident = _strdup("accel-pppd");
+
+ openlog(ident, 0, facility);
+}
+
+static void init(void)
+{
+ log_buf = malloc(LOG_MAX_SIZE + 1);
+
+ load_config();
+
+ triton_context_register(&syslog_ctx, NULL);
+ triton_context_wakeup(&syslog_ctx);
+
+ log_register_target(&target);
+
+ triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config);
+}
+
+DEFINE_INIT(1, init);