12 #if defined(HAVE_UCRED) || defined(HAVE_SOCKPEERCRED) 13 #include <sys/socket.h> 14 #elif defined(HAVE_GETPEERUCRED) 19 #include <sys/types.h> 29 static int is_ipc_provider_expected(qb_ipcc_connection_t *qb_ipc,
int sock,
30 uid_t refuid, gid_t refgid, pid_t *gotpid,
31 uid_t *gotuid, gid_t *gotgid);
57 (*api)->server = server;
73 (*api)->ipc_size_max = 512 * 1024;
93 (*api)->ipc_size_max = 5 * 1024 * 1024;
101 if ((*api)->cmds == NULL) {
108 (*api)->ipc_size_max);
109 if ((*api)->ipc == NULL) {
116 if ((*api)->cmds->new_data != NULL) {
117 if ((*api)->cmds->new_data(*api) !=
pcmk_rc_ok) {
130 if ((api != NULL) && (api->
cmds != NULL)) {
153 if ((api != NULL) && (api->
cb != NULL)) {
154 api->
cb(api, event_type, status, event_data, api->
user_data);
167 ipc_post_disconnect(gpointer user_data)
194 free_daemon_specific_data(api);
195 crm_trace(
"Freeing IPC API object after disconnect");
208 bool free_on_disconnect =
false;
215 if (api->
ipc != NULL) {
230 if (!free_on_disconnect) {
231 free_daemon_specific_data(api);
250 return for_log?
"Pacemaker" : NULL;
255 return pcmk__s(
name,
"Pacemaker");
325 if (buffer == NULL) {
326 crm_warn(
"Empty message received from %s IPC",
333 crm_warn(
"Malformed message received from %s IPC",
338 more = call_api_dispatch(api, msg);
361 dispatch_ipc_source_data(
const char *buffer, ssize_t length, gpointer user_data)
366 dispatch_ipc_data(buffer, api);
392 struct pollfd pollfd = { 0, };
400 crm_debug(
"Could not obtain file descriptor for %s IPC: %s",
405 pollfd.events = POLLIN;
406 rc = poll(&pollfd, 1, timeout_ms);
411 return (errno == EAGAIN)? ENOMEM : errno;
412 }
else if (rc == 0) {
448 .
dispatch = dispatch_ipc_source_data,
449 .destroy = ipc_post_disconnect,
457 crm_debug(
"Connected to %s IPC (attached to main loop)",
474 crm_debug(
"Connected to %s IPC (without main loop)",
496 if ((api == NULL) || (attempts < 1)) {
500 if (api->
ipc == NULL) {
502 if (api->
ipc == NULL) {
514 crm_debug(
"Attempting connection to %s (up to %d time%s)",
516 for (
int remaining = attempts - 1; remaining >= 0; --remaining) {
517 switch (dispatch_type) {
519 rc = connect_with_main_loop(api);
524 rc = connect_without_main_loop(api);
528 if ((remaining == 0) || ((rc != EAGAIN) && (rc != EALREADY))) {
534 crm_debug(
"Re-attempting connection to %s (%d attempt%s remaining)",
566 crm_err(
"Connection to %s failed: %s",
586 if ((api == NULL) || (api->
ipc == NULL)) {
616 ipc_post_disconnect(api);
661 xmlNode *reply = NULL;
664 if ((api == NULL) || (api->
ipc == NULL) || (request == NULL)) {
671 && (api->
cmds != NULL)
682 }
else if (rc == 0) {
688 bool more = call_api_dispatch(api, reply);
697 }
else if (rc == -ENOMSG || rc ==
pcmk_ok) {
707 }
else if (rc == EINPROGRESS) {
740 create_purge_node_request(
const pcmk_ipc_api_t *api,
const char *node_name,
743 xmlNode *request = NULL;
794 xmlNode *request = NULL;
799 if ((node_name == NULL) && (nodeid == 0)) {
803 request = create_purge_node_request(api, node_name, nodeid);
804 if (request == NULL) {
810 crm_debug(
"%s peer cache purge of node %s[%lu]: rc=%d",
811 pcmk_ipc_name(api,
true), node_name, (
unsigned long) nodeid, rc);
821 unsigned int max_buf_size;
822 unsigned int buf_size;
827 qb_ipcc_connection_t *ipc;
849 if (client == NULL) {
850 crm_err(
"Could not create IPC connection: %s", strerror(errno));
854 client->server_name = strdup(
name);
855 if (client->server_name == NULL) {
856 crm_err(
"Could not create %s IPC connection: %s",
857 name, strerror(errno));
862 client->buffer = malloc(client->buf_size);
863 if (client->buffer == NULL) {
864 crm_err(
"Could not create %s IPC connection: %s",
865 name, strerror(errno));
866 free(client->server_name);
872 client->max_buf_size = client->buf_size;
875 client->pfd.events = POLLIN;
876 client->pfd.revents = 0;
903 ipc->need_reply = FALSE;
904 ipc->ipc = qb_ipcc_connect(ipc->server_name, ipc->buf_size);
905 if (ipc->ipc == NULL) {
909 rc = qb_ipcc_fd_get(ipc->ipc, &ipc->pfd.fd);
922 rc = is_ipc_provider_expected(ipc->ipc, ipc->pfd.fd, cl_uid, cl_gid,
923 &found_pid, &found_uid, &found_gid);
926 crm_info(
"%s IPC provider authentication failed: process %lld has " 927 "uid %lld (expected %lld) and gid %lld (expected %lld)",
930 (
long long) found_uid, (
long long) cl_uid,
931 (
long long) found_gid, (
long long) cl_gid);
937 ipc->max_buf_size = qb_ipcc_get_buffer_size(ipc->ipc);
938 if (ipc->max_buf_size > ipc->buf_size) {
940 ipc->buffer = calloc(ipc->max_buf_size,
sizeof(
char));
941 if (ipc->buffer == NULL) {
946 ipc->buf_size = ipc->max_buf_size;
957 qb_ipcc_connection_t *ipc = client->ipc;
960 qb_ipcc_disconnect(ipc);
969 if (client->ipc && qb_ipcc_is_connected(client->ipc)) {
970 crm_notice(
"Destroying active %s IPC connection",
971 client->server_name);
982 crm_trace(
"Destroying inactive %s IPC connection",
983 client->server_name);
985 free(client->buffer);
986 free(client->server_name);
1003 if ((ipc == NULL) || (fd == NULL)) {
1006 if ((ipc->ipc == NULL) || (ipc->pfd.fd < 0)) {
1019 crm_err(
"Could not obtain file descriptor for %s IPC",
1020 ((client == NULL)?
"unspecified" : client->server_name));
1032 if (client == NULL) {
1036 }
else if (client->ipc == NULL) {
1040 }
else if (client->pfd.fd < 0) {
1045 rc = qb_ipcc_is_connected(client->ipc);
1047 client->pfd.fd = -EINVAL;
1070 client->pfd.revents = 0;
1071 rc = poll(&(client->pfd), 1, 0);
1072 return (rc < 0)? -errno : rc;
1085 unsigned int new_buf_size = QB_MAX((
sizeof(
pcmk__ipc_header_t) + size_u), client->max_buf_size);
1088 crm_trace(
"Decompressing message data %u bytes into %u bytes",
1096 crm_err(
"Decompression failed: %s " QB_XS
" rc=%d",
1107 free(client->buffer);
1108 client->buf_size = new_buf_size;
1109 client->buffer = uncompressed;
1123 && (client->buffer != NULL));
1125 client->buffer[0] = 0;
1126 client->msg_size = qb_ipcc_event_recv(client->ipc, client->buffer,
1127 client->buf_size, 0);
1128 if (client->msg_size >= 0) {
1129 int rc = crm_ipc_decompress(client);
1140 crm_trace(
"Received %s IPC event %d size=%u rc=%d text='%.100s'",
1141 client->server_name, header->
qb.id, header->
qb.size,
1146 crm_trace(
"No message received from %s IPC: %s",
1149 if (client->msg_size == -EAGAIN) {
1155 crm_err(
"Connection to %s IPC failed", client->server_name);
1178 if (client->buffer == NULL) {
1183 return header->
flags;
1190 return client->server_name;
1195 internal_ipc_get_reply(
crm_ipc_t *client,
int request_id,
int ms_timeout,
1202 crm_trace(
"Waiting on reply to %s IPC message %d",
1203 client->server_name, request_id);
1206 *bytes = qb_ipcc_recv(client->ipc, client->buffer, client->buf_size, 1000);
1210 rc = crm_ipc_decompress(client);
1216 if (hdr->
qb.id == request_id) {
1219 }
else if (hdr->
qb.id < request_id) {
1222 crm_err(
"Discarding old reply %d (need %d)", hdr->
qb.id, request_id);
1228 crm_err(
"Discarding newer reply %d (need %d)", hdr->
qb.id, request_id);
1233 crm_err(
"%s IPC provider disconnected while waiting for message %d",
1234 client->server_name, request_id);
1238 }
while (time(NULL) <
timeout);
1267 static uint32_t
id = 0;
1268 static int factor = 8;
1271 if (client == NULL) {
1272 crm_notice(
"Can't send IPC request without connection (bug?): %.100s",
1278 crm_notice(
"Can't send %s IPC requests: Connection closed",
1279 client->server_name);
1283 if (ms_timeout == 0) {
1287 if (client->need_reply) {
1288 qb_rc = qb_ipcc_recv(client->ipc, client->buffer, client->buf_size, ms_timeout);
1290 crm_warn(
"Sending %s IPC disabled until pending reply received",
1291 client->server_name);
1295 crm_notice(
"Sending %s IPC re-enabled after pending reply received",
1296 client->server_name);
1297 client->need_reply = FALSE;
1305 crm_warn(
"Couldn't prepare %s IPC request: %s " QB_XS
" rc=%d",
1310 header = iov[0].iov_base;
1319 if(factor < 10 && (client->max_buf_size / 10) < (bytes / factor)) {
1320 crm_notice(
"Compressed message exceeds %d0%% of configured IPC " 1321 "limit (%u bytes); consider setting PCMK_ipc_buffer to " 1323 factor, client->max_buf_size, 2 * client->max_buf_size);
1328 crm_trace(
"Sending %s IPC request %d of %u bytes using %dms timeout",
1329 client->server_name, header->
qb.id, header->
qb.size, ms_timeout);
1343 qb_rc = qb_ipcc_sendv(client->ipc, iov, 2);
1344 }
while ((qb_rc == -EAGAIN) && (time(NULL) <
timeout));
1351 crm_trace(
"Not waiting for reply to %s IPC request %d",
1352 client->server_name, header->
qb.id);
1356 rc = internal_ipc_get_reply(client, header->
qb.id, ms_timeout, &bytes);
1364 client->need_reply = TRUE;
1371 qb_rc = qb_ipcc_sendv_recv(client->ipc, iov, 2, client->buffer,
1372 client->buf_size, -1);
1380 crm_trace(
"Received %d-byte reply %d to %s IPC %d: %.100s",
1381 rc, hdr->
qb.id, client->server_name, header->
qb.id,
1389 crm_trace(
"No reply to %s IPC %d: rc=%d",
1390 client->server_name, header->
qb.id, rc);
1395 crm_notice(
"Couldn't send %s IPC request %d: Connection closed " 1396 QB_XS
" rc=%d", client->server_name, header->
qb.id, rc);
1398 }
else if (rc == -ETIMEDOUT) {
1399 crm_warn(
"%s IPC request %d failed: %s after %dms " QB_XS
" rc=%d",
1404 }
else if (rc <= 0) {
1405 crm_warn(
"%s IPC request %d failed: %s " QB_XS
" rc=%d",
1406 client->server_name, header->
qb.id,
1432 is_ipc_provider_expected(qb_ipcc_connection_t *qb_ipc,
int sock,
1433 uid_t refuid, gid_t refgid,
1434 pid_t *gotpid, uid_t *gotuid, gid_t *gotgid)
1436 int rc = EOPNOTSUPP;
1437 pid_t found_pid = 0;
1438 uid_t found_uid = 0;
1439 gid_t found_gid = 0;
1441 #ifdef HAVE_QB_IPCC_AUTH_GET 1442 if (qb_ipc != NULL) {
1443 rc = qb_ipcc_auth_get(qb_ipc, &found_pid, &found_uid, &found_gid);
1454 socklen_t ucred_len =
sizeof(ucred);
1456 if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &ucred_len) < 0) {
1458 }
else if (ucred_len !=
sizeof(ucred)) {
1461 found_pid = ucred.pid;
1462 found_uid = ucred.uid;
1463 found_gid = ucred.gid;
1469 #ifdef HAVE_SOCKPEERCRED 1471 struct sockpeercred sockpeercred;
1472 socklen_t sockpeercred_len =
sizeof(sockpeercred);
1474 if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED,
1475 &sockpeercred, &sockpeercred_len) < 0) {
1477 }
else if (sockpeercred_len !=
sizeof(sockpeercred)) {
1480 found_pid = sockpeercred.pid;
1481 found_uid = sockpeercred.uid;
1482 found_gid = sockpeercred.gid;
1488 #ifdef HAVE_GETPEEREID // For example, FreeBSD 1489 if (getpeereid(sock, &found_uid, &found_gid) < 0) {
1497 #ifdef HAVE_GETPEERUCRED 1499 ucred_t *ucred = NULL;
1501 if (getpeerucred(sock, &ucred) < 0) {
1504 found_pid = ucred_getpid(ucred);
1505 found_uid = ucred_geteuid(ucred);
1506 found_gid = ucred_getegid(ucred);
1516 if (gotpid != NULL) {
1517 *gotpid = found_pid;
1519 if (gotuid != NULL) {
1520 *gotuid = found_uid;
1522 if (gotgid != NULL) {
1523 *gotgid = found_gid;
1525 if ((found_uid != 0) && (found_uid != refuid) && (found_gid != refgid)) {
1533 pid_t *gotpid, uid_t *gotuid, gid_t *gotgid)
1535 int ret = is_ipc_provider_expected(NULL, sock, refuid, refgid,
1536 gotpid, gotuid, gotgid);
1550 gid_t refgid, pid_t *gotpid)
1552 static char last_asked_name[PATH_MAX / 2] =
"";
1557 pid_t found_pid = 0; uid_t found_uid = 0; gid_t found_gid = 0;
1558 qb_ipcc_connection_t *c;
1559 #ifdef HAVE_QB_IPCC_CONNECT_ASYNC 1560 struct pollfd pollfd = { 0, };
1563 c = qb_ipcc_connect_async(
name, 0,
1566 c = qb_ipcc_connect(
name, 0);
1569 crm_info(
"Could not connect to %s IPC: %s",
name, strerror(errno));
1573 #ifdef HAVE_QB_IPCC_CONNECT_ASYNC 1574 pollfd.events = POLLIN;
1576 poll_rc = poll(&pollfd, 1, 2000);
1577 }
while ((poll_rc == -1) && (errno == EINTR));
1584 if (qb_ipcc_connect_continue(c) != 0) {
1586 (poll_rc == 0)?
"timeout":strerror(errno));
1593 qb_rc = qb_ipcc_fd_get(c, &fd);
1596 crm_err(
"Could not get fd from %s IPC: %s " QB_XS
" rc=%d",
1601 auth_rc = is_ipc_provider_expected(c, fd, refuid, refgid,
1602 &found_pid, &found_uid, &found_gid);
1604 crm_err(
"Daemon (IPC %s) effectively blocked with unauthorized" 1605 " process %lld (uid: %lld, gid: %lld)",
1607 (
long long) found_uid, (
long long) found_gid);
1614 crm_err(
"Could not get peer credentials from %s IPC: %s " 1619 if (gotpid != NULL) {
1620 *gotpid = found_pid;
1624 if ((found_uid != refuid || found_gid != refgid)
1625 && strncmp(last_asked_name,
name,
sizeof(last_asked_name))) {
1626 if ((found_uid == 0) && (refuid != 0)) {
1627 crm_warn(
"Daemon (IPC %s) runs as root, whereas the expected" 1628 " credentials are %lld:%lld, hazard of violating" 1629 " the least privilege principle",
1630 name, (
long long) refuid, (
long long) refgid);
1632 crm_notice(
"Daemon (IPC %s) runs as %lld:%lld, whereas the" 1633 " expected credentials are %lld:%lld, which may" 1634 " mean a different set of privileges than expected",
1635 name, (
long long) found_uid, (
long long) found_gid,
1636 (
long long) refuid, (
long long) refgid);
1638 memccpy(last_asked_name,
name,
'\0',
sizeof(last_asked_name));
1643 qb_ipcc_disconnect(c);
1661 if ((client != NULL) && (client->ipc == NULL)) {
1662 errno = (rc > 0)? rc : ENOTCONN;
1663 crm_debug(
"Could not establish %s IPC connection: %s (%d)",
1666 crm_err(
"%s IPC provider authentication failed",
1667 (client == NULL)?
"Pacemaker" : client->server_name);
1668 errno = ECONNABORTED;
1670 crm_err(
"Could not verify authenticity of %s IPC provider",
1671 (client == NULL)?
"Pacemaker" : client->server_name);
#define CRM_CHECK(expr, failure_action)
int pcmk__ipc_fd(crm_ipc_t *ipc, int *fd)
#define crm_notice(fmt, args...)
const char * pcmk_strerror(int rc)
const char * pcmk__server_log_name(enum pcmk_ipc_server server)
enum pcmk_ipc_dispatch dispatch_type
#define PCMK__ATTRD_CMD_PEER_REMOVE
int pcmk__send_ipc_request(pcmk_ipc_api_t *api, const xmlNode *request)
int pcmk_rc2legacy(int rc)
void pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value)
long crm_ipc_read(crm_ipc_t *client)
#define PCMK__VALUE_ATTRD
void pcmk_free_ipc_api(pcmk_ipc_api_t *api)
Free the contents of an IPC API object.
Deprecated Pacemaker IPC APIs.
G_GNUC_INTERNAL pcmk__ipc_methods_t * pcmk__schedulerd_api_methods(void)
G_GNUC_INTERNAL pcmk__ipc_methods_t * pcmk__pacemakerd_api_methods(void)
const char * crm_ipc_buffer(crm_ipc_t *client)
int pcmk_ipc_purge_node(pcmk_ipc_api_t *api, const char *node_name, uint32_t nodeid)
Ask a Pacemaker daemon to purge a node from its peer cache.
struct mainloop_io_s mainloop_io_t
#define PCMK__SPECIAL_PID_AS_0(p)
int pcmk_new_ipc_api(pcmk_ipc_api_t **api, enum pcmk_ipc_server server)
Create a new object for using Pacemaker daemon IPC.
#define PCMK__SPECIAL_PID
int pcmk__ipc_prepare_iov(uint32_t request, const xmlNode *message, uint32_t max_send_size, struct iovec **result, ssize_t *bytes)
enum crm_exit_e crm_exit_t
void crm_ipc_destroy(crm_ipc_t *client)
const char * pcmk__server_ipc_name(enum pcmk_ipc_server server)
int pcmk_poll_ipc(const pcmk_ipc_api_t *api, int timeout_ms)
Check whether an IPC connection has data available (without main loop)
#define CRM_LOG_ASSERT(expr)
int pcmk_daemon_user(uid_t *uid, gid_t *gid)
Get user and group IDs of pacemaker daemon user.
struct pcmk__ipc_header_s pcmk__ipc_header_t
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
int crm_ipc_get_fd(crm_ipc_t *client)
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
int pcmk__ipc_is_authentic_process_active(const char *name, uid_t refuid, gid_t refgid, pid_t *gotpid)
const char * crm_xml_add_ll(xmlNode *node, const char *name, long long value)
Create an XML attribute with specified name and long long int value.
void pcmk__xml_free(xmlNode *xml)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Caller will poll and dispatch IPC.
#define crm_warn(fmt, args...)
pcmk_ipc_server
Available IPC interfaces.
void pcmk__sleep_ms(unsigned int ms)
#define crm_debug(fmt, args...)
bool crm_ipc_connect(crm_ipc_t *client)
crm_ipc_t * crm_ipc_new(const char *name, size_t max_size)
Create a new (legacy) object for using Pacemaker daemon IPC.
struct crm_ipc_s crm_ipc_t
void pcmk_register_ipc_callback(pcmk_ipc_api_t *api, pcmk_ipc_callback_t cb, void *user_data)
Register a callback for IPC API events.
G_GNUC_INTERNAL pcmk__ipc_methods_t * pcmk__attrd_api_methods(void)
#define crm_trace(fmt, args...)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
void pcmk__call_ipc_callback(pcmk_ipc_api_t *api, enum pcmk_ipc_event event_type, crm_exit_t status, void *event_data)
uint32_t crm_ipc_buffer_flags(crm_ipc_t *client)
#define pcmk__clear_ipc_flags(ipc_flags, ipc_name, flags_to_clear)
Wrappers for and extensions to libxml2.
void pcmk_disconnect_ipc(pcmk_ipc_api_t *api)
Disconnect an IPC API instance.
G_GNUC_INTERNAL bool pcmk__valid_ipc_header(const pcmk__ipc_header_t *header)
const char * pcmk_ipc_name(const pcmk_ipc_api_t *api, bool for_log)
Get the IPC name used with an IPC API connection.
void crm_ipc_close(crm_ipc_t *client)
#define pcmk__new_request(server, sender_system, recipient_node, recipient_system, task, data)
void mainloop_del_ipc_client(mainloop_io_t *client)
int pcmk_legacy2rc(int legacy_rc)
void pcmk_free_ipc_event(struct iovec *event)
Free an I/O vector created by pcmk__ipc_prepare_iov()
void(* pcmk_ipc_callback_t)(pcmk_ipc_api_t *api, enum pcmk_ipc_event event_type, crm_exit_t status, void *event_data, void *user_data)
Callback function type for Pacemaker daemon IPC APIs.
int(* post_connect)(pcmk_ipc_api_t *api)
int pcmk__add_mainloop_ipc(crm_ipc_t *ipc, int priority, void *userdata, const struct ipc_client_callbacks *callbacks, mainloop_io_t **source)
Connect to IPC and add it as a main loop source.
xmlNode * pcmk__xml_parse(const char *input)
void crm_write_blackbox(int nsig, const struct qb_log_callsite *callsite)
G_GNUC_INTERNAL unsigned int pcmk__ipc_buffer_size(unsigned int max)
int pcmk__connect_generic_ipc(crm_ipc_t *ipc)
#define pcmk__assert(expr)
#define CRM_OP_RM_NODE_CACHE
pcmk_ipc_dispatch
How IPC replies should be dispatched.
int pcmk__bzlib2rc(int bz2)
Map a bz2 return code to the most similar Pacemaker return code.
pcmk_ipc_event
Possible event types that an IPC event callback can be called for.
bool crm_ipc_connected(crm_ipc_t *client)
Attach IPC to GMainLoop for dispatch.
Termination of IPC connection.
mainloop_io_t * mainloop_io
bool(* dispatch)(pcmk_ipc_api_t *api, xmlNode *msg)
bool(* reply_expected)(pcmk_ipc_api_t *api, const xmlNode *request)
#define pcmk__set_ipc_flags(ipc_flags, ipc_name, flags_to_set)
#define crm_err(fmt, args...)
Sending a command will wait for any reply.
void pcmk_dispatch_ipc(pcmk_ipc_api_t *api)
Dispatch available messages on an IPC connection (without main loop)
#define crm_log_xml_notice(xml, text)
Lost connection to something.
int crm_ipc_ready(crm_ipc_t *client)
Check whether an IPC connection is ready to be read.
guint pcmk__timeout_ms2s(guint timeout_ms)
void(* free_data)(void *api_data)
#define pcmk__plural_s(i)
bool pcmk_ipc_is_connected(pcmk_ipc_api_t *api)
Check whether an IPC API connection is active.
IPC interface to Pacemaker daemons.
int pcmk__connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type, int attempts)
int pcmk_connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type)
Connect to a Pacemaker daemon via IPC.
#define crm_log_xml_trace(xml, text)
G_GNUC_INTERNAL pcmk__ipc_methods_t * pcmk__controld_api_methods(void)
pcmk__ipc_methods_t * cmds
int crm_ipc_send(crm_ipc_t *client, const xmlNode *message, enum crm_ipc_flags flags, int32_t ms_timeout, xmlNode **reply)
Send an IPC XML message.
void pcmk__xe_add_node(xmlNode *xml, const char *node, int nodeid)
void(* post_disconnect)(pcmk_ipc_api_t *api)
enum pcmk_ipc_server server
#define pcmk__assert_alloc(nmemb, size)
#define crm_info(fmt, args...)
int(* dispatch)(const char *buffer, ssize_t length, gpointer userdata)
Dispatch function for an IPC connection used as mainloop source.
int crm_ipc_is_authentic_process(int sock, uid_t refuid, gid_t refgid, pid_t *gotpid, uid_t *gotuid, gid_t *gotgid)
Check the authenticity of the IPC socket peer process (legacy)
const char * crm_ipc_name(crm_ipc_t *client)