pacemaker  2.1.7-0f7f88312f
Scalable High-Availability cluster resource manager
ipc_internal.h
Go to the documentation of this file.
1 /*
2  * Copyright 2013-2023 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #ifndef PCMK__IPC_INTERNAL_H
11 #define PCMK__IPC_INTERNAL_H
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 #include <stdbool.h> // bool
18 #include <stdint.h> // uint32_t, uint64_t, UINT64_C()
19 #include <sys/uio.h> // struct iovec
20 #include <sys/types.h> // uid_t, gid_t, pid_t, size_t
21 
22 #ifdef HAVE_GNUTLS_GNUTLS_H
23 # include <gnutls/gnutls.h> // gnutls_session_t
24 #endif
25 
26 #include <glib.h> // guint, gpointer, GQueue, ...
27 #include <libxml/tree.h> // xmlNode
28 #include <qb/qbipcs.h> // qb_ipcs_connection_t, ...
29 
30 #include <crm_config.h> // HAVE_GETPEEREID
31 #include <crm/common/ipc.h>
32 #include <crm/common/ipc_controld.h> // pcmk_controld_api_reply
33 #include <crm/common/ipc_pacemakerd.h> // pcmk_pacemakerd_{api_reply,state}
34 #include <crm/common/mainloop.h> // mainloop_io_t
35 
36 /*
37  * XML attribute names used only by internal code
38  */
39 
40 #define PCMK__XA_IPC_PROTO_VERSION "ipc-protocol-version"
41 
42 /* denotes "non yieldable PID" on FreeBSD, or actual PID1 in scenarios that
43  require a delicate handling anyway (socket-based activation with systemd);
44  we can be reasonably sure that this PID is never possessed by the actual
45  child daemon, as it gets taken either by the proper init, or by pacemakerd
46  itself (i.e. this precludes anything else); note that value of zero
47  is meant to carry "unset" meaning, and better not to bet on/conditionalize
48  over signedness of pid_t */
49 #define PCMK__SPECIAL_PID 1
50 
51 // Timeout (in seconds) to use for IPC client sends, reply waits, etc.
52 #define PCMK__IPC_TIMEOUT 120
53 
54 #if defined(HAVE_GETPEEREID)
55 /* on FreeBSD, we don't want to expose "non-yieldable PID" (leading to
56  "IPC liveness check only") as its nominal representation, which could
57  cause confusion -- this is unambiguous as long as there's no
58  socket-based activation like with systemd (very improbable) */
59 #define PCMK__SPECIAL_PID_AS_0(p) (((p) == PCMK__SPECIAL_PID) ? 0 : (p))
60 #else
61 #define PCMK__SPECIAL_PID_AS_0(p) (p)
62 #endif
63 
96 int pcmk__ipc_is_authentic_process_active(const char *name, uid_t refuid,
97  gid_t refgid, pid_t *gotpid);
98 
100 int pcmk__ipc_fd(crm_ipc_t *ipc, int *fd);
101 int pcmk__connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type,
102  int attempts);
103 
104 /*
105  * Server-related
106  */
107 
109 
111  /* Shared */
112  char *buffer;
113  size_t buffer_size;
118  time_t uptime;
119  char *start_state;
120 
121  /* CIB-only */
122  char *token;
123 
124  /* TLS only */
125 # ifdef HAVE_GNUTLS_GNUTLS_H
126  gnutls_session_t *tls_session;
127 # endif
128 };
129 
131  // Lower 32 bits are reserved for server (not library) use
132 
133  // Next 8 bits are reserved for client type (sort of a cheap enum)
134 
136  pcmk__client_ipc = (UINT64_C(1) << 32),
137 
139  pcmk__client_tcp = (UINT64_C(1) << 33),
140 
141 # ifdef HAVE_GNUTLS_GNUTLS_H
143  pcmk__client_tls = (UINT64_C(1) << 34),
144 # endif
145 
146  // The rest are client attributes
147 
149  pcmk__client_proxied = (UINT64_C(1) << 40),
150 
152  pcmk__client_privileged = (UINT64_C(1) << 41),
153 
155  pcmk__client_to_proxy = (UINT64_C(1) << 42),
156 
162  pcmk__client_authenticated = (UINT64_C(1) << 43),
163 
164 # ifdef HAVE_GNUTLS_GNUTLS_H
166  pcmk__client_tls_handshake_complete = (UINT64_C(1) << 44),
167 # endif
168 };
169 
170 #define PCMK__CLIENT_TYPE(client) ((client)->flags & UINT64_C(0xff00000000))
171 
173  unsigned int pid;
174 
175  char *id;
176  char *name;
177  char *user;
178  uint64_t flags; // Group of pcmk__client_flags
179 
181  void *userdata;
182 
184  GQueue *event_queue;
185 
186  /* Depending on the client type, only some of the following will be
187  * populated/valid. @TODO Maybe convert to a union.
188  */
189 
190  qb_ipcs_connection_t *ipcs; /* IPC */
191 
192  struct pcmk__remote_s *remote; /* TCP/TLS */
193 
194  unsigned int queue_backlog; /* IPC queue length after last flush */
195  unsigned int queue_max; /* Evict client whose queue grows this big */
196 };
197 
198 #define pcmk__set_client_flags(client, flags_to_set) do { \
199  (client)->flags = pcmk__set_flags_as(__func__, __LINE__, \
200  LOG_TRACE, \
201  "Client", pcmk__client_name(client), \
202  (client)->flags, (flags_to_set), #flags_to_set); \
203  } while (0)
204 
205 #define pcmk__clear_client_flags(client, flags_to_clear) do { \
206  (client)->flags = pcmk__clear_flags_as(__func__, __LINE__, \
207  LOG_TRACE, \
208  "Client", pcmk__client_name(client), \
209  (client)->flags, (flags_to_clear), #flags_to_clear); \
210  } while (0)
211 
212 #define pcmk__set_ipc_flags(ipc_flags, ipc_name, flags_to_set) do { \
213  ipc_flags = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \
214  "IPC", (ipc_name), \
215  (ipc_flags), (flags_to_set), \
216  #flags_to_set); \
217  } while (0)
218 
219 #define pcmk__clear_ipc_flags(ipc_flags, ipc_name, flags_to_clear) do { \
220  ipc_flags = pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, \
221  "IPC", (ipc_name), \
222  (ipc_flags), (flags_to_clear), \
223  #flags_to_clear); \
224  } while (0)
225 
226 guint pcmk__ipc_client_count(void);
227 void pcmk__foreach_ipc_client(GHFunc func, gpointer user_data);
228 
229 void pcmk__client_cleanup(void);
230 
231 pcmk__client_t *pcmk__find_client(const qb_ipcs_connection_t *c);
232 pcmk__client_t *pcmk__find_client_by_id(const char *id);
233 const char *pcmk__client_name(const pcmk__client_t *c);
234 const char *pcmk__client_type_str(uint64_t client_type);
235 
237 pcmk__client_t *pcmk__new_client(qb_ipcs_connection_t *c, uid_t uid, gid_t gid);
239 void pcmk__drop_all_clients(qb_ipcs_service_t *s);
240 bool pcmk__set_client_queue_max(pcmk__client_t *client, const char *qmax);
241 
242 xmlNode *pcmk__ipc_create_ack_as(const char *function, int line, uint32_t flags,
243  const char *tag, const char *ver, crm_exit_t status);
244 #define pcmk__ipc_create_ack(flags, tag, ver, st) \
245  pcmk__ipc_create_ack_as(__func__, __LINE__, (flags), (tag), (ver), (st))
246 
247 int pcmk__ipc_send_ack_as(const char *function, int line, pcmk__client_t *c,
248  uint32_t request, uint32_t flags, const char *tag,
249  const char *ver, crm_exit_t status);
250 #define pcmk__ipc_send_ack(c, req, flags, tag, ver, st) \
251  pcmk__ipc_send_ack_as(__func__, __LINE__, (c), (req), (flags), (tag), (ver), (st))
252 
253 int pcmk__ipc_prepare_iov(uint32_t request, const xmlNode *message,
254  uint32_t max_send_size,
255  struct iovec **result, ssize_t *bytes);
256 int pcmk__ipc_send_xml(pcmk__client_t *c, uint32_t request,
257  const xmlNode *message, uint32_t flags);
258 int pcmk__ipc_send_iov(pcmk__client_t *c, struct iovec *iov, uint32_t flags);
259 xmlNode *pcmk__client_data2xml(pcmk__client_t *c, void *data,
260  uint32_t *id, uint32_t *flags);
261 
262 int pcmk__client_pid(qb_ipcs_connection_t *c);
263 
264 void pcmk__serve_attrd_ipc(qb_ipcs_service_t **ipcs,
265  struct qb_ipcs_service_handlers *cb);
266 void pcmk__serve_fenced_ipc(qb_ipcs_service_t **ipcs,
267  struct qb_ipcs_service_handlers *cb);
268 void pcmk__serve_pacemakerd_ipc(qb_ipcs_service_t **ipcs,
269  struct qb_ipcs_service_handlers *cb);
270 qb_ipcs_service_t *pcmk__serve_schedulerd_ipc(struct qb_ipcs_service_handlers *cb);
271 qb_ipcs_service_t *pcmk__serve_controld_ipc(struct qb_ipcs_service_handlers *cb);
272 
273 void pcmk__serve_based_ipc(qb_ipcs_service_t **ipcs_ro,
274  qb_ipcs_service_t **ipcs_rw,
275  qb_ipcs_service_t **ipcs_shm,
276  struct qb_ipcs_service_handlers *ro_cb,
277  struct qb_ipcs_service_handlers *rw_cb);
278 
279 void pcmk__stop_based_ipc(qb_ipcs_service_t *ipcs_ro,
280  qb_ipcs_service_t *ipcs_rw,
281  qb_ipcs_service_t *ipcs_shm);
282 
283 static inline const char *
284 pcmk__ipc_sys_name(const char *ipc_name, const char *fallback)
285 {
286  return ipc_name ? ipc_name : ((crm_system_name ? crm_system_name : fallback));
287 }
288 
290 
293 
294 #ifdef __cplusplus
295 }
296 #endif
297 
298 #endif
Client uses TCP connection.
Definition: ipc_internal.h:139
xmlNode * pcmk__client_data2xml(pcmk__client_t *c, void *data, uint32_t *id, uint32_t *flags)
Definition: ipc_server.c:386
pcmk__client_t * pcmk__new_client(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
Definition: ipc_server.c:218
char data[0]
Definition: cpg.c:55
const char * pcmk__pcmkd_api_reply2str(enum pcmk_pacemakerd_api_reply reply)
const char * name
Definition: cib.c:26
const char * pcmk__controld_api_reply2str(enum pcmk_controld_api_reply reply)
Definition: ipc_controld.c:39
size_t buffer_offset
Definition: ipc_internal.h:114
uint64_t flags
Definition: ipc_internal.h:178
qb_ipcs_service_t * pcmk__serve_controld_ipc(struct qb_ipcs_service_handlers *cb)
Definition: ipc_server.c:896
int pcmk__ipc_send_xml(pcmk__client_t *c, uint32_t request, const xmlNode *message, uint32_t flags)
Definition: ipc_server.c:746
struct mainloop_io_s mainloop_io_t
Definition: mainloop.h:33
char * crm_system_name
Definition: utils.c:51
int pcmk__ipc_prepare_iov(uint32_t request, const xmlNode *message, uint32_t max_send_size, struct iovec **result, ssize_t *bytes)
Definition: ipc_server.c:582
enum crm_exit_e crm_exit_t
void pcmk__stop_based_ipc(qb_ipcs_service_t *ipcs_ro, qb_ipcs_service_t *ipcs_rw, qb_ipcs_service_t *ipcs_shm)
Definition: ipc_server.c:878
pcmk_pacemakerd_api_reply
Possible types of pacemakerd replies.
void pcmk__client_cleanup(void)
Definition: ipc_server.c:115
int pcmk__connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type, int attempts)
Definition: ipc_client.c:501
GQueue * event_queue
Definition: ipc_internal.h:184
Wrappers for and extensions to glib mainloop.
int pcmk__client_pid(qb_ipcs_connection_t *c)
Definition: ipc_server.c:365
Client is run by root or cluster user.
Definition: ipc_internal.h:152
int pcmk__connect_generic_ipc(crm_ipc_t *ipc)
Definition: ipc_client.c:895
int pcmk__ipc_send_ack_as(const char *function, int line, pcmk__client_t *c, uint32_t request, uint32_t flags, const char *tag, const char *ver, crm_exit_t status)
Definition: ipc_server.c:814
pcmk__client_t * pcmk__find_client(const qb_ipcs_connection_t *c)
Definition: ipc_server.c:59
struct crm_ipc_s crm_ipc_t
Definition: ipc.h:165
char * start_state
Definition: ipc_internal.h:119
xmlNode * pcmk__ipc_create_ack_as(const char *function, int line, uint32_t flags, const char *tag, const char *ver, crm_exit_t status)
Definition: ipc_server.c:783
size_t buffer_size
Definition: ipc_internal.h:113
int pcmk__ipc_send_iov(pcmk__client_t *c, struct iovec *iov, uint32_t flags)
Definition: ipc_server.c:667
unsigned int pid
Definition: ipc_internal.h:173
IPC commands for Pacemakerd.
IPC commands for Pacemaker controller.
bool pcmk__set_client_queue_max(pcmk__client_t *client, const char *qmax)
Definition: ipc_server.c:350
Client IPC connection accepted.
Definition: ipc_internal.h:162
#define HAVE_GNUTLS_GNUTLS_H
Definition: config.h:184
mainloop_io_t * source
Definition: ipc_internal.h:117
pcmk_pacemakerd_state
pcmk_ipc_dispatch
How IPC replies should be dispatched.
Definition: ipc.h:88
void pcmk__foreach_ipc_client(GHFunc func, gpointer user_data)
Definition: ipc_server.c:51
guint pcmk__ipc_client_count(void)
Definition: ipc_server.c:36
pcmk__action_result_t result
Definition: pcmk_fence.c:35
int pcmk__ipc_fd(crm_ipc_t *ipc, int *fd)
Definition: ipc_client.c:1040
pcmk__client_t * pcmk__find_client_by_id(const char *id)
Definition: ipc_server.c:70
void pcmk__serve_based_ipc(qb_ipcs_service_t **ipcs_ro, qb_ipcs_service_t **ipcs_rw, qb_ipcs_service_t **ipcs_shm, struct qb_ipcs_service_handlers *ro_cb, struct qb_ipcs_service_handlers *rw_cb)
Definition: ipc_server.c:844
const char * pcmk__pcmkd_state_enum2friendly(enum pcmk_pacemakerd_state state)
IPC interface to Pacemaker daemons.
const char * pcmk__client_name(const pcmk__client_t *c)
Definition: ipc_server.c:98
Client uses plain IPC.
Definition: ipc_internal.h:136
const char * pcmk__client_type_str(uint64_t client_type)
Definition: ipc_common.c:96
pcmk__client_t * pcmk__new_unauth_client(void *key)
Allocate a new pcmk__client_t object and generate its ID.
Definition: ipc_server.c:209
Local client to be proxied.
Definition: ipc_internal.h:155
pcmk__client_flags
Definition: ipc_internal.h:130
void pcmk__drop_all_clients(qb_ipcs_service_t *s)
Definition: ipc_server.c:130
void pcmk__serve_fenced_ipc(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition: ipc_server.c:933
unsigned int queue_max
Definition: ipc_internal.h:195
struct pcmk__remote_s * remote
Definition: ipc_internal.h:192
Client IPC is proxied.
Definition: ipc_internal.h:149
void pcmk__serve_attrd_ipc(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition: ipc_server.c:911
void pcmk__serve_pacemakerd_ipc(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition: ipc_server.c:956
int pcmk__ipc_is_authentic_process_active(const char *name, uid_t refuid, gid_t refgid, pid_t *gotpid)
Definition: ipc_client.c:1596
unsigned int queue_backlog
Definition: ipc_internal.h:194
qb_ipcs_connection_t * ipcs
Definition: ipc_internal.h:190
uint64_t flags
Definition: remote.c:215
qb_ipcs_service_t * pcmk__serve_schedulerd_ipc(struct qb_ipcs_service_handlers *cb)
Definition: ipc_server.c:983
void pcmk__free_client(pcmk__client_t *c)
Definition: ipc_server.c:299
pcmk_controld_api_reply
Possible types of controller replies.
Definition: ipc_controld.h:31