suricata
util-systemd.c
Go to the documentation of this file.
1/* SPDX-License-Identifier: MIT-0 */
2
3/* Implement the systemd notify protocol without external dependencies.
4 * Supports both readiness notification on startup and on reloading,
5 * according to the protocol defined at:
6 * https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
7 * This protocol is guaranteed to be stable as per:
8 * https://systemd.io/PORTABILITY_AND_STABILITY/ */
9
10/* this file is copied from:
11 * https://github.com/systemd/systemd/blob/main/man/notify-selfcontained-example.c
12 * written by Luca Boccassi */
13
14#include "suricata-common.h"
15
16#if (defined SYSTEMD_NOTIFY) && (defined HAVE_SYS_UN_H) && (defined HAVE_SYS_STAT_H) && \
17 (defined HAVE_SYS_TYPES_H)
18#include <sys/un.h>
19#include <sys/stat.h>
20#include <sys/types.h>
21
22#include "util-systemd.h"
23
24#define _cleanup_(f) __attribute__((cleanup(f)))
25
26static void closep(int *fd)
27{
28 if (!fd || *fd < 0)
29 return;
30
31 close(*fd);
32 *fd = -1;
33}
34
35static int Notify(const char *message)
36{
37 union sockaddr_union {
38 struct sockaddr sa;
39 struct sockaddr_un sun;
40 } socket_addr = {
41 .sun.sun_family = AF_UNIX,
42 };
43 size_t path_length, message_length;
44 _cleanup_(closep) int fd = -1;
45 const char *socket_path;
46
47 socket_path = getenv("NOTIFY_SOCKET");
48 if (!socket_path)
49 return 0; /* Not running under systemd? Nothing to do */
50
51 if (!message)
52 return -EINVAL;
53
54 message_length = strlen(message);
55 if (message_length == 0)
56 return -EINVAL;
57
58 /* Only AF_UNIX is supported, with path or abstract sockets */
59 if (socket_path[0] != '/' && socket_path[0] != '@')
60 return -EAFNOSUPPORT;
61
62 path_length = strlen(socket_path);
63 /* Ensure there is room for NUL byte */
64 if (path_length >= sizeof(socket_addr.sun.sun_path))
65 return -E2BIG;
66
67 memcpy(socket_addr.sun.sun_path, socket_path, path_length);
68
69 /* Support for abstract socket */
70 if (socket_addr.sun.sun_path[0] == '@')
71 socket_addr.sun.sun_path[0] = 0;
72
73 fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
74 if (fd < 0)
75 return -errno;
76
77 if (connect(fd, &socket_addr.sa,
78 offsetof(struct sockaddr_un, sun_path) + (uint32_t)path_length) != 0)
79 return -errno;
80
81 ssize_t written = write(fd, message, message_length);
82 if (written != (ssize_t)message_length)
83 return written < 0 ? -errno : -EPROTO;
84
85 return 1; /* Notified! */
86}
87
88int SystemDNotifyReady(void)
89{
90 return Notify("READY=1");
91}
92#endif
int SystemDNotifyReady(void)