journald-syslog.c revision 178cc7700c23ac088cd7190d7854282075028d91
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering This file is part of systemd.
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering Copyright 2011 Lennart 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 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 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/* Warn once every 30s if we missed syslog message */
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering#define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringstatic void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, struct ucred *ucred, struct timeval *tv) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering strncpy(sa.un.sun_path, "/run/systemd/journal/syslog", sizeof(sa.un.sun_path));
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering msghdr.msg_namelen = offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering memcpy(CMSG_DATA(cmsg), ucred, sizeof(struct ucred));
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 if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
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 /* 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 memcpy(CMSG_DATA(cmsg), &u, sizeof(struct ucred));
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering log_debug("Failed to forward syslog message: %m");
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringstatic void forward_syslog_raw(Server *s, int priority, const char *buffer, struct ucred *ucred, struct timeval *tv) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (LOG_PRI(priority) > s->max_level_syslog)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering forward_syslog_iovec(s, &iovec, 1, ucred, tv);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringvoid server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred, struct timeval *tv) {
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering char header_priority[6], header_time[64], header_pid[16];
3ef63c317481c2b3f1fe39e1b0f130aac3544522Lennart Poettering if (LOG_PRI(priority) > s->max_level_syslog)
0591220f339c313761f9a208e88fb719db566993Zbigniew Jędrzejewski-Szmek /* First: priority field */
0591220f339c313761f9a208e88fb719db566993Zbigniew Jędrzejewski-Szmek snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering IOVEC_SET_STRING(iovec[n++], header_priority);
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace /* Second: timestamp */
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering t = tv ? tv->tv_sec : ((time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC));
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
067d851d30386c553e3a84f59d81d003ff638b91Daniel Wallace /* Third: identifier and PID */
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering IOVEC_SET_STRING(iovec[n++], identifier);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering IOVEC_SET_STRING(iovec[n++], header_pid);
6569cae18ed640a4e9f52f73e2a3ec54b07d0406Lennart Poettering IOVEC_SET_STRING(iovec[n++], identifier);
774de5a97fe69da822fde77b88af8d970ab5d0c6Oleksii Shevchuk /* Fourth: message */
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering forward_syslog_iovec(s, iovec, n, ucred, tv);
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering return (priority & LOG_PRIMASK) | LOG_USER;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringvoid syslog_parse_identifier(const char **buf, char **identifier, char **pid) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering const char *p;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (p[k] == '[') {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringvoid syslog_parse_priority(char **p, int *priority) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering int a = 0, b = 0, c = 0;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if ((*p)[0] != '<')
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (a < 0 || b < 0 || c < 0)
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poetteringstatic void syslog_skip_date(char **buf) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering for (i = 0; i < ELEMENTSOF(sequence); i++, p++) {
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (*p != ' ')
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering if (*p == ' ')
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering /* fall through */
case COLON:
*buf = p;
Server *s,
const char *buf,
const char *label,
char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *syslog_pid = NULL;
const char *orig;
assert(s);
if (s->forward_to_syslog)
if (s->forward_to_kmsg)
if (s->forward_to_console)
if (identifier) {
if (syslog_identifier)
if (pid) {
if (syslog_pid)
if (message)
server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv, label, label_len, NULL, priority);
int one, r;
assert(s);
if (s->syslog_fd < 0) {
if (s->syslog_fd < 0) {
return -errno;
r = bind(s->syslog_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
return -errno;
return -errno;
#ifdef HAVE_SELINUX
return -errno;
return -errno;
usec_t n;
assert(s);
if (s->n_forward_syslog_missed <= 0)
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;