journald-syslog.c revision 178cc7700c23ac088cd7190d7854282075028d91
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering/***
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering This file is part of systemd.
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering Copyright 2011 Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering systemd is free software; you can redistribute it and/or modify it
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering under the terms of the GNU Lesser General Public License as published by
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering (at your option) any later version.
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering systemd is distributed in the hope that it will be useful, but
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering Lesser General Public License for more details.
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering You should have received a copy of the GNU Lesser General Public License
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering***/
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering#include <unistd.h>
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering#include <stddef.h>
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering#include <sys/epoll.h>
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering#include "systemd/sd-messages.h"
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering#include "socket-util.h"
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering#include "journald.h"
0591220f339c313761f9a208e88fb719db566993Zbigniew Jędrzejewski-Szmek#include "journald-syslog.h"
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering#include "journald-kmsg.h"
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering#include "journald-console.h"
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering/* Warn once every 30s if we missed syslog message */
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering#define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringstatic void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, struct ucred *ucred, struct timeval *tv) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering struct msghdr msghdr;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering struct cmsghdr *cmsg;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering union {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering struct cmsghdr cmsghdr;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering } control;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering union sockaddr_union sa;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(s);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(iovec);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(n_iovec > 0);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering zero(msghdr);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering msghdr.msg_iov = (struct iovec*) iovec;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering msghdr.msg_iovlen = n_iovec;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering zero(sa);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering sa.un.sun_family = AF_UNIX;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering strncpy(sa.un.sun_path, "/run/systemd/journal/syslog", sizeof(sa.un.sun_path));
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering msghdr.msg_name = &sa;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering msghdr.msg_namelen = offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (ucred) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering zero(control);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering msghdr.msg_control = &control;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering msghdr.msg_controllen = sizeof(control);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering cmsg = CMSG_FIRSTHDR(&msghdr);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering cmsg->cmsg_level = SOL_SOCKET;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering cmsg->cmsg_type = SCM_CREDENTIALS;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering memcpy(CMSG_DATA(cmsg), ucred, sizeof(struct ucred));
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering msghdr.msg_controllen = cmsg->cmsg_len;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering }
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering /* Forward the syslog message we received via /dev/log to
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering * /run/systemd/syslog. Unfortunately we currently can't set
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering * the SO_TIMESTAMP auxiliary data, and hence we don't. */
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering /* The socket is full? I guess the syslog implementation is
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering * too slow, and we shouldn't wait for that... */
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (errno == EAGAIN) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering s->n_forward_syslog_missed++;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering }
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (ucred && errno == ESRCH) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering struct ucred u;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering /* Hmm, presumably the sender process vanished
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering * by now, so let's fix it as good as we
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering * can, and retry */
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering u = *ucred;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering u.pid = getpid();
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering memcpy(CMSG_DATA(cmsg), &u, sizeof(struct ucred));
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (errno == EAGAIN) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering s->n_forward_syslog_missed++;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering }
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering }
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (errno != ENOENT)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering log_debug("Failed to forward syslog message: %m");
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering}
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringstatic void forward_syslog_raw(Server *s, int priority, const char *buffer, struct ucred *ucred, struct timeval *tv) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering struct iovec iovec;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
67445f4e22ad924394acdd4fd49e6f238244a5caZbigniew Jędrzejewski-Szmek assert(s);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(buffer);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (LOG_PRI(priority) > s->max_level_syslog)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering IOVEC_SET_STRING(iovec, buffer);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering forward_syslog_iovec(s, &iovec, 1, ucred, tv);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering}
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringvoid server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred, struct timeval *tv) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering struct iovec iovec[5];
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering char header_priority[6], header_time[64], header_pid[16];
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering int n = 0;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering time_t t;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering struct tm *tm;
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer char *ident_buf = NULL;
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace assert(s);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(priority >= 0);
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering assert(priority <= 999);
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering assert(message);
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering if (LOG_PRI(priority) > s->max_level_syslog)
0591220f339c313761f9a208e88fb719db566993Zbigniew Jędrzejewski-Szmek return;
0591220f339c313761f9a208e88fb719db566993Zbigniew Jędrzejewski-Szmek
0591220f339c313761f9a208e88fb719db566993Zbigniew Jędrzejewski-Szmek /* First: priority field */
0591220f339c313761f9a208e88fb719db566993Zbigniew Jędrzejewski-Szmek snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
0591220f339c313761f9a208e88fb719db566993Zbigniew Jędrzejewski-Szmek char_array_0(header_priority);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering IOVEC_SET_STRING(iovec[n++], header_priority);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace /* Second: timestamp */
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering t = tv ? tv->tv_sec : ((time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC));
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering tm = localtime(&t);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (!tm)
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace return;
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace return;
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace IOVEC_SET_STRING(iovec[n++], header_time);
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace /* Third: identifier and PID */
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace if (ucred) {
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace if (!identifier) {
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace get_process_comm(ucred->pid, &ident_buf);
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace identifier = ident_buf;
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace }
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering char_array_0(header_pid);
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering if (identifier)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering IOVEC_SET_STRING(iovec[n++], identifier);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering IOVEC_SET_STRING(iovec[n++], header_pid);
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering } else if (identifier) {
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering IOVEC_SET_STRING(iovec[n++], identifier);
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering IOVEC_SET_STRING(iovec[n++], ": ");
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering }
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
774de5a97fe69da822fde77b88af8d970ab5d0c6Oleksii Shevchuk /* Fourth: message */
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering IOVEC_SET_STRING(iovec[n++], message);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering forward_syslog_iovec(s, iovec, n, ucred, tv);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering free(ident_buf);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering}
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringint syslog_fixup_facility(int priority) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering if ((priority & LOG_FACMASK) == 0)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return (priority & LOG_PRIMASK) | LOG_USER;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return priority;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering}
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringvoid syslog_parse_identifier(const char **buf, char **identifier, char **pid) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering const char *p;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering char *t;
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering size_t l, e;
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(buf);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(identifier);
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek assert(pid);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering p = *buf;
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering p += strspn(p, WHITESPACE);
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering l = strcspn(p, WHITESPACE);
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek if (l <= 0 ||
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek p[l-1] != ':')
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek return;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek e = l;
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek l--;
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek if (p[l-1] == ']') {
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek size_t k = l-1;
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek for (;;) {
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (p[k] == '[') {
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek t = strndup(p+k+1, l-k-2);
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek if (t)
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek *pid = t;
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering l = k;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering break;
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek }
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek if (k == 0)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering break;
3baed19327663d012c3313b72cc5b3d02a58720aZbigniew Jędrzejewski-Szmek
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering k--;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering }
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering }
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering t = strndup(p, l);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (t)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering *identifier = t;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering *buf = p + e;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering *buf += strspn(*buf, WHITESPACE);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering}
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringvoid syslog_parse_priority(char **p, int *priority) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering int a = 0, b = 0, c = 0;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering int k;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(p);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(*p);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(priority);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if ((*p)[0] != '<')
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (!strchr(*p, '>'))
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if ((*p)[2] == '>') {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering c = undecchar((*p)[1]);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering k = 3;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering } else if ((*p)[3] == '>') {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering b = undecchar((*p)[1]);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering c = undecchar((*p)[2]);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering k = 4;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering } else if ((*p)[4] == '>') {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering a = undecchar((*p)[1]);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering b = undecchar((*p)[2]);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering c = undecchar((*p)[3]);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering k = 5;
7584d236eac91f9b7128b1eb08bddf18be2bce9fZbigniew Jędrzejewski-Szmek } else
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (a < 0 || b < 0 || c < 0)
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering return;
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering
7584d236eac91f9b7128b1eb08bddf18be2bce9fZbigniew Jędrzejewski-Szmek *priority = a*100+b*10+c;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering *p += k;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering}
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringstatic void syslog_skip_date(char **buf) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering enum {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering LETTER,
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering SPACE,
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering NUMBER,
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering SPACE_OR_NUMBER,
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering COLON
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering } sequence[] = {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering LETTER, LETTER, LETTER,
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering SPACE,
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering SPACE_OR_NUMBER, NUMBER,
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering SPACE,
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace SPACE_OR_NUMBER, NUMBER,
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering COLON,
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering SPACE_OR_NUMBER, NUMBER,
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering COLON,
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering SPACE_OR_NUMBER, NUMBER,
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering SPACE
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering };
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering char *p;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering unsigned i;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(buf);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering assert(*buf);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering p = *buf;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering for (i = 0; i < ELEMENTSOF(sequence); i++, p++) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (!*p)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering switch (sequence[i]) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering case SPACE:
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (*p != ' ')
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering break;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering case SPACE_OR_NUMBER:
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (*p == ' ')
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering break;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering /* fall through */
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering case NUMBER:
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (*p < '0' || *p > '9')
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering break;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering case LETTER:
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (!(*p >= 'A' && *p <= 'Z') &&
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering !(*p >= 'a' && *p <= 'z'))
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering break;
case COLON:
if (*p != ':')
return;
break;
}
}
*buf = p;
}
void server_process_syslog_message(
Server *s,
const char *buf,
struct ucred *ucred,
struct timeval *tv,
const char *label,
size_t label_len) {
char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *syslog_pid = NULL;
struct iovec iovec[N_IOVEC_META_FIELDS + 6];
unsigned n = 0;
int priority = LOG_USER | LOG_INFO;
char *identifier = NULL, *pid = NULL;
const char *orig;
assert(s);
assert(buf);
orig = buf;
syslog_parse_priority((char**) &buf, &priority);
if (s->forward_to_syslog)
forward_syslog_raw(s, priority, orig, ucred, tv);
syslog_skip_date((char**) &buf);
syslog_parse_identifier(&buf, &identifier, &pid);
if (s->forward_to_kmsg)
server_forward_kmsg(s, priority, identifier, buf, ucred);
if (s->forward_to_console)
server_forward_console(s, priority, identifier, buf, ucred);
IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=syslog");
if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0)
IOVEC_SET_STRING(iovec[n++], syslog_priority);
if (priority & LOG_FACMASK)
if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0)
IOVEC_SET_STRING(iovec[n++], syslog_facility);
if (identifier) {
syslog_identifier = strappend("SYSLOG_IDENTIFIER=", identifier);
if (syslog_identifier)
IOVEC_SET_STRING(iovec[n++], syslog_identifier);
}
if (pid) {
syslog_pid = strappend("SYSLOG_PID=", pid);
if (syslog_pid)
IOVEC_SET_STRING(iovec[n++], syslog_pid);
}
message = strappend("MESSAGE=", buf);
if (message)
IOVEC_SET_STRING(iovec[n++], message);
server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv, label, label_len, NULL, priority);
free(message);
free(identifier);
free(pid);
free(syslog_priority);
free(syslog_facility);
free(syslog_identifier);
free(syslog_pid);
}
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) {
s->syslog_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (s->syslog_fd < 0) {
log_error("socket() failed: %m");
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));
if (r < 0) {
log_error("bind() failed: %m");
return -errno;
}
chmod(sa.un.sun_path, 0666);
} else
fd_nonblock(s->syslog_fd, 1);
one = 1;
r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
if (r < 0) {
log_error("SO_PASSCRED failed: %m");
return -errno;
}
#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");
#endif
one = 1;
r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
if (r < 0) {
log_error("SO_TIMESTAMP failed: %m");
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;
}
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;
}