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 
26 static void closep(int *fd)
27 {
28  if (!fd || *fd < 0)
29  return;
30 
31  close(*fd);
32  *fd = -1;
33 }
34 
35 static 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, offsetof(struct sockaddr_un, sun_path) + path_length) != 0)
78  return -errno;
79 
80  ssize_t written = write(fd, message, message_length);
81  if (written != (ssize_t)message_length)
82  return written < 0 ? -errno : -EPROTO;
83 
84  return 1; /* Notified! */
85 }
86 
87 int SystemDNotifyReady(void)
88 {
89  return Notify("READY=1");
90 }
91 #endif
SystemDNotifyReady
int SystemDNotifyReady(void)
util-systemd.h
suricata-common.h