journald-kmsg.c revision 968f319679d9069af037240d0c3bcd126181cdac
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog/***
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog This file is part of systemd.
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog Copyright 2011 Lennart Poettering
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog systemd is free software; you can redistribute it and/or modify it
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog under the terms of the GNU Lesser General Public License as published by
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog the Free Software Foundation; either version 2.1 of the License, or
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog (at your option) any later version.
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog systemd is distributed in the hope that it will be useful, but
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog WITHOUT ANY WARRANTY; without even the implied warranty of
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog Lesser General Public License for more details.
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog You should have received a copy of the GNU Lesser General Public License
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog along with systemd; If not, see <http://www.gnu.org/licenses/>.
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog***/
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog#include <unistd.h>
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog#include <sys/epoll.h>
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog#include <fcntl.h>
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog#include <sys/mman.h>
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog#include <sys/socket.h>
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog#include <systemd/sd-messages.h>
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog#include <libudev.h>
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
a64edefacbad4f3d538b45a6a65d8a5a03797d78Thomas Hindoe Paaboel Andersen#include "journald-server.h"
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog#include "journald-kmsg.h"
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog#include "journald-syslog.h"
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskogvoid server_forward_kmsg(
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog Server *s,
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog int priority,
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog const char *identifier,
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog const char *message,
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog struct ucred *ucred) {
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
89ca10c6a61309d84d54c5dc5a295387ce39e610Lennart Poettering struct iovec iovec[5];
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog char header_priority[6], header_pid[16];
89ca10c6a61309d84d54c5dc5a295387ce39e610Lennart Poettering int n = 0;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog char *ident_buf = NULL;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog assert(s);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog assert(priority >= 0);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog assert(priority <= 999);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog assert(message);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (_unlikely_(LOG_PRI(priority) > s->max_level_kmsg))
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (_unlikely_(s->dev_kmsg_fd < 0))
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog /* Never allow messages with kernel facility to be written to
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen * kmsg, regardless where the data comes from. */
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen priority = syslog_fixup_facility(priority);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen /* First: priority field */
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog char_array_0(header_priority);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog IOVEC_SET_STRING(iovec[n++], header_priority);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog /* Second: identifier and PID */
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (ucred) {
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (!identifier) {
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog get_process_comm(ucred->pid, &ident_buf);
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen identifier = ident_buf;
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen }
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen char_array_0(header_pid);
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen if (identifier)
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen IOVEC_SET_STRING(iovec[n++], identifier);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen IOVEC_SET_STRING(iovec[n++], header_pid);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog } else if (identifier) {
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog IOVEC_SET_STRING(iovec[n++], identifier);
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen IOVEC_SET_STRING(iovec[n++], ": ");
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen }
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog /* Fourth: message */
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen IOVEC_SET_STRING(iovec[n++], message);
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen IOVEC_SET_STRING(iovec[n++], "\n");
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen if (writev(s->dev_kmsg_fd, iovec, n) < 0)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog log_debug("Failed to write to /dev/kmsg for logging: %s", strerror(errno));
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog free(ident_buf);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog}
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersenstatic bool is_us(const char *pid) {
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen pid_t t;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
996d16975b4d802335188a3be2bbc3635c1287f3Tom Gundersen assert(pid);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (parse_pid(pid, &t) < 0)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return false;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return t == getpid();
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog}
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskogstatic void dev_kmsg_record(Server *s, char *p, size_t l) {
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog struct iovec iovec[N_IOVEC_META_FIELDS + 7 + N_IOVEC_KERNEL_FIELDS + 2 + N_IOVEC_UDEV_FIELDS];
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog char *message = NULL, *syslog_priority = NULL, *syslog_pid = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *source_time = NULL;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog int priority, r;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog unsigned n = 0, z = 0, j;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog unsigned long long usec;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog char *identifier = NULL, *pid = NULL, *e, *f, *k;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog uint64_t serial;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog size_t pl;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog char *kernel_device = NULL;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog assert(s);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog assert(p);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (l <= 0)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog e = memchr(p, ',', l);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (!e)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog *e = 0;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog r = safe_atoi(p, &priority);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (r < 0 || priority < 0 || priority > 999)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (s->forward_to_kmsg && (priority & LOG_FACMASK) != LOG_KERN)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog l -= (e - p) + 1;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog p = e + 1;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog e = memchr(p, ',', l);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (!e)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog *e = 0;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog r = safe_atou64(p, &serial);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (r < 0)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (s->kernel_seqnum) {
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog /* We already read this one? */
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (serial < *s->kernel_seqnum)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog /* Did we lose any? */
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (serial > *s->kernel_seqnum)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %"PRIu64" kernel messages",
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog serial - *s->kernel_seqnum - 1);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog /* Make sure we never read this one again. Note that
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog * we always store the next message serial we expect
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog * here, simply because this makes handling the first
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog * message with serial 0 easy. */
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog *s->kernel_seqnum = serial + 1;
89ca10c6a61309d84d54c5dc5a295387ce39e610Lennart Poettering }
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog l -= (e - p) + 1;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog p = e + 1;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog f = memchr(p, ';', l);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (!f)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog /* Kernel 3.6 has the flags field, kernel 3.5 lacks that */
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog e = memchr(p, ',', l);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (!e || f < e)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog e = f;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog *e = 0;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog r = safe_atollu(p, &usec);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (r < 0)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog l -= (f - p) + 1;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog p = f + 1;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog e = memchr(p, '\n', l);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (!e)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog *e = 0;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog pl = e - p;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog l -= (e - p) + 1;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog k = e + 1;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog for (j = 0; l > 0 && j < N_IOVEC_KERNEL_FIELDS; j++) {
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog char *m;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog /* Meta data fields attached */
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (*k != ' ')
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog break;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
a64edefacbad4f3d538b45a6a65d8a5a03797d78Thomas Hindoe Paaboel Andersen k ++, l --;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog e = memchr(k, '\n', l);
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog if (!e)
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog return;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog *e = 0;
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog
d9bf4f8c6c47b8620ffa1a056208eb15118b78d5Umut Tezduyar Lindskog m = cunescape_length_with_prefix(k, e - k, "_KERNEL_");
if (!m)
break;
if (startswith(m, "_KERNEL_DEVICE="))
kernel_device = m + 15;
IOVEC_SET_STRING(iovec[n++], m);
z++;
l -= (e - k) + 1;
k = e + 1;
}
if (kernel_device) {
struct udev_device *ud;
ud = udev_device_new_from_device_id(s->udev, kernel_device);
if (ud) {
const char *g;
struct udev_list_entry *ll;
char *b;
g = udev_device_get_devnode(ud);
if (g) {
b = strappend("_UDEV_DEVNODE=", g);
if (b) {
IOVEC_SET_STRING(iovec[n++], b);
z++;
}
}
g = udev_device_get_sysname(ud);
if (g) {
b = strappend("_UDEV_SYSNAME=", g);
if (b) {
IOVEC_SET_STRING(iovec[n++], b);
z++;
}
}
j = 0;
ll = udev_device_get_devlinks_list_entry(ud);
udev_list_entry_foreach(ll, ll) {
if (j > N_IOVEC_UDEV_FIELDS)
break;
g = udev_list_entry_get_name(ll);
if (g) {
b = strappend("_UDEV_DEVLINK=", g);
if (b) {
IOVEC_SET_STRING(iovec[n++], b);
z++;
}
}
j++;
}
udev_device_unref(ud);
}
}
if (asprintf(&source_time, "_SOURCE_MONOTONIC_TIMESTAMP=%llu", usec) >= 0)
IOVEC_SET_STRING(iovec[n++], source_time);
IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=kernel");
if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0)
IOVEC_SET_STRING(iovec[n++], syslog_priority);
if ((priority & LOG_FACMASK) == LOG_KERN)
IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=kernel");
else {
pl -= syslog_parse_identifier((const char**) &p, &identifier, &pid);
/* Avoid any messages we generated ourselves via
* log_info() and friends. */
if (pid && is_us(pid))
goto finish;
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);
}
if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0)
IOVEC_SET_STRING(iovec[n++], syslog_facility);
}
message = cunescape_length_with_prefix(p, pl, "MESSAGE=");
if (message)
IOVEC_SET_STRING(iovec[n++], message);
server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, NULL, 0, NULL, priority, 0);
finish:
for (j = 0; j < z; j++)
free(iovec[j].iov_base);
free(message);
free(syslog_priority);
free(syslog_identifier);
free(syslog_pid);
free(syslog_facility);
free(source_time);
free(identifier);
free(pid);
}
int server_read_dev_kmsg(Server *s) {
char buffer[8192+1]; /* the kernel-side limit per record is 8K currently */
ssize_t l;
assert(s);
assert(s->dev_kmsg_fd >= 0);
l = read(s->dev_kmsg_fd, buffer, sizeof(buffer) - 1);
if (l == 0)
return 0;
if (l < 0) {
/* Old kernels who don't allow reading from /dev/kmsg
* return EINVAL when we try. So handle this cleanly,
* but don' try to ever read from it again. */
if (errno == EINVAL) {
epoll_ctl(s->epoll_fd, EPOLL_CTL_DEL, s->dev_kmsg_fd, NULL);
return 0;
}
if (errno == EAGAIN || errno == EINTR || errno == EPIPE)
return 0;
log_error("Failed to read from kernel: %m");
return -errno;
}
dev_kmsg_record(s, buffer, l);
return 1;
}
int server_flush_dev_kmsg(Server *s) {
int r;
assert(s);
if (s->dev_kmsg_fd < 0)
return 0;
if (!s->dev_kmsg_readable)
return 0;
log_debug("Flushing /dev/kmsg...");
for (;;) {
r = server_read_dev_kmsg(s);
if (r < 0)
return r;
if (r == 0)
break;
}
return 0;
}
int server_open_dev_kmsg(Server *s) {
struct epoll_event ev;
assert(s);
s->dev_kmsg_fd = open("/dev/kmsg", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
if (s->dev_kmsg_fd < 0) {
log_warning("Failed to open /dev/kmsg, ignoring: %m");
return 0;
}
zero(ev);
ev.events = EPOLLIN;
ev.data.fd = s->dev_kmsg_fd;
if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->dev_kmsg_fd, &ev) < 0) {
/* This will fail with EPERM on older kernels where
* /dev/kmsg is not readable. */
if (errno == EPERM)
return 0;
log_error("Failed to add /dev/kmsg fd to epoll object: %m");
return -errno;
}
s->dev_kmsg_readable = true;
return 0;
}
int server_open_kernel_seqnum(Server *s) {
int fd;
uint64_t *p;
assert(s);
/* We store the seqnum we last read in an mmaped file. That
* way we can just use it like a variable, but it is
* persistent and automatically flushed at reboot. */
fd = open("/run/systemd/journal/kernel-seqnum", O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644);
if (fd < 0) {
log_error("Failed to open /run/systemd/journal/kernel-seqnum, ignoring: %m");
return 0;
}
if (posix_fallocate(fd, 0, sizeof(uint64_t)) < 0) {
log_error("Failed to allocate sequential number file, ignoring: %m");
close_nointr_nofail(fd);
return 0;
}
p = mmap(NULL, sizeof(uint64_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (p == MAP_FAILED) {
log_error("Failed to map sequential number file, ignoring: %m");
close_nointr_nofail(fd);
return 0;
}
close_nointr_nofail(fd);
s->kernel_seqnum = p;
return 0;
}