back to topotato report
topotato coverage report
Current view: top level - lib - systemd.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 15 70 21.4 %
Date: 2023-11-16 17:19:14 Functions: 1 14 7.1 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /* lib/systemd Code
       3             :  * Copyright (C) 2016 Cumulus Networks, Inc.
       4             :  * Donald Sharp
       5             :  */
       6             : 
       7             : #include <zebra.h>
       8             : #include <sys/un.h>
       9             : 
      10             : #include "frrevent.h"
      11             : #include "systemd.h"
      12             : #include "lib_errors.h"
      13             : 
      14             : /* these are cleared from env so they don't "leak" into things we fork(),
      15             :  * particularly for watchfrr starting individual daemons
      16             :  *
      17             :  * watchdog_pid is currently not used since watchfrr starts forking.
      18             :  * (TODO: handle that better, somehow?)
      19             :  */
      20             : static pid_t watchdog_pid = -1;
      21             : static intmax_t watchdog_msec;
      22             : 
      23             : /* not used yet, but can trigger auto-switch to journald logging */
      24             : bool sd_stdout_is_journal;
      25             : bool sd_stderr_is_journal;
      26             : 
      27             : static char *notify_socket;
      28             : 
      29             : /* talk to whatever entity claims to be systemd ;)
      30             :  *
      31             :  * refer to sd_notify docs for messages systemd accepts over this socket.
      32             :  * This function should be functionally equivalent to sd_notify().
      33             :  */
      34           0 : static void systemd_send_information(const char *info)
      35             : {
      36           0 :         int sock;
      37           0 :         struct sockaddr_un sun;
      38             : 
      39           0 :         if (!notify_socket)
      40           0 :                 return;
      41             : 
      42           0 :         sock = socket(AF_UNIX, SOCK_DGRAM, 0);
      43           0 :         if (sock < 0)
      44             :                 return;
      45             : 
      46           0 :         sun.sun_family = AF_UNIX;
      47           0 :         strlcpy(sun.sun_path, notify_socket, sizeof(sun.sun_path));
      48             : 
      49             :         /* linux abstract unix socket namespace */
      50           0 :         if (sun.sun_path[0] == '@')
      51           0 :                 sun.sun_path[0] = '\0';
      52             : 
      53             :         /* nothing we can do if this errors out... */
      54           0 :         (void)sendto(sock, info, strlen(info), 0, (struct sockaddr *)&sun,
      55             :                      sizeof(sun));
      56             : 
      57           0 :         close(sock);
      58             : }
      59             : 
      60           0 : void systemd_send_stopping(void)
      61             : {
      62           0 :         systemd_send_information("STATUS=");
      63           0 :         systemd_send_information("STOPPING=1");
      64           0 : }
      65             : 
      66             : static struct event_loop *systemd_master = NULL;
      67             : 
      68           0 : static void systemd_send_watchdog(struct event *t)
      69             : {
      70           0 :         systemd_send_information("WATCHDOG=1");
      71             : 
      72           0 :         assert(watchdog_msec > 0);
      73           0 :         event_add_timer_msec(systemd_master, systemd_send_watchdog, NULL,
      74             :                              watchdog_msec, NULL);
      75           0 : }
      76             : 
      77           0 : void systemd_send_started(struct event_loop *m)
      78             : {
      79           0 :         assert(m != NULL);
      80             : 
      81           0 :         systemd_master = m;
      82             : 
      83           0 :         systemd_send_information("READY=1");
      84           0 :         if (watchdog_msec > 0)
      85           0 :                 systemd_send_watchdog(NULL);
      86           0 : }
      87             : 
      88           0 : void systemd_send_status(const char *status)
      89             : {
      90           0 :         char buffer[1024];
      91             : 
      92           0 :         snprintf(buffer, sizeof(buffer), "STATUS=%s", status);
      93           0 :         systemd_send_information(buffer);
      94           0 : }
      95             : 
      96           0 : static intmax_t getenv_int(const char *varname, intmax_t dflt)
      97             : {
      98           0 :         char *val, *err;
      99           0 :         intmax_t intval;
     100             : 
     101           0 :         val = getenv(varname);
     102           0 :         if (!val)
     103             :                 return dflt;
     104             : 
     105           0 :         intval = strtoimax(val, &err, 0);
     106           0 :         if (*err || !*val)
     107             :                 return dflt;
     108             :         return intval;
     109             : }
     110             : 
     111           4 : void systemd_init_env(void)
     112             : {
     113           4 :         char *tmp;
     114           4 :         uintmax_t dev, ino;
     115           4 :         int len;
     116           4 :         struct stat st;
     117             : 
     118           4 :         notify_socket = getenv("NOTIFY_SOCKET");
     119             : 
     120             :         /* no point in setting up watchdog w/o notify socket */
     121           4 :         if (notify_socket) {
     122           0 :                 intmax_t watchdog_usec;
     123             : 
     124           0 :                 watchdog_pid = getenv_int("WATCHDOG_PID", -1);
     125           0 :                 if (watchdog_pid <= 0)
     126           0 :                         watchdog_pid = -1;
     127             : 
     128             :                 /* note this is the deadline, hence the divide by 3 */
     129           0 :                 watchdog_usec = getenv_int("WATCHDOG_USEC", 0);
     130           0 :                 if (watchdog_usec >= 3000)
     131           0 :                         watchdog_msec = watchdog_usec / 3000;
     132             :                 else {
     133           0 :                         if (watchdog_usec != 0)
     134           0 :                                 flog_err(
     135             :                                         EC_LIB_UNAVAILABLE,
     136             :                                         "systemd expects a %jd microsecond watchdog timer, but FRR only supports millisecond resolution!",
     137             :                                         watchdog_usec);
     138           0 :                         watchdog_msec = 0;
     139             :                 }
     140             :         }
     141             : 
     142           4 :         tmp = getenv("JOURNAL_STREAM");
     143           4 :         if (tmp && sscanf(tmp, "%ju:%ju%n", &dev, &ino, &len) == 2
     144           4 :             && (size_t)len == strlen(tmp)) {
     145           4 :                 if (fstat(1, &st) == 0 && st.st_dev == (dev_t)dev
     146           0 :                     && st.st_ino == (ino_t)ino)
     147           0 :                         sd_stdout_is_journal = true;
     148           4 :                 if (fstat(2, &st) == 0 && st.st_dev == (dev_t)dev
     149           0 :                     && st.st_ino == (ino_t)ino)
     150           0 :                         sd_stderr_is_journal = true;
     151             :         }
     152             : 
     153             :         /* these should *not* be passed to any other process we start */
     154           4 :         unsetenv("WATCHDOG_PID");
     155           4 :         unsetenv("WATCHDOG_USEC");
     156           4 : }

Generated by: LCOV version v1.16-topotato