LCOV - code coverage report
Current view: top level - journal - journald-syslog.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 30 254 11.8 %
Date: 2019-08-23 13:36:53 Functions: 1 9 11.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 19 276 6.9 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <stddef.h>
       4                 :            : #include <sys/epoll.h>
       5                 :            : #include <unistd.h>
       6                 :            : 
       7                 :            : #include "sd-messages.h"
       8                 :            : 
       9                 :            : #include "alloc-util.h"
      10                 :            : #include "fd-util.h"
      11                 :            : #include "format-util.h"
      12                 :            : #include "io-util.h"
      13                 :            : #include "journald-console.h"
      14                 :            : #include "journald-kmsg.h"
      15                 :            : #include "journald-server.h"
      16                 :            : #include "journald-syslog.h"
      17                 :            : #include "journald-wall.h"
      18                 :            : #include "process-util.h"
      19                 :            : #include "selinux-util.h"
      20                 :            : #include "socket-util.h"
      21                 :            : #include "stdio-util.h"
      22                 :            : #include "string-util.h"
      23                 :            : #include "syslog-util.h"
      24                 :            : 
      25                 :            : /* Warn once every 30s if we missed syslog message */
      26                 :            : #define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC)
      27                 :            : 
      28                 :          0 : static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, const struct ucred *ucred, const struct timeval *tv) {
      29                 :            : 
      30                 :            :         static const union sockaddr_union sa = {
      31                 :            :                 .un.sun_family = AF_UNIX,
      32                 :            :                 .un.sun_path = "/run/systemd/journal/syslog",
      33                 :            :         };
      34                 :          0 :         struct msghdr msghdr = {
      35                 :            :                 .msg_iov = (struct iovec *) iovec,
      36                 :            :                 .msg_iovlen = n_iovec,
      37                 :            :                 .msg_name = (struct sockaddr*) &sa.sa,
      38   [ #  #  #  # ]:          0 :                 .msg_namelen = SOCKADDR_UN_LEN(sa.un),
      39                 :            :         };
      40                 :            :         struct cmsghdr *cmsg;
      41                 :            :         union {
      42                 :            :                 struct cmsghdr cmsghdr;
      43                 :            :                 uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
      44                 :            :         } control;
      45                 :            : 
      46         [ #  # ]:          0 :         assert(s);
      47         [ #  # ]:          0 :         assert(iovec);
      48         [ #  # ]:          0 :         assert(n_iovec > 0);
      49                 :            : 
      50         [ #  # ]:          0 :         if (ucred) {
      51         [ #  # ]:          0 :                 zero(control);
      52                 :          0 :                 msghdr.msg_control = &control;
      53                 :          0 :                 msghdr.msg_controllen = sizeof(control);
      54                 :            : 
      55         [ #  # ]:          0 :                 cmsg = CMSG_FIRSTHDR(&msghdr);
      56                 :          0 :                 cmsg->cmsg_level = SOL_SOCKET;
      57                 :          0 :                 cmsg->cmsg_type = SCM_CREDENTIALS;
      58                 :          0 :                 cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
      59                 :          0 :                 memcpy(CMSG_DATA(cmsg), ucred, sizeof(struct ucred));
      60                 :          0 :                 msghdr.msg_controllen = cmsg->cmsg_len;
      61                 :            :         }
      62                 :            : 
      63                 :            :         /* Forward the syslog message we received via /dev/log to
      64                 :            :          * /run/systemd/syslog. Unfortunately we currently can't set
      65                 :            :          * the SO_TIMESTAMP auxiliary data, and hence we don't. */
      66                 :            : 
      67         [ #  # ]:          0 :         if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
      68                 :          0 :                 return;
      69                 :            : 
      70                 :            :         /* The socket is full? I guess the syslog implementation is
      71                 :            :          * too slow, and we shouldn't wait for that... */
      72         [ #  # ]:          0 :         if (errno == EAGAIN) {
      73                 :          0 :                 s->n_forward_syslog_missed++;
      74                 :          0 :                 return;
      75                 :            :         }
      76                 :            : 
      77   [ #  #  #  #  :          0 :         if (ucred && IN_SET(errno, ESRCH, EPERM)) {
                   #  # ]
      78                 :            :                 struct ucred u;
      79                 :            : 
      80                 :            :                 /* Hmm, presumably the sender process vanished
      81                 :            :                  * by now, or we don't have CAP_SYS_AMDIN, so
      82                 :            :                  * let's fix it as good as we can, and retry */
      83                 :            : 
      84                 :          0 :                 u = *ucred;
      85                 :          0 :                 u.pid = getpid_cached();
      86                 :          0 :                 memcpy(CMSG_DATA(cmsg), &u, sizeof(struct ucred));
      87                 :            : 
      88         [ #  # ]:          0 :                 if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
      89                 :          0 :                         return;
      90                 :            : 
      91         [ #  # ]:          0 :                 if (errno == EAGAIN) {
      92                 :          0 :                         s->n_forward_syslog_missed++;
      93                 :          0 :                         return;
      94                 :            :                 }
      95                 :            :         }
      96                 :            : 
      97         [ #  # ]:          0 :         if (errno != ENOENT)
      98         [ #  # ]:          0 :                 log_debug_errno(errno, "Failed to forward syslog message: %m");
      99                 :            : }
     100                 :            : 
     101                 :          0 : static void forward_syslog_raw(Server *s, int priority, const char *buffer, size_t buffer_len, const struct ucred *ucred, const struct timeval *tv) {
     102                 :            :         struct iovec iovec;
     103                 :            : 
     104         [ #  # ]:          0 :         assert(s);
     105         [ #  # ]:          0 :         assert(buffer);
     106                 :            : 
     107         [ #  # ]:          0 :         if (LOG_PRI(priority) > s->max_level_syslog)
     108                 :          0 :                 return;
     109                 :            : 
     110                 :          0 :         iovec = IOVEC_MAKE((char *) buffer, buffer_len);
     111                 :          0 :         forward_syslog_iovec(s, &iovec, 1, ucred, tv);
     112                 :            : }
     113                 :            : 
     114                 :          0 : void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred, const struct timeval *tv) {
     115                 :            :         struct iovec iovec[5];
     116                 :            :         char header_priority[DECIMAL_STR_MAX(priority) + 3], header_time[64],
     117                 :            :              header_pid[STRLEN("[]: ") + DECIMAL_STR_MAX(pid_t) + 1];
     118                 :          0 :         int n = 0;
     119                 :            :         time_t t;
     120                 :            :         struct tm tm;
     121         [ #  # ]:          0 :         _cleanup_free_ char *ident_buf = NULL;
     122                 :            : 
     123         [ #  # ]:          0 :         assert(s);
     124         [ #  # ]:          0 :         assert(priority >= 0);
     125         [ #  # ]:          0 :         assert(priority <= 999);
     126         [ #  # ]:          0 :         assert(message);
     127                 :            : 
     128         [ #  # ]:          0 :         if (LOG_PRI(priority) > s->max_level_syslog)
     129                 :          0 :                 return;
     130                 :            : 
     131                 :            :         /* First: priority field */
     132         [ #  # ]:          0 :         xsprintf(header_priority, "<%i>", priority);
     133                 :          0 :         iovec[n++] = IOVEC_MAKE_STRING(header_priority);
     134                 :            : 
     135                 :            :         /* Second: timestamp */
     136         [ #  # ]:          0 :         t = tv ? tv->tv_sec : ((time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC));
     137         [ #  # ]:          0 :         if (!localtime_r(&t, &tm))
     138                 :          0 :                 return;
     139         [ #  # ]:          0 :         if (strftime(header_time, sizeof(header_time), "%h %e %T ", &tm) <= 0)
     140                 :          0 :                 return;
     141                 :          0 :         iovec[n++] = IOVEC_MAKE_STRING(header_time);
     142                 :            : 
     143                 :            :         /* Third: identifier and PID */
     144         [ #  # ]:          0 :         if (ucred) {
     145         [ #  # ]:          0 :                 if (!identifier) {
     146                 :          0 :                         get_process_comm(ucred->pid, &ident_buf);
     147                 :          0 :                         identifier = ident_buf;
     148                 :            :                 }
     149                 :            : 
     150         [ #  # ]:          0 :                 xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid);
     151                 :            : 
     152         [ #  # ]:          0 :                 if (identifier)
     153                 :          0 :                         iovec[n++] = IOVEC_MAKE_STRING(identifier);
     154                 :            : 
     155                 :          0 :                 iovec[n++] = IOVEC_MAKE_STRING(header_pid);
     156         [ #  # ]:          0 :         } else if (identifier) {
     157                 :          0 :                 iovec[n++] = IOVEC_MAKE_STRING(identifier);
     158                 :          0 :                 iovec[n++] = IOVEC_MAKE_STRING(": ");
     159                 :            :         }
     160                 :            : 
     161                 :            :         /* Fourth: message */
     162                 :          0 :         iovec[n++] = IOVEC_MAKE_STRING(message);
     163                 :            : 
     164                 :          0 :         forward_syslog_iovec(s, iovec, n, ucred, tv);
     165                 :            : }
     166                 :            : 
     167                 :          0 : int syslog_fixup_facility(int priority) {
     168                 :            : 
     169         [ #  # ]:          0 :         if ((priority & LOG_FACMASK) == 0)
     170                 :          0 :                 return (priority & LOG_PRIMASK) | LOG_USER;
     171                 :            : 
     172                 :          0 :         return priority;
     173                 :            : }
     174                 :            : 
     175                 :         56 : size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid) {
     176                 :            :         const char *p;
     177                 :            :         char *t;
     178                 :            :         size_t l, e;
     179                 :            : 
     180         [ -  + ]:         56 :         assert(buf);
     181         [ -  + ]:         56 :         assert(identifier);
     182         [ -  + ]:         56 :         assert(pid);
     183                 :            : 
     184                 :         56 :         p = *buf;
     185                 :            : 
     186                 :         56 :         p += strspn(p, WHITESPACE);
     187                 :         56 :         l = strcspn(p, WHITESPACE);
     188                 :            : 
     189         [ +  + ]:         56 :         if (l <= 0 ||
     190         [ +  + ]:         48 :             p[l-1] != ':')
     191                 :         20 :                 return 0;
     192                 :            : 
     193                 :         36 :         e = l;
     194                 :         36 :         l--;
     195                 :            : 
     196   [ +  +  +  + ]:         36 :         if (l > 0 && p[l-1] == ']') {
     197                 :          4 :                 size_t k = l-1;
     198                 :            : 
     199                 :            :                 for (;;) {
     200                 :            : 
     201         [ +  + ]:         20 :                         if (p[k] == '[') {
     202                 :          4 :                                 t = strndup(p+k+1, l-k-2);
     203         [ +  - ]:          4 :                                 if (t)
     204                 :          4 :                                         *pid = t;
     205                 :            : 
     206                 :          4 :                                 l = k;
     207                 :          4 :                                 break;
     208                 :            :                         }
     209                 :            : 
     210         [ -  + ]:         16 :                         if (k == 0)
     211                 :          0 :                                 break;
     212                 :            : 
     213                 :         16 :                         k--;
     214                 :            :                 }
     215                 :            :         }
     216                 :            : 
     217                 :         36 :         t = strndup(p, l);
     218         [ +  - ]:         36 :         if (t)
     219                 :         36 :                 *identifier = t;
     220                 :            : 
     221                 :            :         /* Single space is used as separator */
     222   [ +  +  +  - ]:         36 :         if (p[e] != '\0' && strchr(WHITESPACE, p[e]))
     223                 :         20 :                 e++;
     224                 :            : 
     225                 :         36 :         l = (p - *buf) + e;
     226                 :         36 :         *buf = p + e;
     227                 :         36 :         return l;
     228                 :            : }
     229                 :            : 
     230                 :          0 : static int syslog_skip_timestamp(const char **buf) {
     231                 :            :         enum {
     232                 :            :                 LETTER,
     233                 :            :                 SPACE,
     234                 :            :                 NUMBER,
     235                 :            :                 SPACE_OR_NUMBER,
     236                 :            :                 COLON
     237                 :          0 :         } sequence[] = {
     238                 :            :                 LETTER, LETTER, LETTER,
     239                 :            :                 SPACE,
     240                 :            :                 SPACE_OR_NUMBER, NUMBER,
     241                 :            :                 SPACE,
     242                 :            :                 SPACE_OR_NUMBER, NUMBER,
     243                 :            :                 COLON,
     244                 :            :                 SPACE_OR_NUMBER, NUMBER,
     245                 :            :                 COLON,
     246                 :            :                 SPACE_OR_NUMBER, NUMBER,
     247                 :            :                 SPACE
     248                 :            :         };
     249                 :            : 
     250                 :            :         const char *p, *t;
     251                 :            :         unsigned i;
     252                 :            : 
     253         [ #  # ]:          0 :         assert(buf);
     254         [ #  # ]:          0 :         assert(*buf);
     255                 :            : 
     256         [ #  # ]:          0 :         for (i = 0, p = *buf; i < ELEMENTSOF(sequence); i++, p++) {
     257         [ #  # ]:          0 :                 if (!*p)
     258                 :          0 :                         return 0;
     259                 :            : 
     260   [ #  #  #  #  :          0 :                 switch (sequence[i]) {
                   #  # ]
     261                 :            : 
     262                 :          0 :                 case SPACE:
     263         [ #  # ]:          0 :                         if (*p != ' ')
     264                 :          0 :                                 return 0;
     265                 :          0 :                         break;
     266                 :            : 
     267                 :          0 :                 case SPACE_OR_NUMBER:
     268         [ #  # ]:          0 :                         if (*p == ' ')
     269                 :          0 :                                 break;
     270                 :            : 
     271                 :            :                         _fallthrough_;
     272                 :            :                 case NUMBER:
     273   [ #  #  #  # ]:          0 :                         if (*p < '0' || *p > '9')
     274                 :          0 :                                 return 0;
     275                 :            : 
     276                 :          0 :                         break;
     277                 :            : 
     278                 :          0 :                 case LETTER:
     279   [ #  #  #  # ]:          0 :                         if (!(*p >= 'A' && *p <= 'Z') &&
     280   [ #  #  #  # ]:          0 :                             !(*p >= 'a' && *p <= 'z'))
     281                 :          0 :                                 return 0;
     282                 :            : 
     283                 :          0 :                         break;
     284                 :            : 
     285                 :          0 :                 case COLON:
     286         [ #  # ]:          0 :                         if (*p != ':')
     287                 :          0 :                                 return 0;
     288                 :          0 :                         break;
     289                 :            : 
     290                 :            :                 }
     291                 :          0 :         }
     292                 :            : 
     293                 :          0 :         t = *buf;
     294                 :          0 :         *buf = p;
     295                 :          0 :         return p - t;
     296                 :            : }
     297                 :            : 
     298                 :          0 : void server_process_syslog_message(
     299                 :            :                 Server *s,
     300                 :            :                 const char *buf,
     301                 :            :                 size_t raw_len,
     302                 :            :                 const struct ucred *ucred,
     303                 :            :                 const struct timeval *tv,
     304                 :            :                 const char *label,
     305                 :            :                 size_t label_len) {
     306                 :            : 
     307                 :            :         char *t, syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)],
     308                 :            :                  syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
     309                 :            :         const char *msg, *syslog_ts, *a;
     310   [ #  #  #  # ]:          0 :         _cleanup_free_ char *identifier = NULL, *pid = NULL,
     311   [ #  #  #  #  :          0 :                 *dummy = NULL, *msg_msg = NULL, *msg_raw = NULL;
                   #  # ]
     312                 :          0 :         int priority = LOG_USER | LOG_INFO, r;
     313                 :          0 :         ClientContext *context = NULL;
     314                 :            :         struct iovec *iovec;
     315                 :          0 :         size_t n = 0, m, i, leading_ws, syslog_ts_len;
     316                 :            :         bool store_raw;
     317                 :            : 
     318         [ #  # ]:          0 :         assert(s);
     319         [ #  # ]:          0 :         assert(buf);
     320                 :            :         /* The message cannot be empty. */
     321         [ #  # ]:          0 :         assert(raw_len > 0);
     322                 :            :         /* The buffer NUL-terminated and can be used a string. raw_len is the length
     323                 :            :          * without the terminating NUL byte, the buffer is actually one bigger. */
     324         [ #  # ]:          0 :         assert(buf[raw_len] == '\0');
     325                 :            : 
     326   [ #  #  #  # ]:          0 :         if (ucred && pid_is_valid(ucred->pid)) {
     327                 :          0 :                 r = client_context_get(s, ucred->pid, ucred, label, label_len, NULL, &context);
     328         [ #  # ]:          0 :                 if (r < 0)
     329         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m", ucred->pid);
     330                 :            :         }
     331                 :            : 
     332                 :            :         /* We are creating a copy of the message because we want to forward the original message
     333                 :            :            verbatim to the legacy syslog implementation */
     334         [ #  # ]:          0 :         for (i = raw_len; i > 0; i--)
     335         [ #  # ]:          0 :                 if (!strchr(WHITESPACE, buf[i-1]))
     336                 :          0 :                         break;
     337                 :            : 
     338                 :          0 :         leading_ws = strspn(buf, WHITESPACE);
     339                 :            : 
     340         [ #  # ]:          0 :         if (i == 0)
     341                 :            :                 /* The message contains only whitespaces */
     342                 :          0 :                 msg = buf + raw_len;
     343         [ #  # ]:          0 :         else if (i == raw_len)
     344                 :            :                 /* Nice! No need to strip anything on the end, let's optimize this a bit */
     345                 :          0 :                 msg = buf + leading_ws;
     346                 :            :         else {
     347                 :          0 :                 msg = dummy = new(char, i - leading_ws + 1);
     348         [ #  # ]:          0 :                 if (!dummy) {
     349                 :          0 :                         log_oom();
     350                 :          0 :                         return;
     351                 :            :                 }
     352                 :            : 
     353                 :          0 :                 memcpy(dummy, buf + leading_ws, i - leading_ws);
     354                 :          0 :                 dummy[i - leading_ws] = 0;
     355                 :            :         }
     356                 :            : 
     357                 :            :         /* We will add the SYSLOG_RAW= field when we stripped anything
     358                 :            :          * _or_ if the input message contained NUL bytes. */
     359   [ #  #  #  # ]:          0 :         store_raw = msg != buf || strlen(msg) != raw_len;
     360                 :            : 
     361                 :          0 :         syslog_parse_priority(&msg, &priority, true);
     362                 :            : 
     363         [ #  # ]:          0 :         if (!client_context_test_priority(context, priority))
     364                 :          0 :                 return;
     365                 :            : 
     366                 :          0 :         syslog_ts = msg;
     367                 :          0 :         syslog_ts_len = syslog_skip_timestamp(&msg);
     368         [ #  # ]:          0 :         if (syslog_ts_len == 0)
     369                 :            :                 /* We failed to parse the full timestamp, store the raw message too */
     370                 :          0 :                 store_raw = true;
     371                 :            : 
     372                 :          0 :         syslog_parse_identifier(&msg, &identifier, &pid);
     373                 :            : 
     374         [ #  # ]:          0 :         if (s->forward_to_syslog)
     375                 :          0 :                 forward_syslog_raw(s, priority, buf, raw_len, ucred, tv);
     376                 :            : 
     377         [ #  # ]:          0 :         if (s->forward_to_kmsg)
     378                 :          0 :                 server_forward_kmsg(s, priority, identifier, msg, ucred);
     379                 :            : 
     380         [ #  # ]:          0 :         if (s->forward_to_console)
     381                 :          0 :                 server_forward_console(s, priority, identifier, msg, ucred);
     382                 :            : 
     383         [ #  # ]:          0 :         if (s->forward_to_wall)
     384                 :          0 :                 server_forward_wall(s, priority, identifier, msg, ucred);
     385                 :            : 
     386                 :          0 :         m = N_IOVEC_META_FIELDS + 8 + client_context_extra_fields_n_iovec(context);
     387   [ #  #  #  # ]:          0 :         iovec = newa(struct iovec, m);
     388                 :            : 
     389                 :          0 :         iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=syslog");
     390                 :            : 
     391         [ #  # ]:          0 :         xsprintf(syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK);
     392                 :          0 :         iovec[n++] = IOVEC_MAKE_STRING(syslog_priority);
     393                 :            : 
     394         [ #  # ]:          0 :         if (priority & LOG_FACMASK) {
     395         [ #  # ]:          0 :                 xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority));
     396                 :          0 :                 iovec[n++] = IOVEC_MAKE_STRING(syslog_facility);
     397                 :            :         }
     398                 :            : 
     399         [ #  # ]:          0 :         if (identifier) {
     400   [ #  #  #  #  :          0 :                 a = strjoina("SYSLOG_IDENTIFIER=", identifier);
          #  #  #  #  #  
                #  #  # ]
     401                 :          0 :                 iovec[n++] = IOVEC_MAKE_STRING(a);
     402                 :            :         }
     403                 :            : 
     404         [ #  # ]:          0 :         if (pid) {
     405   [ #  #  #  #  :          0 :                 a = strjoina("SYSLOG_PID=", pid);
          #  #  #  #  #  
                #  #  # ]
     406                 :          0 :                 iovec[n++] = IOVEC_MAKE_STRING(a);
     407                 :            :         }
     408                 :            : 
     409         [ #  # ]:          0 :         if (syslog_ts_len > 0) {
     410                 :          0 :                 const size_t hlen = STRLEN("SYSLOG_TIMESTAMP=");
     411                 :            : 
     412   [ #  #  #  # ]:          0 :                 t = newa(char, hlen + syslog_ts_len);
     413                 :          0 :                 memcpy(t, "SYSLOG_TIMESTAMP=", hlen);
     414                 :          0 :                 memcpy(t + hlen, syslog_ts, syslog_ts_len);
     415                 :            : 
     416                 :          0 :                 iovec[n++] = IOVEC_MAKE(t, hlen + syslog_ts_len);
     417                 :            :         }
     418                 :            : 
     419                 :          0 :         msg_msg = strjoin("MESSAGE=", msg);
     420         [ #  # ]:          0 :         if (!msg_msg) {
     421                 :          0 :                 log_oom();
     422                 :          0 :                 return;
     423                 :            :         }
     424                 :          0 :         iovec[n++] = IOVEC_MAKE_STRING(msg_msg);
     425                 :            : 
     426         [ #  # ]:          0 :         if (store_raw) {
     427                 :          0 :                 const size_t hlen = STRLEN("SYSLOG_RAW=");
     428                 :            : 
     429                 :          0 :                 msg_raw = new(char, hlen + raw_len);
     430         [ #  # ]:          0 :                 if (!msg_raw) {
     431                 :          0 :                         log_oom();
     432                 :          0 :                         return;
     433                 :            :                 }
     434                 :            : 
     435                 :          0 :                 memcpy(msg_raw, "SYSLOG_RAW=", hlen);
     436                 :          0 :                 memcpy(msg_raw + hlen, buf, raw_len);
     437                 :            : 
     438                 :          0 :                 iovec[n++] = IOVEC_MAKE(msg_raw, hlen + raw_len);
     439                 :            :         }
     440                 :            : 
     441                 :          0 :         server_dispatch_message(s, iovec, n, m, context, tv, priority, 0);
     442                 :            : }
     443                 :            : 
     444                 :          0 : int server_open_syslog_socket(Server *s) {
     445                 :            : 
     446                 :            :         static const union sockaddr_union sa = {
     447                 :            :                 .un.sun_family = AF_UNIX,
     448                 :            :                 .un.sun_path = "/run/systemd/journal/dev-log",
     449                 :            :         };
     450                 :            :         int r;
     451                 :            : 
     452         [ #  # ]:          0 :         assert(s);
     453                 :            : 
     454         [ #  # ]:          0 :         if (s->syslog_fd < 0) {
     455                 :          0 :                 s->syslog_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
     456         [ #  # ]:          0 :                 if (s->syslog_fd < 0)
     457         [ #  # ]:          0 :                         return log_error_errno(errno, "socket() failed: %m");
     458                 :            : 
     459                 :          0 :                 (void) sockaddr_un_unlink(&sa.un);
     460                 :            : 
     461   [ #  #  #  # ]:          0 :                 r = bind(s->syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
     462         [ #  # ]:          0 :                 if (r < 0)
     463         [ #  # ]:          0 :                         return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);
     464                 :            : 
     465                 :          0 :                 (void) chmod(sa.un.sun_path, 0666);
     466                 :            :         } else
     467                 :          0 :                 (void) fd_nonblock(s->syslog_fd, true);
     468                 :            : 
     469                 :          0 :         r = setsockopt_int(s->syslog_fd, SOL_SOCKET, SO_PASSCRED, true);
     470         [ #  # ]:          0 :         if (r < 0)
     471         [ #  # ]:          0 :                 return log_error_errno(r, "SO_PASSCRED failed: %m");
     472                 :            : 
     473                 :            : #if HAVE_SELINUX
     474         [ #  # ]:          0 :         if (mac_selinux_use()) {
     475                 :          0 :                 r = setsockopt_int(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, true);
     476         [ #  # ]:          0 :                 if (r < 0)
     477         [ #  # ]:          0 :                         log_warning_errno(r, "SO_PASSSEC failed: %m");
     478                 :            :         }
     479                 :            : #endif
     480                 :            : 
     481                 :          0 :         r = setsockopt_int(s->syslog_fd, SOL_SOCKET, SO_TIMESTAMP, true);
     482         [ #  # ]:          0 :         if (r < 0)
     483         [ #  # ]:          0 :                 return log_error_errno(r, "SO_TIMESTAMP failed: %m");
     484                 :            : 
     485                 :          0 :         r = sd_event_add_io(s->event, &s->syslog_event_source, s->syslog_fd, EPOLLIN, server_process_datagram, s);
     486         [ #  # ]:          0 :         if (r < 0)
     487         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to add syslog server fd to event loop: %m");
     488                 :            : 
     489                 :          0 :         r = sd_event_source_set_priority(s->syslog_event_source, SD_EVENT_PRIORITY_NORMAL+5);
     490         [ #  # ]:          0 :         if (r < 0)
     491         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to adjust syslog event source priority: %m");
     492                 :            : 
     493                 :          0 :         return 0;
     494                 :            : }
     495                 :            : 
     496                 :          0 : void server_maybe_warn_forward_syslog_missed(Server *s) {
     497                 :            :         usec_t n;
     498                 :            : 
     499         [ #  # ]:          0 :         assert(s);
     500                 :            : 
     501         [ #  # ]:          0 :         if (s->n_forward_syslog_missed <= 0)
     502                 :          0 :                 return;
     503                 :            : 
     504                 :          0 :         n = now(CLOCK_MONOTONIC);
     505         [ #  # ]:          0 :         if (s->last_warn_forward_syslog_missed + WARN_FORWARD_SYSLOG_MISSED_USEC > n)
     506                 :          0 :                 return;
     507                 :            : 
     508                 :          0 :         server_driver_message(s, 0,
     509                 :            :                               "MESSAGE_ID=" SD_MESSAGE_FORWARD_SYSLOG_MISSED_STR,
     510                 :            :                               LOG_MESSAGE("Forwarding to syslog missed %u messages.",
     511                 :            :                                           s->n_forward_syslog_missed),
     512                 :            :                               NULL);
     513                 :            : 
     514                 :          0 :         s->n_forward_syslog_missed = 0;
     515                 :          0 :         s->last_warn_forward_syslog_missed = n;
     516                 :            : }

Generated by: LCOV version 1.14