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