1 /*
2 * Copyright 2004-2024 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
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 * Message creation utilities
31 *
32 * These are used for both IPC messages and cluster layer messages. However,
33 * since this is public API, they stay in this header for backward
34 * compatibility.
35 */
36
37 // @COMPAT Make internal when we can break API backward compatibility
38 //! \deprecated Do not use
39 #define create_reply(request, xml_response_data) \
40 create_reply_adv(request, xml_response_data, __func__)
41
42 // @COMPAT Make internal when we can break API backward compatibility
43 //! \deprecated Do not use
44 xmlNode *create_reply_adv(const xmlNode *request, xmlNode *xml_response_data,
45 const char *origin);
46
47 // @COMPAT Make internal when we can break API backward compatibility
48 //! \deprecated Do not use
49 #define create_request(task, xml_data, host_to, sys_to, sys_from, uuid_from) \
50 create_request_adv(task, xml_data, host_to, sys_to, sys_from, uuid_from, \
51 __func__)
52
53 // @COMPAT Make internal when we can break API backward compatibility
54 //! \deprecated Do not use
55 xmlNode *create_request_adv(const char *task, xmlNode *xml_data,
56 const char *host_to, const char *sys_to,
57 const char *sys_from, const char *uuid_from,
58 const char *origin);
59
60
61 /*
62 * The library supports two methods of creating IPC connections. The older code
63 * allows connecting to any arbitrary IPC name. The newer code only allows
64 * connecting to one of the Pacemaker daemons.
65 *
66 * As daemons are converted to use the new model, the old functions should be
67 * considered deprecated for use with those daemons. Once all daemons are
68 * converted, the old functions should be officially deprecated as public API
69 * and eventually made internal API.
70 */
71
72 /*
73 * Pacemaker daemon IPC
74 */
75
76 //! Available IPC interfaces
77 enum pcmk_ipc_server {
78 pcmk_ipc_attrd, //!< Attribute manager
79 pcmk_ipc_based, //!< CIB manager
80 pcmk_ipc_controld, //!< Controller
81 pcmk_ipc_execd, //!< Executor
82 pcmk_ipc_fenced, //!< Fencer
83 pcmk_ipc_pacemakerd, //!< Launcher
84 pcmk_ipc_schedulerd, //!< Scheduler
85 };
86
87 // NOTE: sbd (as of at least 1.5.2) uses this enum
88 //! Possible event types that an IPC event callback can be called for
89 enum pcmk_ipc_event {
90 pcmk_ipc_event_connect, //!< Result of asynchronous connection attempt
91
92 // NOTE: sbd (as of at least 1.5.2) uses this value
93 pcmk_ipc_event_disconnect, //!< Termination of IPC connection
94
95 // NOTE: sbd (as of at least 1.5.2) uses this value
96 pcmk_ipc_event_reply, //!< Daemon's reply to client IPC request
97
98 pcmk_ipc_event_notify, //!< Notification from daemon
99 };
100
101 //! How IPC replies should be dispatched
102 enum pcmk_ipc_dispatch {
103 pcmk_ipc_dispatch_main, //!< Attach IPC to GMainLoop for dispatch
104 pcmk_ipc_dispatch_poll, //!< Caller will poll and dispatch IPC
105 pcmk_ipc_dispatch_sync, //!< Sending a command will wait for any reply
106 };
107
108 // NOTE: sbd (as of at least 1.5.2) uses this
109 //! Client connection to Pacemaker IPC
110 typedef struct pcmk_ipc_api_s pcmk_ipc_api_t;
111
112 /*!
113 * \brief Callback function type for Pacemaker daemon IPC APIs
114 *
115 * \param[in,out] api IPC API connection
116 * \param[in] event_type The type of event that occurred
117 * \param[in] status Event status
118 * \param[in,out] event_data Event-specific data
119 * \param[in,out] user_data Caller data provided when callback was registered
120 *
121 * \note For connection and disconnection events, event_data may be NULL (for
122 * local IPC) or the name of the connected node (for remote IPC, for
123 * daemons that support that). For reply and notify events, event_data is
124 * defined by the specific daemon API.
125 */
126 typedef void (*pcmk_ipc_callback_t)(pcmk_ipc_api_t *api,
127 enum pcmk_ipc_event event_type,
128 crm_exit_t status,
129 void *event_data, void *user_data);
130
131 // NOTE: sbd (as of at least 1.5.2) uses this
132 int pcmk_new_ipc_api(pcmk_ipc_api_t **api, enum pcmk_ipc_server server);
133
134 // NOTE: sbd (as of at least 1.5.2) uses this
135 void pcmk_free_ipc_api(pcmk_ipc_api_t *api);
136
137 // NOTE: sbd (as of at least 1.5.2) uses this
138 int pcmk_connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type);
139
140 void pcmk_disconnect_ipc(pcmk_ipc_api_t *api);
141
142 int pcmk_poll_ipc(const pcmk_ipc_api_t *api, int timeout_ms);
143
144 void pcmk_dispatch_ipc(pcmk_ipc_api_t *api);
145
146 // NOTE: sbd (as of at least 1.5.2) uses this
147 void pcmk_register_ipc_callback(pcmk_ipc_api_t *api, pcmk_ipc_callback_t cb,
148 void *user_data);
149
150 const char *pcmk_ipc_name(const pcmk_ipc_api_t *api, bool for_log);
151
152 bool pcmk_ipc_is_connected(pcmk_ipc_api_t *api);
153
154 int pcmk_ipc_purge_node(pcmk_ipc_api_t *api, const char *node_name,
155 uint32_t nodeid);
156
157
158 /*
159 * Generic IPC API (to eventually be deprecated as public API and made internal)
160 */
161
162 /* *INDENT-OFF* */
163 enum crm_ipc_flags
164 {
165 crm_ipc_flags_none = 0x00000000,
166
167 crm_ipc_compressed = 0x00000001, /* Message has been compressed */
168
169 crm_ipc_proxied = 0x00000100, /* _ALL_ replies to proxied connections need to be sent as events */
170 crm_ipc_client_response = 0x00000200, /* A Response is expected in reply */
171
172 // These are options for Pacemaker's internal use only (pcmk__ipc_send_*())
173 crm_ipc_server_event = 0x00010000, /* Send an Event instead of a Response */
174 crm_ipc_server_free = 0x00020000, /* Free the iovec after sending */
175 crm_ipc_proxied_relay_response = 0x00040000, /* all replies to proxied connections are sent as events, this flag preserves whether the event should be treated as an actual event, or a response.*/
176
177 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
178 crm_ipc_server_info = 0x00100000, //!< \deprecated Unused
179 crm_ipc_server_error = 0x00200000, //!< \deprecated Unused
180 #endif
181 };
182 /* *INDENT-ON* */
183
184 typedef struct crm_ipc_s crm_ipc_t;
185
186 crm_ipc_t *crm_ipc_new(const char *name, size_t max_size);
187 bool crm_ipc_connect(crm_ipc_t * client);
188 void crm_ipc_close(crm_ipc_t * client);
189 void crm_ipc_destroy(crm_ipc_t * client);
190 void pcmk_free_ipc_event(struct iovec *event);
191
192 int crm_ipc_send(crm_ipc_t *client, const xmlNode *message,
193 enum crm_ipc_flags flags, int32_t ms_timeout, xmlNode **reply);
194
195 int crm_ipc_get_fd(crm_ipc_t * client);
196 bool crm_ipc_connected(crm_ipc_t * client);
197 int crm_ipc_ready(crm_ipc_t * client);
198 long crm_ipc_read(crm_ipc_t * client);
199 const char *crm_ipc_buffer(crm_ipc_t * client);
200 uint32_t crm_ipc_buffer_flags(crm_ipc_t * client);
201 const char *crm_ipc_name(crm_ipc_t * client);
202 unsigned int crm_ipc_default_buffer_size(void);
203
204 /*!
205 * \brief Check the authenticity of the IPC socket peer process (legacy)
206 *
207 * If everything goes well, peer's authenticity is verified by the means
208 * of comparing against provided referential UID and GID (either satisfies),
209 * and the result of this check can be deduced from the return value.
210 * As an exception, detected UID of 0 ("root") satisfies arbitrary
211 * provided referential daemon's credentials.
212 *
213 * \param[in] sock IPC related, connected Unix socket to check peer of
214 * \param[in] refuid referential UID to check against
215 * \param[in] refgid referential GID to check against
216 * \param[out] gotpid to optionally store obtained PID of the peer
217 * (not available on FreeBSD, special value of 1
218 * used instead, and the caller is required to
219 * special case this value respectively)
220 * \param[out] gotuid to optionally store obtained UID of the peer
221 * \param[out] gotgid to optionally store obtained GID of the peer
222 *
223 * \return 0 if IPC related socket's peer is not authentic given the
224 * referential credentials (see above), 1 if it is,
225 * negative value on error (generally expressing -errno unless
226 * it was zero even on nonhappy path, -pcmk_err_generic is
227 * returned then; no message is directly emitted)
228 *
229 * \note While this function is tolerant on what constitutes authorized
230 * IPC daemon process (its effective user matches UID=0 or \p refuid,
231 * or at least its group matches \p refgid), either or both (in case
232 * of UID=0) mismatches on the expected credentials of such peer
233 * process \e shall be investigated at the caller when value of 1
234 * gets returned there, since higher-than-expected privileges in
235 * respect to the expected/intended credentials possibly violate
236 * the least privilege principle and may pose an additional risk
237 * (i.e. such accidental inconsistency shall be eventually fixed).
238 */
239 int crm_ipc_is_authentic_process(int sock, uid_t refuid, gid_t refgid,
240 pid_t *gotpid, uid_t *gotuid, gid_t *gotgid);
241
242 // @COMPAT Make internal when we can break API backward compatibility
243 //! \deprecated Do not use
244 xmlNode *create_hello_message(const char *uuid, const char *client_name,
245 const char *major_version, const char *minor_version);
246
247 #ifdef __cplusplus
248 }
249 #endif
250
251 #endif