diff --git a/daemons/attrd/attrd_ipc.c b/daemons/attrd/attrd_ipc.c index 43e0f41824c..be87c00fa08 100644 --- a/daemons/attrd/attrd_ipc.c +++ b/daemons/attrd/attrd_ipc.c @@ -596,7 +596,7 @@ attrd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size) if (xml == NULL) { crm_debug("Unrecognizable IPC data from PID %d", pcmk__client_pid(c)); - pcmk__ipc_send_ack(client, id, flags, PCMK__XE_ACK, NULL, + pcmk__ipc_send_ack(client, id, flags, PCMK__XE_NACK, NULL, CRM_EX_PROTOCOL); return 0; diff --git a/daemons/attrd/attrd_messages.c b/daemons/attrd/attrd_messages.c index 27cdadb6697..5cee2ffbd66 100644 --- a/daemons/attrd/attrd_messages.c +++ b/daemons/attrd/attrd_messages.c @@ -59,7 +59,8 @@ handle_unknown_request(pcmk__request_t *request) request->op, pcmk__request_origin_type(request), pcmk__request_origin(request)); pcmk__format_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID, - "Unknown request type '%s' (bug?)", request->op); + "Unknown request type '%s' (bug?)", + pcmk__s(request->op, "")); return NULL; } diff --git a/daemons/attrd/attrd_sync.c b/daemons/attrd/attrd_sync.c index 23915a619d1..86d9268cc5c 100644 --- a/daemons/attrd/attrd_sync.c +++ b/daemons/attrd/attrd_sync.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 the Pacemaker project contributors + * Copyright 2022-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -379,7 +379,7 @@ confirmation_timeout_cb(gpointer data) crm_trace("Timed out waiting for confirmations for client %s", client->id); pcmk__ipc_send_ack(client, action->ipc_id, action->flags|crm_ipc_client_response, - PCMK__XE_ACK, ATTRD_PROTOCOL_VERSION, + PCMK__XE_NACK, ATTRD_PROTOCOL_VERSION, CRM_EX_TIMEOUT); g_hash_table_iter_remove(&iter); diff --git a/daemons/based/based_callbacks.c b/daemons/based/based_callbacks.c index 1d34055d9d3..4efc2ae1ba6 100644 --- a/daemons/based/based_callbacks.c +++ b/daemons/based/based_callbacks.c @@ -292,7 +292,14 @@ cib_common_callback_worker(uint32_t id, uint32_t flags, xmlNode * op_request, } } - pcmk__ipc_send_ack(cib_client, id, flags, PCMK__XE_ACK, NULL, status); + if (status == CRM_EX_OK) { + pcmk__ipc_send_ack(cib_client, id, flags, PCMK__XE_ACK, NULL, + status); + } else { + pcmk__ipc_send_ack(cib_client, id, flags, PCMK__XE_NACK, NULL, + status); + } + return; } diff --git a/daemons/controld/controld_control.c b/daemons/controld/controld_control.c index 220f8305669..414a62755fc 100644 --- a/daemons/controld/controld_control.c +++ b/daemons/controld/controld_control.c @@ -413,7 +413,7 @@ dispatch_controller_ipc(qb_ipcs_connection_t * c, void *data, size_t size) } if (msg == NULL) { - pcmk__ipc_send_ack(client, id, flags, PCMK__XE_ACK, NULL, + pcmk__ipc_send_ack(client, id, flags, PCMK__XE_NACK, NULL, CRM_EX_PROTOCOL); return 0; } diff --git a/daemons/execd/Makefile.am b/daemons/execd/Makefile.am index e177dbb1a8b..bcf96edec07 100644 --- a/daemons/execd/Makefile.am +++ b/daemons/execd/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2012-2024 the Pacemaker project contributors +# Copyright 2012-2025 the Pacemaker project contributors # # The version control history for this file may have further details. # @@ -25,7 +25,8 @@ pacemaker_execd_LDADD += $(top_builddir)/lib/services/libcrmservice.la pacemaker_execd_LDADD += $(top_builddir)/lib/common/libcrmcommon.la pacemaker_execd_SOURCES = pacemaker-execd.c \ execd_commands.c \ - execd_alerts.c + execd_alerts.c \ + execd_messages.c sbin_PROGRAMS = pacemaker-remoted if BUILD_SYSTEMD diff --git a/daemons/execd/execd_alerts.c b/daemons/execd/execd_alerts.c index bdf75f0477a..64b67c2712a 100644 --- a/daemons/execd/execd_alerts.c +++ b/daemons/execd/execd_alerts.c @@ -102,7 +102,7 @@ alert_complete(svc_action_t *action) } int -process_lrmd_alert_exec(pcmk__client_t *client, uint32_t id, xmlNode *request) +execd_process_alert_exec(pcmk__client_t *client, xmlNode *request) { static int alert_sequence_no = 0; @@ -114,17 +114,17 @@ process_lrmd_alert_exec(pcmk__client_t *client, uint32_t id, xmlNode *request) PCMK__XA_LRMD_ALERT_PATH); svc_action_t *action = NULL; int alert_timeout = 0; - int rc = pcmk_ok; + int rc = pcmk_rc_ok; GHashTable *params = NULL; struct alert_cb_s *cb_data = NULL; if ((alert_id == NULL) || (alert_path == NULL) || (client == NULL) || (client->id == NULL)) { /* hint static analyzer */ - rc = -EINVAL; + rc = EINVAL; goto err; } if (draining_alerts) { - return pcmk_ok; + return pcmk_rc_ok; } crm_element_value_int(alert_xml, PCMK__XA_LRMD_TIMEOUT, &alert_timeout); @@ -144,12 +144,13 @@ process_lrmd_alert_exec(pcmk__client_t *client, uint32_t id, xmlNode *request) action = services_alert_create(alert_id, alert_path, alert_timeout, params, alert_sequence_no, cb_data); if (action->rc != PCMK_OCF_UNKNOWN) { - rc = -E2BIG; + rc = E2BIG; goto err; } rc = services_action_user(action, CRM_DAEMON_USER); if (rc < 0) { + rc = pcmk_legacy2rc(rc); goto err; } @@ -157,7 +158,7 @@ process_lrmd_alert_exec(pcmk__client_t *client, uint32_t id, xmlNode *request) if (services_alert_async(action, alert_complete) == FALSE) { services_action_free(action); } - return pcmk_ok; + return pcmk_rc_ok; err: if (cb_data) { diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c index a59dee23560..eafd5f2d5d3 100644 --- a/daemons/execd/execd_commands.c +++ b/daemons/execd/execd_commands.c @@ -547,8 +547,8 @@ schedule_lrmd_cmd(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd) } } -static xmlNode * -create_lrmd_reply(const char *origin, int rc, int call_id) +xmlNode * +execd_create_reply_as(const char *origin, int rc, int call_id) { xmlNode *reply = pcmk__xe_create(NULL, PCMK__XE_LRMD_REPLY); @@ -696,8 +696,8 @@ send_cmd_complete_notify(lrmd_cmd_t * cmd) pcmk__xml_free(notify); } -static void -send_generic_notify(int rc, xmlNode * request) +void +execd_send_generic_notify(int rc, xmlNode *request) { if (pcmk__ipc_client_count() != 0) { int call_id = 0; @@ -1512,11 +1512,11 @@ free_rsc(gpointer data) free(rsc); } -static int -process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id, - xmlNode **reply) +int +execd_process_signon(pcmk__client_t *client, xmlNode *request, int call_id, + xmlNode **reply) { - int rc = pcmk_ok; + int rc = pcmk_rc_ok; time_t now = time(NULL); const char *protocol_version = crm_element_value(request, PCMK__XA_LRMD_PROTOCOL_VERSION); @@ -1525,7 +1525,7 @@ process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id, if (compare_version(protocol_version, LRMD_COMPATIBLE_PROTOCOL) < 0) { crm_err("Cluster API version must be greater than or equal to %s, not %s", LRMD_COMPATIBLE_PROTOCOL, protocol_version); - rc = -EPROTO; + rc = EPROTO; } if (pcmk__xe_attr_is_true(request, PCMK__XA_LRMD_IS_IPC_PROVIDER)) { @@ -1555,14 +1555,16 @@ process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id, remoted_request_cib_schema_files(); } } else { - rc = -EACCES; + rc = EACCES; } #else - rc = -EPROTONOSUPPORT; + rc = EPROTONOSUPPORT; #endif } - *reply = create_lrmd_reply(__func__, rc, call_id); + pcmk__assert(reply != NULL); + + *reply = execd_create_reply(pcmk_rc2legacy(rc), call_id); crm_xml_add(*reply, PCMK__XA_LRMD_OP, CRM_OP_REGISTER); crm_xml_add(*reply, PCMK__XA_LRMD_CLIENTID, client->id); crm_xml_add(*reply, PCMK__XA_LRMD_PROTOCOL_VERSION, LRMD_PROTOCOL_VERSION); @@ -1575,63 +1577,63 @@ process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id, return rc; } -static int -process_lrmd_rsc_register(pcmk__client_t *client, uint32_t id, xmlNode *request) +void +execd_process_rsc_register(pcmk__client_t *client, uint32_t id, xmlNode *request) { - int rc = pcmk_ok; lrmd_rsc_t *rsc = build_rsc_from_xml(request); lrmd_rsc_t *dup = g_hash_table_lookup(rsc_list, rsc->rsc_id); if (dup && pcmk__str_eq(rsc->class, dup->class, pcmk__str_casei) && - pcmk__str_eq(rsc->provider, dup->provider, pcmk__str_casei) && pcmk__str_eq(rsc->type, dup->type, pcmk__str_casei)) { + pcmk__str_eq(rsc->provider, dup->provider, pcmk__str_casei) && + pcmk__str_eq(rsc->type, dup->type, pcmk__str_casei)) { crm_notice("Ignoring duplicate registration of '%s'", rsc->rsc_id); free_rsc(rsc); - return rc; + return; } g_hash_table_replace(rsc_list, rsc->rsc_id, rsc); crm_info("Cached agent information for '%s'", rsc->rsc_id); - return rc; } -static xmlNode * -process_lrmd_get_rsc_info(xmlNode *request, int call_id) +int +execd_process_get_rsc_info(xmlNode *request, int call_id, xmlNode **reply) { - int rc = pcmk_ok; + int rc = pcmk_rc_ok; xmlNode *rsc_xml = pcmk__xpath_find_one(request->doc, "//" PCMK__XE_LRMD_RSC, LOG_ERR); const char *rsc_id = crm_element_value(rsc_xml, PCMK__XA_LRMD_RSC_ID); - xmlNode *reply = NULL; lrmd_rsc_t *rsc = NULL; if (rsc_id == NULL) { - rc = -ENODEV; + rc = ENODEV; } else { rsc = g_hash_table_lookup(rsc_list, rsc_id); if (rsc == NULL) { crm_info("Agent information for '%s' not in cache", rsc_id); - rc = -ENODEV; + rc = ENODEV; } } - reply = create_lrmd_reply(__func__, rc, call_id); + CRM_LOG_ASSERT(reply != NULL); + + *reply = execd_create_reply(pcmk_rc2legacy(rc), call_id); if (rsc) { - crm_xml_add(reply, PCMK__XA_LRMD_RSC_ID, rsc->rsc_id); - crm_xml_add(reply, PCMK__XA_LRMD_CLASS, rsc->class); - crm_xml_add(reply, PCMK__XA_LRMD_PROVIDER, rsc->provider); - crm_xml_add(reply, PCMK__XA_LRMD_TYPE, rsc->type); + crm_xml_add(*reply, PCMK__XA_LRMD_RSC_ID, rsc->rsc_id); + crm_xml_add(*reply, PCMK__XA_LRMD_CLASS, rsc->class); + crm_xml_add(*reply, PCMK__XA_LRMD_PROVIDER, rsc->provider); + crm_xml_add(*reply, PCMK__XA_LRMD_TYPE, rsc->type); } - return reply; + + return rc; } -static int -process_lrmd_rsc_unregister(pcmk__client_t *client, uint32_t id, - xmlNode *request) +int +execd_process_rsc_unregister(pcmk__client_t *client, xmlNode *request) { - int rc = pcmk_ok; + int rc = pcmk_rc_ok; lrmd_rsc_t *rsc = NULL; xmlNode *rsc_xml = pcmk__xpath_find_one(request->doc, "//" PCMK__XE_LRMD_RSC, @@ -1639,21 +1641,21 @@ process_lrmd_rsc_unregister(pcmk__client_t *client, uint32_t id, const char *rsc_id = crm_element_value(rsc_xml, PCMK__XA_LRMD_RSC_ID); if (!rsc_id) { - return -ENODEV; + return ENODEV; } rsc = g_hash_table_lookup(rsc_list, rsc_id); if (rsc == NULL) { crm_info("Ignoring unregistration of resource '%s', which is not registered", rsc_id); - return pcmk_ok; + return pcmk_rc_ok; } if (rsc->active) { /* let the caller know there are still active ops on this rsc to watch for */ crm_trace("Operation (%p) still in progress for unregistered resource %s", rsc->active, rsc_id); - rc = -EINPROGRESS; + rc = EINPROGRESS; } g_hash_table_remove(rsc_list, rsc_id); @@ -1661,8 +1663,8 @@ process_lrmd_rsc_unregister(pcmk__client_t *client, uint32_t id, return rc; } -static int -process_lrmd_rsc_exec(pcmk__client_t *client, uint32_t id, xmlNode *request) +int +execd_process_rsc_exec(pcmk__client_t *client, xmlNode *request) { lrmd_rsc_t *rsc = NULL; lrmd_cmd_t *cmd = NULL; @@ -1670,25 +1672,24 @@ process_lrmd_rsc_exec(pcmk__client_t *client, uint32_t id, xmlNode *request) "//" PCMK__XE_LRMD_RSC, LOG_ERR); const char *rsc_id = crm_element_value(rsc_xml, PCMK__XA_LRMD_RSC_ID); - int call_id; if (!rsc_id) { - return -EINVAL; + return EINVAL; } + if (!(rsc = g_hash_table_lookup(rsc_list, rsc_id))) { crm_info("Resource '%s' not found (%d active resources)", rsc_id, g_hash_table_size(rsc_list)); - return -ENODEV; + return ENODEV; } cmd = create_lrmd_cmd(request, client); - call_id = cmd->call_id; /* Don't reference cmd after handing it off to be scheduled. * The cmd could get merged and freed. */ schedule_lrmd_cmd(rsc, cmd); - return call_id; + return pcmk_rc_ok; } static int @@ -1709,7 +1710,7 @@ cancel_op(const char *rsc_id, const char *action, guint interval_ms) * never existed. */ if (!rsc) { - return -ENODEV; + return ENODEV; } for (gIter = rsc->pending_ops; gIter != NULL; gIter = gIter->next) { @@ -1718,7 +1719,7 @@ cancel_op(const char *rsc_id, const char *action, guint interval_ms) if (action_matches(cmd, action, interval_ms)) { cmd->result.execution_status = PCMK_EXEC_CANCELLED; cmd_finalize(cmd, rsc); - return pcmk_ok; + return pcmk_rc_ok; } } @@ -1733,7 +1734,7 @@ cancel_op(const char *rsc_id, const char *action, guint interval_ms) if (rsc->active != cmd) { cmd_finalize(cmd, rsc); } - return pcmk_ok; + return pcmk_rc_ok; } } } else if (services_action_cancel(rsc_id, @@ -1743,10 +1744,10 @@ cancel_op(const char *rsc_id, const char *action, guint interval_ms) * this action was cancelled, which will destroy the cmd and remove * it from the recurring_op list. Do not do that in this function * if the service library says it cancelled it. */ - return pcmk_ok; + return pcmk_rc_ok; } - return -EOPNOTSUPP; + return EOPNOTSUPP; } static void @@ -1788,8 +1789,8 @@ cancel_all_recurring(lrmd_rsc_t * rsc, const char *client_id) g_list_free(cmd_list); } -static int -process_lrmd_rsc_cancel(pcmk__client_t *client, uint32_t id, xmlNode *request) +int +execd_process_rsc_cancel(pcmk__client_t *client, xmlNode *request) { xmlNode *rsc_xml = pcmk__xpath_find_one(request->doc, "//" PCMK__XE_LRMD_RSC, @@ -1801,7 +1802,7 @@ process_lrmd_rsc_cancel(pcmk__client_t *client, uint32_t id, xmlNode *request) crm_element_value_ms(rsc_xml, PCMK__XA_LRMD_RSC_INTERVAL, &interval_ms); if (!rsc_id || !action) { - return -EINVAL; + return EINVAL; } return cancel_op(rsc_id, action, interval_ms); @@ -1824,13 +1825,12 @@ add_recurring_op_xml(xmlNode *reply, lrmd_rsc_t *rsc) } } -static xmlNode * -process_lrmd_get_recurring(xmlNode *request, int call_id) +int +execd_process_get_recurring(xmlNode *request, int call_id, xmlNode **reply) { - int rc = pcmk_ok; + int rc = pcmk_rc_ok; const char *rsc_id = NULL; lrmd_rsc_t *rsc = NULL; - xmlNode *reply = NULL; xmlNode *rsc_xml = NULL; // Resource ID is optional @@ -1848,11 +1848,13 @@ process_lrmd_get_recurring(xmlNode *request, int call_id) if (rsc == NULL) { crm_info("Resource '%s' not found (%d active resources)", rsc_id, g_hash_table_size(rsc_list)); - rc = -ENODEV; + rc = ENODEV; } } - reply = create_lrmd_reply(__func__, rc, call_id); + CRM_LOG_ASSERT(reply != NULL); + + *reply = execd_create_reply(pcmk_rc2legacy(rc), call_id); // If resource ID is not specified, check all resources if (rsc_id == NULL) { @@ -1862,149 +1864,11 @@ process_lrmd_get_recurring(xmlNode *request, int call_id) g_hash_table_iter_init(&iter, rsc_list); while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &rsc)) { - add_recurring_op_xml(reply, rsc); + add_recurring_op_xml(*reply, rsc); } } else if (rsc) { - add_recurring_op_xml(reply, rsc); - } - return reply; -} - -void -process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request) -{ - int rc = pcmk_ok; - int call_id = 0; - const char *op = crm_element_value(request, PCMK__XA_LRMD_OP); - int do_reply = 0; - int do_notify = 0; - xmlNode *reply = NULL; - - /* Certain IPC commands may be done only by privileged users (i.e. root or - * hacluster), because they would otherwise provide a means of bypassing - * ACLs. - */ - bool allowed = pcmk_is_set(client->flags, pcmk__client_privileged); - - crm_trace("Processing %s operation from %s", op, client->id); - crm_element_value_int(request, PCMK__XA_LRMD_CALLID, &call_id); - - if (pcmk__str_eq(op, CRM_OP_IPC_FWD, pcmk__str_none)) { -#ifdef PCMK__COMPILE_REMOTE - if (allowed) { - ipc_proxy_forward_client(client, request); - } else { - rc = -EACCES; - } -#else - rc = -EPROTONOSUPPORT; -#endif - do_reply = 1; - } else if (pcmk__str_eq(op, CRM_OP_REGISTER, pcmk__str_none)) { - rc = process_lrmd_signon(client, request, call_id, &reply); - do_reply = 1; - } else if (pcmk__str_eq(op, LRMD_OP_RSC_REG, pcmk__str_none)) { - if (allowed) { - rc = process_lrmd_rsc_register(client, id, request); - do_notify = 1; - } else { - rc = -EACCES; - } - do_reply = 1; - } else if (pcmk__str_eq(op, LRMD_OP_RSC_INFO, pcmk__str_none)) { - if (allowed) { - reply = process_lrmd_get_rsc_info(request, call_id); - } else { - rc = -EACCES; - } - do_reply = 1; - } else if (pcmk__str_eq(op, LRMD_OP_RSC_UNREG, pcmk__str_none)) { - if (allowed) { - rc = process_lrmd_rsc_unregister(client, id, request); - /* don't notify anyone about failed un-registers */ - if (rc == pcmk_ok || rc == -EINPROGRESS) { - do_notify = 1; - } - } else { - rc = -EACCES; - } - do_reply = 1; - } else if (pcmk__str_eq(op, LRMD_OP_RSC_EXEC, pcmk__str_none)) { - if (allowed) { - rc = process_lrmd_rsc_exec(client, id, request); - } else { - rc = -EACCES; - } - do_reply = 1; - } else if (pcmk__str_eq(op, LRMD_OP_RSC_CANCEL, pcmk__str_none)) { - if (allowed) { - rc = process_lrmd_rsc_cancel(client, id, request); - } else { - rc = -EACCES; - } - do_reply = 1; - } else if (pcmk__str_eq(op, LRMD_OP_POKE, pcmk__str_none)) { - do_notify = 1; - do_reply = 1; - } else if (pcmk__str_eq(op, LRMD_OP_CHECK, pcmk__str_none)) { - if (allowed) { - xmlNode *wrapper = pcmk__xe_first_child(request, - PCMK__XE_LRMD_CALLDATA, - NULL, NULL); - xmlNode *data = pcmk__xe_first_child(wrapper, NULL, NULL, NULL); - - const char *timeout = NULL; - - CRM_LOG_ASSERT(data != NULL); - timeout = crm_element_value(data, PCMK__XA_LRMD_WATCHDOG); - pcmk__valid_stonith_watchdog_timeout(timeout); - } else { - rc = -EACCES; - } - } else if (pcmk__str_eq(op, LRMD_OP_ALERT_EXEC, pcmk__str_none)) { - if (allowed) { - rc = process_lrmd_alert_exec(client, id, request); - } else { - rc = -EACCES; - } - do_reply = 1; - } else if (pcmk__str_eq(op, LRMD_OP_GET_RECURRING, pcmk__str_none)) { - if (allowed) { - reply = process_lrmd_get_recurring(request, call_id); - } else { - rc = -EACCES; - } - do_reply = 1; - } else { - rc = -EOPNOTSUPP; - do_reply = 1; - crm_err("Unknown IPC request '%s' from client %s", - op, pcmk__client_name(client)); - } - - if (rc == -EACCES) { - crm_warn("Rejecting IPC request '%s' from unprivileged client %s", - op, pcmk__client_name(client)); + add_recurring_op_xml(*reply, rsc); } - crm_debug("Processed %s operation from %s: rc=%d, reply=%d, notify=%d", - op, client->id, rc, do_reply, do_notify); - - if (do_reply) { - int send_rc = pcmk_rc_ok; - - if (reply == NULL) { - reply = create_lrmd_reply(__func__, rc, call_id); - } - send_rc = lrmd_server_send_reply(client, id, reply); - pcmk__xml_free(reply); - if (send_rc != pcmk_rc_ok) { - crm_warn("Reply to client %s failed: %s " QB_XS " rc=%d", - pcmk__client_name(client), pcmk_rc_str(send_rc), send_rc); - } - } - - if (do_notify) { - send_generic_notify(rc, request); - } + return rc; } diff --git a/daemons/execd/execd_messages.c b/daemons/execd/execd_messages.c new file mode 100644 index 00000000000..558123bbc47 --- /dev/null +++ b/daemons/execd/execd_messages.c @@ -0,0 +1,638 @@ +/* + * Copyright 2012-2025 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU Lesser General Public License + * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. + */ + +#include + +#include // ENOMEM +#include // bool +#include // NULL, size_t +#include // int32_t, uint32_t +#include // free +#include // gid_t, uid_t + +#include // g_byte_array_free, FALSE +#include // xmlNode +#include // qb_ipcs_connection_t, qb_ipcs_service_handlers +#include // QB_XS + +#include // CRM_SYSTEM_LRMD +#include // pcmk__process_request, pcmk__xml_free +#include // crm_ipc_flags +#include // pcmk__client_s, pcmk__find_client +#include // pcmk_rc_e, pcmk_rc_str +#include // crm_strdup_printf +#include // pcmk_is_set +#include // crm_xml_add, crm_element_value +#include // PCMK__XA_LRMD_*, pcmk__xe_is + +#include "pacemaker-execd.h" // client_disconnect_cleanup + +static GHashTable *execd_handlers = NULL; +static int lrmd_call_id = 0; + +static xmlNode * +handle_ipc_fwd_request(pcmk__request_t *request) +{ + int call_id = 0; + int rc = pcmk_rc_ok; + xmlNode *reply = NULL; + +#ifdef PCMK__COMPILE_REMOTE + bool allowed = pcmk_is_set(request->ipc_client->flags, + pcmk__client_privileged); + + if (!allowed) { + pcmk__set_result(&request->result, CRM_EX_INSUFFICIENT_PRIV, + PCMK_EXEC_ERROR, NULL); + crm_warn("Rejecting IPC request '%s' from unprivileged client %s", + request->op, pcmk__client_name(request->ipc_client)); + return NULL; + } + + ipc_proxy_forward_client(request->ipc_client, request->xml); +#else + rc = EPROTONOSUPPORT; +#endif + + crm_element_value_int(request->xml, PCMK__XA_LRMD_CALLID, &call_id); + + /* Create a generic reply since forwarding doesn't create a more specific one */ + reply = execd_create_reply(pcmk_rc2legacy(rc), call_id); + return reply; +} + +static xmlNode * +handle_register_request(pcmk__request_t *request) +{ + int call_id = 0; + int rc = pcmk_rc_ok; + xmlNode *reply = NULL; + + crm_element_value_int(request->xml, PCMK__XA_LRMD_CALLID, &call_id); + rc = execd_process_signon(request->ipc_client, request->xml, call_id, &reply); + + if (rc != pcmk_rc_ok) { + pcmk__set_result(&request->result, pcmk_rc2exitc(rc), PCMK_EXEC_ERROR, + pcmk_rc_str(rc)); + return NULL; + } + + pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); + return reply; +} + +static xmlNode * +handle_alert_exec_request(pcmk__request_t *request) +{ + int call_id = 0; + int rc = pcmk_rc_ok; + bool allowed = pcmk_is_set(request->ipc_client->flags, + pcmk__client_privileged); + xmlNode *reply = NULL; + + if (!allowed) { + pcmk__set_result(&request->result, CRM_EX_INSUFFICIENT_PRIV, + PCMK_EXEC_ERROR, NULL); + crm_warn("Rejecting IPC request '%s' from unprivileged client %s", + request->op, pcmk__client_name(request->ipc_client)); + return NULL; + } + + crm_element_value_int(request->xml, PCMK__XA_LRMD_CALLID, &call_id); + + rc = execd_process_alert_exec(request->ipc_client, request->xml); + + if (rc == pcmk_rc_ok) { + pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); + } else { + pcmk__set_result(&request->result, pcmk_rc2exitc(rc), PCMK_EXEC_ERROR, + pcmk_rc_str(rc)); + } + + /* Create a generic reply since executing an alert doesn't create a + * more specific one. + */ + reply = execd_create_reply(pcmk_rc2legacy(rc), call_id); + return reply; +} + +static xmlNode * +handle_check_request(pcmk__request_t *request) +{ + bool allowed = pcmk_is_set(request->ipc_client->flags, + pcmk__client_privileged); + xmlNode *wrapper = NULL; + xmlNode *data = NULL; + const char *timeout = NULL; + + if (!allowed) { + pcmk__set_result(&request->result, CRM_EX_INSUFFICIENT_PRIV, + PCMK_EXEC_ERROR, NULL); + crm_warn("Rejecting IPC request '%s' from unprivileged client %s", + request->op, pcmk__client_name(request->ipc_client)); + return NULL; + } + + wrapper = pcmk__xe_first_child(request->xml, + PCMK__XE_LRMD_CALLDATA, + NULL, NULL); + data = pcmk__xe_first_child(wrapper, NULL, NULL, NULL); + + if (data == NULL) { + pcmk__set_result(&request->result, CRM_EX_SOFTWARE, PCMK_EXEC_INVALID, + NULL); + return NULL; + } + + timeout = crm_element_value(data, PCMK__XA_LRMD_WATCHDOG); + /* FIXME: This just exits on certain conditions, which seems like a pretty + * extreme reaction for a daemon to take. + */ + pcmk__valid_stonith_watchdog_timeout(timeout); + + pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); + return NULL; +} + +static xmlNode * +handle_get_recurring_request(pcmk__request_t *request) +{ + int call_id = 0; + int rc = pcmk_rc_ok; + bool allowed = pcmk_is_set(request->ipc_client->flags, + pcmk__client_privileged); + xmlNode *reply = NULL; + + if (!allowed) { + pcmk__set_result(&request->result, CRM_EX_INSUFFICIENT_PRIV, + PCMK_EXEC_ERROR, NULL); + crm_warn("Rejecting IPC request '%s' from unprivileged client %s", + request->op, pcmk__client_name(request->ipc_client)); + return NULL; + } + + crm_element_value_int(request->xml, PCMK__XA_LRMD_CALLID, &call_id); + + rc = execd_process_get_recurring(request->xml, call_id, &reply); + + if (rc == pcmk_rc_ok) { + pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); + } else { + pcmk__set_result(&request->result, pcmk_rc2exitc(rc), PCMK_EXEC_ERROR, + pcmk_rc_str(rc)); + } + + return reply; +} + +static xmlNode * +handle_poke_request(pcmk__request_t *request) +{ + int call_id = 0; + xmlNode *reply = NULL; + + crm_element_value_int(request->xml, PCMK__XA_LRMD_CALLID, &call_id); + + /* Create a generic reply since this doesn't create a more specific one */ + reply = execd_create_reply(pcmk_ok, call_id); + return reply; +} + +static xmlNode * +handle_rsc_cancel_request(pcmk__request_t *request) +{ + int call_id = 0; + int rc = pcmk_rc_ok; + bool allowed = pcmk_is_set(request->ipc_client->flags, + pcmk__client_privileged); + xmlNode *reply = NULL; + + if (!allowed) { + pcmk__set_result(&request->result, CRM_EX_INSUFFICIENT_PRIV, + PCMK_EXEC_ERROR, NULL); + crm_warn("Rejecting IPC request '%s' from unprivileged client %s", + request->op, pcmk__client_name(request->ipc_client)); + return NULL; + } + + crm_element_value_int(request->xml, PCMK__XA_LRMD_CALLID, &call_id); + + rc = execd_process_rsc_cancel(request->ipc_client, request->xml); + + if (rc == pcmk_rc_ok) { + pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); + } else { + pcmk__set_result(&request->result, pcmk_rc2exitc(rc), PCMK_EXEC_ERROR, + pcmk_rc_str(rc)); + } + + /* Create a generic reply since canceling a resource doesn't create a + * more specific one. + */ + reply = execd_create_reply(pcmk_rc2legacy(rc), call_id); + return reply; +} + +static xmlNode * +handle_rsc_exec_request(pcmk__request_t *request) +{ + int call_id = 0; + int rc = pcmk_rc_ok; + bool allowed = pcmk_is_set(request->ipc_client->flags, + pcmk__client_privileged); + xmlNode *reply = NULL; + + if (!allowed) { + pcmk__set_result(&request->result, CRM_EX_INSUFFICIENT_PRIV, + PCMK_EXEC_ERROR, NULL); + crm_warn("Rejecting IPC request '%s' from unprivileged client %s", + request->op, pcmk__client_name(request->ipc_client)); + return NULL; + } + + crm_element_value_int(request->xml, PCMK__XA_LRMD_CALLID, &call_id); + + rc = execd_process_rsc_exec(request->ipc_client, request->xml); + + if (rc == pcmk_rc_ok) { + pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); + + /* This looks redundant, but it's unfortunately necessary. The first + * argument is set as the PCMK__XA_LRMD_RC attribute in the response. + * On the other side of the connection, lrmd_send_command will read + * this and use it as its return value, which passes back up to the + * public API function lrmd_api_exec. + */ + reply = execd_create_reply(call_id, call_id); + } else { + pcmk__set_result(&request->result, pcmk_rc2exitc(rc), PCMK_EXEC_ERROR, + pcmk_rc_str(rc)); + reply = execd_create_reply(pcmk_rc2legacy(rc), call_id); + } + + return reply; +} + +static xmlNode * +handle_rsc_info_request(pcmk__request_t *request) +{ + int call_id = 0; + int rc = pcmk_rc_ok; + bool allowed = pcmk_is_set(request->ipc_client->flags, + pcmk__client_privileged); + xmlNode *reply = NULL; + + if (!allowed) { + pcmk__set_result(&request->result, CRM_EX_INSUFFICIENT_PRIV, + PCMK_EXEC_ERROR, NULL); + crm_warn("Rejecting IPC request '%s' from unprivileged client %s", + request->op, pcmk__client_name(request->ipc_client)); + return NULL; + } + + crm_element_value_int(request->xml, PCMK__XA_LRMD_CALLID, &call_id); + + /* This returns ENODEV if the resource isn't in the cache which will be + * logged as an error. However, this isn't fatal to the client - it may + * querying to see if the resource exists before deciding to register it. + */ + rc = execd_process_get_rsc_info(request->xml, call_id, &reply); + + if (rc == pcmk_rc_ok) { + pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); + } else { + pcmk__set_result(&request->result, pcmk_rc2exitc(rc), PCMK_EXEC_ERROR, + pcmk_rc_str(rc)); + } + + return reply; +} + +static xmlNode * +handle_rsc_reg_request(pcmk__request_t *request) +{ + int call_id = 0; + bool allowed = pcmk_is_set(request->ipc_client->flags, + pcmk__client_privileged); + xmlNode *reply = NULL; + + if (!allowed) { + pcmk__set_result(&request->result, CRM_EX_INSUFFICIENT_PRIV, + PCMK_EXEC_ERROR, NULL); + crm_warn("Rejecting IPC request '%s' from unprivileged client %s", + request->op, pcmk__client_name(request->ipc_client)); + return NULL; + } + + crm_element_value_int(request->xml, PCMK__XA_LRMD_CALLID, &call_id); + + execd_process_rsc_register(request->ipc_client, request->ipc_id, request->xml); + + /* Create a generic reply since registering a resource doesn't create + * a more specific one. + */ + reply = execd_create_reply(pcmk_ok, call_id); + pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); + return reply; +} + +static xmlNode * +handle_rsc_unreg_request(pcmk__request_t *request) +{ + int call_id = 0; + int rc = pcmk_rc_ok; + bool allowed = pcmk_is_set(request->ipc_client->flags, + pcmk__client_privileged); + xmlNode *reply = NULL; + + if (!allowed) { + pcmk__set_result(&request->result, CRM_EX_INSUFFICIENT_PRIV, + PCMK_EXEC_ERROR, NULL); + crm_warn("Rejecting IPC request '%s' from unprivileged client %s", + request->op, pcmk__client_name(request->ipc_client)); + return NULL; + } + + crm_element_value_int(request->xml, PCMK__XA_LRMD_CALLID, &call_id); + + rc = execd_process_rsc_unregister(request->ipc_client, request->xml); + + /* Create a generic reply since unregistering a resource doesn't create + * a more specific one. + */ + reply = execd_create_reply(pcmk_rc2legacy(rc), call_id); + pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL); + return reply; +} + +static bool +requires_notify(const char *command, int rc) +{ + if (pcmk__str_eq(command, LRMD_OP_RSC_UNREG, pcmk__str_none)) { + /* Don't notify about failed unregisters */ + return (rc == pcmk_ok) || (rc == -EINPROGRESS); + } else { + return pcmk__str_any_of(command, LRMD_OP_POKE, LRMD_OP_RSC_REG, NULL); + } +} + + +static xmlNode * +handle_unknown_request(pcmk__request_t *request) +{ + pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags, + PCMK__XE_NACK, NULL, CRM_EX_PROTOCOL); + + pcmk__format_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID, + "Unknown IPC request type '%s' (bug?)", + pcmk__s(request->op, "")); + return NULL; +} + +static void +execd_register_handlers(void) +{ + pcmk__server_command_t handlers[] = { + { CRM_OP_IPC_FWD, handle_ipc_fwd_request }, + { CRM_OP_REGISTER, handle_register_request }, + { LRMD_OP_ALERT_EXEC, handle_alert_exec_request }, + { LRMD_OP_CHECK, handle_check_request }, + { LRMD_OP_GET_RECURRING, handle_get_recurring_request }, + { LRMD_OP_POKE, handle_poke_request }, + { LRMD_OP_RSC_CANCEL, handle_rsc_cancel_request }, + { LRMD_OP_RSC_EXEC, handle_rsc_exec_request }, + { LRMD_OP_RSC_INFO, handle_rsc_info_request }, + { LRMD_OP_RSC_REG, handle_rsc_reg_request }, + { LRMD_OP_RSC_UNREG, handle_rsc_unreg_request }, + { NULL, handle_unknown_request }, + }; + + execd_handlers = pcmk__register_handlers(handlers); +} + +void +execd_unregister_handlers(void) +{ + if (execd_handlers != NULL) { + g_hash_table_destroy(execd_handlers); + execd_handlers = NULL; + } +} + +static int32_t +lrmd_ipc_accept(qb_ipcs_connection_t *qbc, uid_t uid, gid_t gid) +{ + crm_trace("Connection %p", qbc); + if (pcmk__new_client(qbc, uid, gid) == NULL) { + return -ENOMEM; + } + return 0; +} + +static void +lrmd_ipc_created(qb_ipcs_connection_t *qbc) +{ + pcmk__client_t *new_client = pcmk__find_client(qbc); + + crm_trace("Connection %p", qbc); + pcmk__assert(new_client != NULL); + /* Now that the connection is offically established, alert + * the other clients a new connection exists. */ + + notify_of_new_client(new_client); +} + +static int32_t +lrmd_ipc_dispatch(qb_ipcs_connection_t *qbc, void *data, size_t size) +{ + int rc = pcmk_rc_ok; + uint32_t id = 0; + uint32_t flags = 0; + pcmk__client_t *client = pcmk__find_client(qbc); + xmlNode *msg = NULL; + + CRM_CHECK(client != NULL, crm_err("Invalid client"); + return FALSE); + CRM_CHECK(client->id != NULL, crm_err("Invalid client: %p", client); + return FALSE); + + rc = pcmk__ipc_msg_append(&client->buffer, data); + + if (rc == pcmk_rc_ipc_more) { + /* We haven't read the complete message yet, so just return. */ + return 0; + + } else if (rc == pcmk_rc_ok) { + /* We've read the complete message and there's already a header on + * the front. Pass it off for processing. + */ + msg = pcmk__client_data2xml(client, &id, &flags); + g_byte_array_free(client->buffer, TRUE); + client->buffer = NULL; + + } else { + /* Some sort of error occurred reassembling the message. All we can + * do is clean up, log an error and return. + */ + crm_err("Error when reading IPC message: %s", pcmk_rc_str(rc)); + + if (client->buffer != NULL) { + g_byte_array_free(client->buffer, TRUE); + client->buffer = NULL; + } + + return 0; + } + + CRM_CHECK(flags & crm_ipc_client_response, crm_err("Invalid client request: %p", client); + return FALSE); + + if (!msg) { + return 0; + } + + execd_process_message(client, id, flags, msg); + pcmk__xml_free(msg); + return 0; +} + +static int32_t +lrmd_ipc_closed(qb_ipcs_connection_t *qbc) +{ + pcmk__client_t *client = pcmk__find_client(qbc); + + if (client == NULL) { + return 0; + } + + crm_trace("Connection %p", qbc); + client_disconnect_cleanup(client->id); +#ifdef PCMK__COMPILE_REMOTE + ipc_proxy_remove_provider(client); +#endif + lrmd_client_destroy(client); + return 0; +} + +static void +lrmd_ipc_destroy(qb_ipcs_connection_t *qbc) +{ + lrmd_ipc_closed(qbc); + crm_trace("Connection %p", qbc); +} + +struct qb_ipcs_service_handlers lrmd_ipc_callbacks = { + .connection_accept = lrmd_ipc_accept, + .connection_created = lrmd_ipc_created, + .msg_process = lrmd_ipc_dispatch, + .connection_closed = lrmd_ipc_closed, + .connection_destroyed = lrmd_ipc_destroy +}; + +static bool +invalid_msg(xmlNode *msg) +{ + const char *to = crm_element_value(msg, PCMK__XA_T); + + /* IPC proxy messages do not get a t="" attribute set on them. */ + bool invalid = !pcmk__str_eq(to, CRM_SYSTEM_LRMD, pcmk__str_none) && + !pcmk__xe_is(msg, PCMK__XE_LRMD_IPC_PROXY); + + if (invalid) { + crm_info("Ignoring invalid IPC message: to '%s' not " CRM_SYSTEM_LRMD, + pcmk__s(to, "")); + crm_log_xml_info(msg, "[Invalid]"); + } + + return invalid; +} + +void +execd_process_message(pcmk__client_t *c, uint32_t id, uint32_t flags, xmlNode *msg) +{ + int rc = pcmk_rc_ok; + + if (execd_handlers == NULL) { + execd_register_handlers(); + } + + if (!c->name) { + c->name = crm_element_value_copy(msg, PCMK__XA_LRMD_CLIENTNAME); + } + + lrmd_call_id++; + if (lrmd_call_id < 1) { + lrmd_call_id = 1; + } + + crm_xml_add(msg, PCMK__XA_LRMD_CLIENTID, c->id); + crm_xml_add(msg, PCMK__XA_LRMD_CLIENTNAME, c->name); + crm_xml_add_int(msg, PCMK__XA_LRMD_CALLID, lrmd_call_id); + + if (invalid_msg(msg)) { + pcmk__ipc_send_ack(c, id, flags, PCMK__XE_NACK, NULL, CRM_EX_PROTOCOL); + } else { + char *log_msg = NULL; + const char *reason = NULL; + xmlNode *reply = NULL; + + pcmk__request_t request = { + .ipc_client = c, + .ipc_id = id, + .ipc_flags = flags, + .peer = NULL, + .xml = msg, + .call_options = 0, + .result = PCMK__UNKNOWN_RESULT, + }; + + request.op = crm_element_value_copy(request.xml, PCMK__XA_LRMD_OP); + CRM_CHECK(request.op != NULL, return); + + crm_trace("Processing %s operation from %s", request.op, c->id); + + reply = pcmk__process_request(&request, execd_handlers); + + if (reply != NULL) { + int reply_rc = pcmk_ok; + + rc = lrmd_server_send_reply(c, id, reply); + if (rc != pcmk_rc_ok) { + crm_warn("Reply to client %s failed: %s " QB_XS " rc=%d", + pcmk__client_name(c), pcmk_rc_str(rc), rc); + } + + crm_element_value_int(reply, PCMK__XA_LRMD_RC, &reply_rc); + if (requires_notify(request.op, reply_rc)) { + execd_send_generic_notify(reply_rc, request.xml); + } + + pcmk__xml_free(reply); + } + + reason = request.result.exit_reason; + + log_msg = crm_strdup_printf("Processed %s request from %s %s: %s%s%s%s", + request.op, pcmk__request_origin_type(&request), + pcmk__request_origin(&request), + pcmk_exec_status_str(request.result.execution_status), + (reason == NULL)? "" : " (", + (reason == NULL)? "" : reason, + (reason == NULL)? "" : ")"); + + if (!pcmk__result_ok(&request.result)) { + crm_warn("%s", log_msg); + } else { + crm_debug("%s", log_msg); + } + + free(log_msg); + pcmk__reset_request(&request); + } +} diff --git a/daemons/execd/pacemaker-execd.c b/daemons/execd/pacemaker-execd.c index 3229487e4e8..d5868bf66b7 100644 --- a/daemons/execd/pacemaker-execd.c +++ b/daemons/execd/pacemaker-execd.c @@ -40,7 +40,6 @@ static GMainLoop *mainloop = NULL; static qb_ipcs_service_t *ipcs = NULL; static stonith_t *stonith_api = NULL; -int lrmd_call_id = 0; time_t start_time; static struct { @@ -97,108 +96,6 @@ get_stonith_connection(void) return stonith_api; } -static int32_t -lrmd_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid) -{ - crm_trace("Connection %p", c); - if (pcmk__new_client(c, uid, gid) == NULL) { - return -ENOMEM; - } - return 0; -} - -static void -lrmd_ipc_created(qb_ipcs_connection_t * c) -{ - pcmk__client_t *new_client = pcmk__find_client(c); - - crm_trace("Connection %p", c); - pcmk__assert(new_client != NULL); - /* Now that the connection is offically established, alert - * the other clients a new connection exists. */ - - notify_of_new_client(new_client); -} - -static int32_t -lrmd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size) -{ - int rc = pcmk_rc_ok; - uint32_t id = 0; - uint32_t flags = 0; - pcmk__client_t *client = pcmk__find_client(c); - xmlNode *request = NULL; - - CRM_CHECK(client != NULL, crm_err("Invalid client"); - return FALSE); - CRM_CHECK(client->id != NULL, crm_err("Invalid client: %p", client); - return FALSE); - - rc = pcmk__ipc_msg_append(&client->buffer, data); - - if (rc == pcmk_rc_ipc_more) { - /* We haven't read the complete message yet, so just return. */ - return 0; - - } else if (rc == pcmk_rc_ok) { - /* We've read the complete message and there's already a header on - * the front. Pass it off for processing. - */ - request = pcmk__client_data2xml(client, &id, &flags); - g_byte_array_free(client->buffer, TRUE); - client->buffer = NULL; - - } else { - /* Some sort of error occurred reassembling the message. All we can - * do is clean up, log an error and return. - */ - crm_err("Error when reading IPC message: %s", pcmk_rc_str(rc)); - - if (client->buffer != NULL) { - g_byte_array_free(client->buffer, TRUE); - client->buffer = NULL; - } - - return 0; - } - - CRM_CHECK(flags & crm_ipc_client_response, crm_err("Invalid client request: %p", client); - return FALSE); - - if (!request) { - return 0; - } - - /* @TODO functionize some of this to reduce duplication with - * lrmd_remote_client_msg() - */ - - if (!client->name) { - const char *value = crm_element_value(request, - PCMK__XA_LRMD_CLIENTNAME); - - if (value == NULL) { - client->name = pcmk__itoa(pcmk__client_pid(c)); - } else { - client->name = pcmk__str_copy(value); - } - } - - lrmd_call_id++; - if (lrmd_call_id < 1) { - lrmd_call_id = 1; - } - - crm_xml_add(request, PCMK__XA_LRMD_CLIENTID, client->id); - crm_xml_add(request, PCMK__XA_LRMD_CLIENTNAME, client->name); - crm_xml_add_int(request, PCMK__XA_LRMD_CALLID, lrmd_call_id); - - process_lrmd_message(client, id, request); - - pcmk__xml_free(request); - return 0; -} - /*! * \internal * \brief Free a client connection, and exit if appropriate @@ -220,39 +117,6 @@ lrmd_client_destroy(pcmk__client_t *client) #endif } -static int32_t -lrmd_ipc_closed(qb_ipcs_connection_t * c) -{ - pcmk__client_t *client = pcmk__find_client(c); - - if (client == NULL) { - return 0; - } - - crm_trace("Connection %p", c); - client_disconnect_cleanup(client->id); -#ifdef PCMK__COMPILE_REMOTE - ipc_proxy_remove_provider(client); -#endif - lrmd_client_destroy(client); - return 0; -} - -static void -lrmd_ipc_destroy(qb_ipcs_connection_t * c) -{ - lrmd_ipc_closed(c); - crm_trace("Connection %p", c); -} - -static struct qb_ipcs_service_handlers lrmd_ipc_callbacks = { - .connection_accept = lrmd_ipc_accept, - .connection_created = lrmd_ipc_created, - .msg_process = lrmd_ipc_dispatch, - .connection_closed = lrmd_ipc_closed, - .connection_destroyed = lrmd_ipc_destroy -}; - // \return Standard Pacemaker return code int lrmd_server_send_reply(pcmk__client_t *client, uint32_t id, xmlNode *reply) @@ -324,6 +188,7 @@ exit_executor(void) #endif pcmk__client_cleanup(); + execd_unregister_handlers(); if (mainloop) { lrmd_drain_alerts(mainloop); diff --git a/daemons/execd/pacemaker-execd.h b/daemons/execd/pacemaker-execd.h index a66f5ef8889..d9d02d8807b 100644 --- a/daemons/execd/pacemaker-execd.h +++ b/daemons/execd/pacemaker-execd.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the Pacemaker project contributors + * Copyright 2012-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -20,6 +20,8 @@ extern GHashTable *rsc_list; extern time_t start_time; +extern struct qb_ipcs_service_handlers lrmd_ipc_callbacks; + typedef struct lrmd_rsc_s { char *rsc_id; char *class; @@ -62,9 +64,6 @@ int lrmd_server_send_notify(pcmk__client_t *client, xmlNode *msg); void notify_of_new_client(pcmk__client_t *new_client); -void process_lrmd_message(pcmk__client_t *client, uint32_t id, - xmlNode *request); - void free_rsc(gpointer data); void handle_shutdown_ack(void); @@ -100,8 +99,27 @@ void remoted_spawn_pidone(int argc, char **argv); void remoted_request_cib_schema_files(void); #endif -int process_lrmd_alert_exec(pcmk__client_t *client, uint32_t id, - xmlNode *request); +void execd_unregister_handlers(void); + void lrmd_drain_alerts(GMainLoop *mloop); +void execd_process_message(pcmk__client_t *c, uint32_t id, uint32_t flags, + xmlNode *msg); + +xmlNode *execd_create_reply_as(const char *origin, int rc, int call_id); +void execd_send_generic_notify(int rc, xmlNode *request); + +#define execd_create_reply(rc, call_id) \ + execd_create_reply_as(__func__, (rc), (call_id)) + +int execd_process_alert_exec(pcmk__client_t *client, xmlNode *request); +int execd_process_get_recurring(xmlNode *request, int call_id, xmlNode **reply); +int execd_process_get_rsc_info(xmlNode *request, int call_id, xmlNode **reply); +int execd_process_rsc_cancel(pcmk__client_t *client, xmlNode *request); +int execd_process_rsc_exec(pcmk__client_t *client, xmlNode *request); +void execd_process_rsc_register(pcmk__client_t *client, uint32_t id, xmlNode *request); +int execd_process_rsc_unregister(pcmk__client_t *client, xmlNode *request); +int execd_process_signon(pcmk__client_t *client, xmlNode *request, int call_id, + xmlNode **reply); + #endif // PACEMAKER_EXECD__H diff --git a/daemons/execd/remoted_tls.c b/daemons/execd/remoted_tls.c index 13c867f3e63..6d28f94f505 100644 --- a/daemons/execd/remoted_tls.c +++ b/daemons/execd/remoted_tls.c @@ -33,7 +33,6 @@ static pcmk__tls_t *tls = NULL; static int ssock = -1; -extern int lrmd_call_id; /*! * \internal @@ -131,21 +130,8 @@ lrmd_remote_client_msg(gpointer data) crm_element_value_int(request, PCMK__XA_LRMD_REMOTE_MSG_ID, &id); crm_trace("Processing remote client request %d", id); - if (!client->name) { - client->name = crm_element_value_copy(request, - PCMK__XA_LRMD_CLIENTNAME); - } - - lrmd_call_id++; - if (lrmd_call_id < 1) { - lrmd_call_id = 1; - } - - crm_xml_add(request, PCMK__XA_LRMD_CLIENTID, client->id); - crm_xml_add(request, PCMK__XA_LRMD_CLIENTNAME, client->name); - crm_xml_add_int(request, PCMK__XA_LRMD_CALLID, lrmd_call_id); - process_lrmd_message(client, id, request); + execd_process_message(client, id, client->flags, request); pcmk__xml_free(request); return 0; diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 9934760ea5e..36e4c472d67 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -3485,7 +3485,8 @@ handle_unknown_request(pcmk__request_t *request) request->op, pcmk__request_origin_type(request), pcmk__request_origin(request)); pcmk__format_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID, - "Unknown IPC request type '%s' (bug?)", request->op); + "Unknown IPC request type '%s' (bug?)", + pcmk__s(request->op, "")); return fenced_construct_reply(request->xml, NULL, &request->result); } diff --git a/daemons/pacemakerd/pcmkd_messages.c b/daemons/pacemakerd/pcmkd_messages.c index 1f22720abb7..341ed5c06ce 100644 --- a/daemons/pacemakerd/pcmkd_messages.c +++ b/daemons/pacemakerd/pcmkd_messages.c @@ -145,11 +145,11 @@ static xmlNode * handle_unknown_request(pcmk__request_t *request) { pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags, - PCMK__XE_ACK, NULL, CRM_EX_INVALID_PARAM); + PCMK__XE_NACK, NULL, CRM_EX_PROTOCOL); pcmk__format_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID, "Unknown IPC request type '%s' (bug?)", - pcmk__client_name(request->ipc_client)); + pcmk__s(request->op, "")); return NULL; } @@ -248,7 +248,7 @@ pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size) } if (msg == NULL) { - pcmk__ipc_send_ack(c, id, flags, PCMK__XE_ACK, NULL, CRM_EX_PROTOCOL); + pcmk__ipc_send_ack(c, id, flags, PCMK__XE_NACK, NULL, CRM_EX_PROTOCOL); return 0; } else { diff --git a/daemons/schedulerd/schedulerd_messages.c b/daemons/schedulerd/schedulerd_messages.c index 1862b59f7fb..1d83d7d9acd 100644 --- a/daemons/schedulerd/schedulerd_messages.c +++ b/daemons/schedulerd/schedulerd_messages.c @@ -178,11 +178,11 @@ static xmlNode * handle_unknown_request(pcmk__request_t *request) { pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags, - PCMK__XE_ACK, NULL, CRM_EX_INVALID_PARAM); + PCMK__XE_NACK, NULL, CRM_EX_PROTOCOL); pcmk__format_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID, "Unknown IPC request type '%s' (bug?)", - pcmk__client_name(request->ipc_client)); + pcmk__s(request->op, "")); return NULL; } @@ -265,7 +265,7 @@ pe_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size) } if (msg == NULL) { - pcmk__ipc_send_ack(c, id, flags, PCMK__XE_ACK, NULL, CRM_EX_PROTOCOL); + pcmk__ipc_send_ack(c, id, flags, PCMK__XE_NACK, NULL, CRM_EX_PROTOCOL); return 0; }