diff options
Diffstat (limited to 'accel-pppd/logs')
-rw-r--r-- | accel-pppd/logs/CMakeLists.txt | 38 | ||||
-rw-r--r-- | accel-pppd/logs/log_syslog.c | 194 |
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); |