X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fjournal%2Fjournald-syslog.c;h=b826e23c016b1be84e6ca6c1277c41496d70a6dd;hp=12c5b2849ce66ea11e5841b0f62f9527f01c1ead;hb=03ee5c38cb0da193dd08733fb4c0c2809cee6a99;hpb=5809560d858f45351856d6fe786a8117306dd0f2 diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c index 12c5b2849..b826e23c0 100644 --- a/src/journal/journald-syslog.c +++ b/src/journal/journald-syslog.c @@ -20,36 +20,44 @@ ***/ #include +#include #include +#include "systemd/sd-messages.h" #include "socket-util.h" -#include "journald.h" +#include "selinux-util.h" +#include "journald-server.h" #include "journald-syslog.h" #include "journald-kmsg.h" +#include "journald-console.h" +#include "journald-wall.h" + +/* Warn once every 30s if we missed syslog message */ +#define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC) static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, struct ucred *ucred, struct timeval *tv) { - struct msghdr msghdr; + + union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/journal/syslog", + }; + struct msghdr msghdr = { + .msg_iov = (struct iovec *) iovec, + .msg_iovlen = n_iovec, + .msg_name = &sa, + .msg_namelen = offsetof(union sockaddr_union, un.sun_path) + + strlen("/run/systemd/journal/syslog"), + }; struct cmsghdr *cmsg; union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; } control; - union sockaddr_union sa; assert(s); assert(iovec); assert(n_iovec > 0); - zero(msghdr); - msghdr.msg_iov = (struct iovec*) iovec; - msghdr.msg_iovlen = n_iovec; - - zero(sa); - sa.un.sun_family = AF_UNIX; - strncpy(sa.un.sun_path, "/run/systemd/journal/syslog", sizeof(sa.un.sun_path)); - msghdr.msg_name = &sa; - msghdr.msg_namelen = offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path); - if (ucred) { zero(control); msghdr.msg_control = &control; @@ -72,8 +80,10 @@ static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned /* The socket is full? I guess the syslog implementation is * too slow, and we shouldn't wait for that... */ - if (errno == EAGAIN) + if (errno == EAGAIN) { + s->n_forward_syslog_missed++; return; + } if (ucred && errno == ESRCH) { struct ucred u; @@ -89,8 +99,10 @@ static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0) return; - if (errno == EAGAIN) + if (errno == EAGAIN) { + s->n_forward_syslog_missed++; return; + } } if (errno != ENOENT) @@ -147,7 +159,7 @@ void server_forward_syslog(Server *s, int priority, const char *identifier, cons identifier = ident_buf; } - snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid); + snprintf(header_pid, sizeof(header_pid), "["PID_FMT"]: ", ucred->pid); char_array_0(header_pid); if (identifier) @@ -175,7 +187,7 @@ int syslog_fixup_facility(int priority) { return priority; } -void syslog_parse_identifier(const char **buf, char **identifier, char **pid) { +size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid) { const char *p; char *t; size_t l, e; @@ -191,7 +203,7 @@ void syslog_parse_identifier(const char **buf, char **identifier, char **pid) { if (l <= 0 || p[l-1] != ':') - return; + return 0; e = l; l--; @@ -221,11 +233,12 @@ void syslog_parse_identifier(const char **buf, char **identifier, char **pid) { if (t) *identifier = t; + e += strspn(p + e, WHITESPACE); *buf = p + e; - *buf += strspn(*buf, WHITESPACE); + return e; } -void syslog_parse_priority(char **p, int *priority) { +void syslog_parse_priority(const char **p, int *priority, bool with_facility) { int a = 0, b = 0, c = 0; int k; @@ -254,10 +267,14 @@ void syslog_parse_priority(char **p, int *priority) { } else return; - if (a < 0 || b < 0 || c < 0) + if (a < 0 || b < 0 || c < 0 || + (!with_facility && (a || b || c > 7))) return; - *priority = a*100+b*10+c; + if (with_facility) + *priority = a*100 + b*10 + c; + else + *priority = (*priority & LOG_FACMASK) | c; *p += k; } @@ -350,7 +367,7 @@ void server_process_syslog_message( assert(buf); orig = buf; - syslog_parse_priority((char**) &buf, &priority); + syslog_parse_priority(&buf, &priority, true); if (s->forward_to_syslog) forward_syslog_raw(s, priority, orig, ucred, tv); @@ -364,6 +381,9 @@ void server_process_syslog_message( if (s->forward_to_console) server_forward_console(s, priority, identifier, buf, ucred); + if (s->forward_to_wall) + server_forward_wall(s, priority, identifier, buf, ucred); + IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=syslog"); if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0) @@ -389,7 +409,7 @@ void server_process_syslog_message( if (message) IOVEC_SET_STRING(iovec[n++], message); - server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv, label, label_len, NULL, priority); + server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv, label, label_len, NULL, priority, 0); free(message); free(identifier); @@ -401,13 +421,15 @@ void server_process_syslog_message( } int server_open_syslog_socket(Server *s) { - union sockaddr_union sa; int one, r; - struct epoll_event ev; assert(s); if (s->syslog_fd < 0) { + union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/journal/dev-log", + }; s->syslog_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (s->syslog_fd < 0) { @@ -415,10 +437,6 @@ int server_open_syslog_socket(Server *s) { return -errno; } - zero(sa); - sa.un.sun_family = AF_UNIX; - strncpy(sa.un.sun_path, "/dev/log", sizeof(sa.un.sun_path)); - unlink(sa.un.sun_path); r = bind(s->syslog_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); @@ -439,10 +457,12 @@ int server_open_syslog_socket(Server *s) { } #ifdef HAVE_SELINUX - one = 1; - r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one)); - if (r < 0) - log_warning("SO_PASSSEC failed: %m"); + if (use_selinux()) { + one = 1; + r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one)); + if (r < 0) + log_warning("SO_PASSSEC failed: %m"); + } #endif one = 1; @@ -452,13 +472,28 @@ int server_open_syslog_socket(Server *s) { return -errno; } - zero(ev); - ev.events = EPOLLIN; - ev.data.fd = s->syslog_fd; - if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->syslog_fd, &ev) < 0) { - log_error("Failed to add syslog server fd to epoll object: %m"); - return -errno; + r = sd_event_add_io(s->event, &s->syslog_event_source, s->syslog_fd, EPOLLIN, process_datagram, s); + if (r < 0) { + log_error("Failed to add syslog server fd to event loop: %s", strerror(-r)); + return r; } return 0; } + +void server_maybe_warn_forward_syslog_missed(Server *s) { + usec_t n; + assert(s); + + if (s->n_forward_syslog_missed <= 0) + return; + + n = now(CLOCK_MONOTONIC); + if (s->last_warn_forward_syslog_missed + WARN_FORWARD_SYSLOG_MISSED_USEC > n) + return; + + server_driver_message(s, SD_MESSAGE_FORWARD_SYSLOG_MISSED, "Forwarding to syslog missed %u messages.", s->n_forward_syslog_missed); + + s->n_forward_syslog_missed = 0; + s->last_warn_forward_syslog_missed = n; +}