]>
git.proxmox.com Git - mirror_frr.git/blob - lib/systemd.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2016 Cumulus Networks, Inc.
12 #include "lib_errors.h"
14 /* these are cleared from env so they don't "leak" into things we fork(),
15 * particularly for watchfrr starting individual daemons
17 * watchdog_pid is currently not used since watchfrr starts forking.
18 * (TODO: handle that better, somehow?)
20 static pid_t watchdog_pid
= -1;
21 static intmax_t watchdog_msec
;
23 /* not used yet, but can trigger auto-switch to journald logging */
24 bool sd_stdout_is_journal
;
25 bool sd_stderr_is_journal
;
27 static char *notify_socket
;
29 /* talk to whatever entity claims to be systemd ;)
31 * refer to sd_notify docs for messages systemd accepts over this socket.
32 * This function should be functionally equivalent to sd_notify().
34 static void systemd_send_information(const char *info
)
37 struct sockaddr_un sun
;
42 sock
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
46 sun
.sun_family
= AF_UNIX
;
47 strlcpy(sun
.sun_path
, notify_socket
, sizeof(sun
.sun_path
));
49 /* linux abstract unix socket namespace */
50 if (sun
.sun_path
[0] == '@')
51 sun
.sun_path
[0] = '\0';
53 /* nothing we can do if this errors out... */
54 (void)sendto(sock
, info
, strlen(info
), 0, (struct sockaddr
*)&sun
,
60 void systemd_send_stopping(void)
62 systemd_send_information("STATUS=");
63 systemd_send_information("STOPPING=1");
66 static struct event_loop
*systemd_master
= NULL
;
68 static void systemd_send_watchdog(struct event
*t
)
70 systemd_send_information("WATCHDOG=1");
72 assert(watchdog_msec
> 0);
73 event_add_timer_msec(systemd_master
, systemd_send_watchdog
, NULL
,
77 void systemd_send_started(struct event_loop
*m
)
83 systemd_send_information("READY=1");
84 if (watchdog_msec
> 0)
85 systemd_send_watchdog(NULL
);
88 void systemd_send_status(const char *status
)
92 snprintf(buffer
, sizeof(buffer
), "STATUS=%s", status
);
93 systemd_send_information(buffer
);
96 static intmax_t getenv_int(const char *varname
, intmax_t dflt
)
101 val
= getenv(varname
);
105 intval
= strtoimax(val
, &err
, 0);
111 void systemd_init_env(void)
118 notify_socket
= getenv("NOTIFY_SOCKET");
120 /* no point in setting up watchdog w/o notify socket */
122 intmax_t watchdog_usec
;
124 watchdog_pid
= getenv_int("WATCHDOG_PID", -1);
125 if (watchdog_pid
<= 0)
128 /* note this is the deadline, hence the divide by 3 */
129 watchdog_usec
= getenv_int("WATCHDOG_USEC", 0);
130 if (watchdog_usec
>= 3000)
131 watchdog_msec
= watchdog_usec
/ 3000;
133 if (watchdog_usec
!= 0)
136 "systemd expects a %jd microsecond watchdog timer, but FRR only supports millisecond resolution!",
142 tmp
= getenv("JOURNAL_STREAM");
143 if (tmp
&& sscanf(tmp
, "%ju:%ju%n", &dev
, &ino
, &len
) == 2
144 && (size_t)len
== strlen(tmp
)) {
145 if (fstat(1, &st
) == 0 && st
.st_dev
== (dev_t
)dev
146 && st
.st_ino
== (ino_t
)ino
)
147 sd_stdout_is_journal
= true;
148 if (fstat(2, &st
) == 0 && st
.st_dev
== (dev_t
)dev
149 && st
.st_ino
== (ino_t
)ino
)
150 sd_stderr_is_journal
= true;
153 /* these should *not* be passed to any other process we start */
154 unsetenv("WATCHDOG_PID");
155 unsetenv("WATCHDOG_USEC");