1 /*
2 * Copyright 2004-2025 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__CRM_COMMON_IPC__H
11 #define PCMK__CRM_COMMON_IPC__H
12
13 #include <stdint.h>
14 #include <sys/uio.h>
15 #include <qb/qbipcc.h>
16 #include <crm/common/xml.h>
17
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21
22 /**
23 * \file
24 * \brief IPC interface to Pacemaker daemons
25 *
26 * \ingroup core
27 */
28
29 /*
30 * The library supports two methods of creating IPC connections. The older code
31 * allows connecting to any arbitrary IPC name. The newer code only allows
32 * connecting to one of the Pacemaker daemons.
33 *
34 * As daemons are converted to use the new model, the old functions should be
35 * considered deprecated for use with those daemons. Once all daemons are
36 * converted, the old functions should be officially deprecated as public API
37 * and eventually made internal API.
38 */
39
40 /*
41 * Pacemaker daemon IPC
42 */
43
44 /* @COMPAT This is also used internally for cluster message types, but it's not
45 * worth the hassle of redefining this public API just to change the name.
46 */
47 //! Available IPC interfaces
48 enum pcmk_ipc_server {
49 pcmk_ipc_unknown, //!< Unknown or invalid
50 pcmk_ipc_attrd, //!< Attribute manager
51 pcmk_ipc_based, //!< CIB manager
52 pcmk_ipc_controld, //!< Controller
53 pcmk_ipc_execd, //!< Executor
54 pcmk_ipc_fenced, //!< Fencer
55 pcmk_ipc_pacemakerd, //!< Launcher
56 pcmk_ipc_schedulerd, //!< Scheduler
57 };
58
59 // NOTE: sbd (as of at least 1.5.2) uses this enum
60 //! Possible event types that an IPC event callback can be called for
61 enum pcmk_ipc_event {
62 pcmk_ipc_event_connect, //!< Result of asynchronous connection attempt
63
64 // NOTE: sbd (as of at least 1.5.2) uses this value
65 pcmk_ipc_event_disconnect, //!< Termination of IPC connection
66
67 // NOTE: sbd (as of at least 1.5.2) uses this value
68 pcmk_ipc_event_reply, //!< Daemon's reply to client IPC request
69
70 pcmk_ipc_event_notify, //!< Notification from daemon
71 };
72
73 //! How IPC replies should be dispatched
74 enum pcmk_ipc_dispatch {
75 pcmk_ipc_dispatch_main, //!< Attach IPC to GMainLoop for dispatch
76 pcmk_ipc_dispatch_poll, //!< Caller will poll and dispatch IPC
77 pcmk_ipc_dispatch_sync, //!< Sending a command will wait for any reply
78 };
79
80 // NOTE: sbd (as of at least 1.5.2) uses this
81 //! Client connection to Pacemaker IPC
82 typedef struct pcmk_ipc_api_s pcmk_ipc_api_t;
83
84 /*!
85 * \brief Callback function type for Pacemaker daemon IPC APIs
86 *
87 * \param[in,out] api IPC API connection
88 * \param[in] event_type The type of event that occurred
89 * \param[in] status Event status
90 * \param[in,out] event_data Event-specific data
91 * \param[in,out] user_data Caller data provided when callback was registered
92 *
93 * \note For connection and disconnection events, event_data may be NULL (for
94 * local IPC) or the name of the connected node (for remote IPC, for
95 * daemons that support that). For reply and notify events, event_data is
96 * defined by the specific daemon API.
97 */
98 typedef void (*pcmk_ipc_callback_t)(pcmk_ipc_api_t *api,
99 enum pcmk_ipc_event event_type,
100 crm_exit_t status,
101 void *event_data, void *user_data);
102
103 // NOTE: sbd (as of at least 1.5.2) uses this
104 int pcmk_new_ipc_api(pcmk_ipc_api_t **api, enum pcmk_ipc_server server);
105
106 // NOTE: sbd (as of at least 1.5.2) uses this
107 void pcmk_free_ipc_api(pcmk_ipc_api_t *api);
108
109 // NOTE: sbd (as of at least 1.5.2) uses this
110 int pcmk_connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type);
111
112 void pcmk_disconnect_ipc(pcmk_ipc_api_t *api);
113
114 int pcmk_poll_ipc(const pcmk_ipc_api_t *api, int timeout_ms);
115
116 void pcmk_dispatch_ipc(pcmk_ipc_api_t *api);
117
118 // NOTE: sbd (as of at least 1.5.2) uses this
119 void pcmk_register_ipc_callback(pcmk_ipc_api_t *api, pcmk_ipc_callback_t cb,
120 void *user_data);
121
122 const char *pcmk_ipc_name(const pcmk_ipc_api_t *api, bool for_log);
123
124 bool pcmk_ipc_is_connected(pcmk_ipc_api_t *api);
125
126 int pcmk_ipc_purge_node(pcmk_ipc_api_t *api, const char *node_name,
127 uint32_t nodeid);
128
129
130 /*
131 * Generic IPC API (to eventually be deprecated as public API and made internal)
132 */
133
134 enum crm_ipc_flags
135 {
136 crm_ipc_flags_none = UINT32_C(0),
137 //! \deprecated Since 3.0.1
138 crm_ipc_compressed = (UINT32_C(1) << 0),
139 //! _ALL_ replies to proxied connections need to be sent as events
140 crm_ipc_proxied = (UINT32_C(1) << 8),
141 //! A response is expected in reply
142 crm_ipc_client_response = (UINT32_C(1) << 9),
143
144 // These are options for Pacemaker's internal use only (pcmk__ipc_send_*())
145
146 //! Send an Event instead of a Response
147 crm_ipc_server_event = (UINT32_C(1) << 16),
148 //! Free the iovec after sending
149 crm_ipc_server_free = (UINT32_C(1) << 17),
150 //! All replies to proxied connections are sent as events. This flag
151 //! preserves whether the events should be treated as an Event or a Response
152 crm_ipc_proxied_relay_response = (UINT32_C(1) << 18),
153 //! This is a multi-part IPC message
154 crm_ipc_multipart = (UINT32_C(1) << 19),
155 //! This is the end of a multi-part IPC message
156 crm_ipc_multipart_end = (UINT32_C(1) << 20),
157 };
158
159 typedef struct crm_ipc_s crm_ipc_t;
160
161 crm_ipc_t *crm_ipc_new(const char *name, size_t max_size);
162 void crm_ipc_close(crm_ipc_t * client);
163 void crm_ipc_destroy(crm_ipc_t * client);
164 void pcmk_free_ipc_event(struct iovec *event);
165
166 int crm_ipc_send(crm_ipc_t *client, const xmlNode *message,
167 enum crm_ipc_flags flags, int32_t ms_timeout, xmlNode **reply);
168
169 int crm_ipc_get_fd(crm_ipc_t * client);
170 bool crm_ipc_connected(crm_ipc_t * client);
171 int crm_ipc_ready(crm_ipc_t * client);
172 long crm_ipc_read(crm_ipc_t * client);
173 const char *crm_ipc_buffer(crm_ipc_t * client);
174 uint32_t crm_ipc_buffer_flags(crm_ipc_t * client);
175 const char *crm_ipc_name(crm_ipc_t * client);
176 unsigned int crm_ipc_default_buffer_size(void);
177
178 /*!
179 * \brief Check the authenticity of the IPC socket peer process (legacy)
180 *
181 * If everything goes well, peer's authenticity is verified by the means
182 * of comparing against provided referential UID and GID (either satisfies),
183 * and the result of this check can be deduced from the return value.
184 * As an exception, detected UID of 0 ("root") satisfies arbitrary
185 * provided referential daemon's credentials.
186 *
187 * \param[in] sock IPC related, connected Unix socket to check peer of
188 * \param[in] refuid referential UID to check against
189 * \param[in] refgid referential GID to check against
190 * \param[out] gotpid to optionally store obtained PID of the peer
191 * (not available on FreeBSD, special value of 1
192 * used instead, and the caller is required to
193 * special case this value respectively)
194 * \param[out] gotuid to optionally store obtained UID of the peer
195 * \param[out] gotgid to optionally store obtained GID of the peer
196 *
197 * \return 0 if IPC related socket's peer is not authentic given the
198 * referential credentials (see above), 1 if it is,
199 * negative value on error (generally expressing -errno unless
200 * it was zero even on nonhappy path, -pcmk_err_generic is
201 * returned then; no message is directly emitted)
202 *
203 * \note While this function is tolerant on what constitutes authorized
204 * IPC daemon process (its effective user matches UID=0 or \p refuid,
205 * or at least its group matches \p refgid), either or both (in case
206 * of UID=0) mismatches on the expected credentials of such peer
207 * process \e shall be investigated at the caller when value of 1
208 * gets returned there, since higher-than-expected privileges in
209 * respect to the expected/intended credentials possibly violate
210 * the least privilege principle and may pose an additional risk
211 * (i.e. such accidental inconsistency shall be eventually fixed).
212 */
213 int crm_ipc_is_authentic_process(int sock, uid_t refuid, gid_t refgid,
214 pid_t *gotpid, uid_t *gotuid, gid_t *gotgid);
215
216 #ifdef __cplusplus
217 }
218 #endif
219
220 #endif