diff --git a/daemons/based/based_callbacks.c b/daemons/based/based_callbacks.c
index 1f62dd0e3c..dd291e9db0 100644
--- a/daemons/based/based_callbacks.c
+++ b/daemons/based/based_callbacks.c
@@ -1,1632 +1,1632 @@
 /*
  * Copyright 2004-2022 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <stdint.h>     // uint32_t, uint64_t, UINT64_C()
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>  /* U64T ~ PRIu64 */
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/cluster/internal.h>
 
 #include <crm/common/xml.h>
 #include <crm/common/remote_internal.h>
 
 #include <pacemaker-based.h>
 
 #define EXIT_ESCALATION_MS 10000
 
 static unsigned long cib_local_bcast_num = 0;
 
 typedef struct cib_local_notify_s {
     xmlNode *notify_src;
     char *client_id;
     gboolean from_peer;
     gboolean sync_reply;
 } cib_local_notify_t;
 
 int next_client_id = 0;
 
 gboolean legacy_mode = FALSE;
 
 qb_ipcs_service_t *ipcs_ro = NULL;
 qb_ipcs_service_t *ipcs_rw = NULL;
 qb_ipcs_service_t *ipcs_shm = NULL;
 
 void send_cib_replace(const xmlNode * sync_request, const char *host);
 static void cib_process_request(xmlNode *request, gboolean privileged,
                                 pcmk__client_t *cib_client);
 
 
 static int cib_process_command(xmlNode *request, xmlNode **reply,
                                xmlNode **cib_diff, gboolean privileged);
 
 gboolean cib_common_callback(qb_ipcs_connection_t * c, void *data, size_t size,
                              gboolean privileged);
 
 gboolean cib_legacy_mode(void)
 {
     return legacy_mode;
 }
 
 
 static int32_t
 cib_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 {
     if (cib_shutdown_flag) {
         crm_info("Ignoring new IPC client [%d] during shutdown",
                  pcmk__client_pid(c));
         return -EPERM;
     }
 
     if (pcmk__new_client(c, uid, gid) == NULL) {
         return -EIO;
     }
     return 0;
 }
 
 static int32_t
 cib_ipc_dispatch_rw(qb_ipcs_connection_t * c, void *data, size_t size)
 {
     pcmk__client_t *client = pcmk__find_client(c);
 
     crm_trace("%p message from %s", c, client->id);
     return cib_common_callback(c, data, size, TRUE);
 }
 
 static int32_t
 cib_ipc_dispatch_ro(qb_ipcs_connection_t * c, void *data, size_t size)
 {
     pcmk__client_t *client = pcmk__find_client(c);
 
     crm_trace("%p message from %s", c, client->id);
     return cib_common_callback(c, data, size, FALSE);
 }
 
 /* Error code means? */
 static int32_t
 cib_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);
     pcmk__free_client(client);
     return 0;
 }
 
 static void
 cib_ipc_destroy(qb_ipcs_connection_t * c)
 {
     crm_trace("Connection %p", c);
     cib_ipc_closed(c);
     if (cib_shutdown_flag) {
         cib_shutdown(0);
     }
 }
 
 struct qb_ipcs_service_handlers ipc_ro_callbacks = {
     .connection_accept = cib_ipc_accept,
     .connection_created = NULL,
     .msg_process = cib_ipc_dispatch_ro,
     .connection_closed = cib_ipc_closed,
     .connection_destroyed = cib_ipc_destroy
 };
 
 struct qb_ipcs_service_handlers ipc_rw_callbacks = {
     .connection_accept = cib_ipc_accept,
     .connection_created = NULL,
     .msg_process = cib_ipc_dispatch_rw,
     .connection_closed = cib_ipc_closed,
     .connection_destroyed = cib_ipc_destroy
 };
 
 void
 cib_common_callback_worker(uint32_t id, uint32_t flags, xmlNode * op_request,
                            pcmk__client_t *cib_client, gboolean privileged)
 {
     const char *op = crm_element_value(op_request, F_CIB_OPERATION);
 
     if (pcmk__str_eq(op, CRM_OP_REGISTER, pcmk__str_none)) {
         if (flags & crm_ipc_client_response) {
             xmlNode *ack = create_xml_node(NULL, __func__);
 
             crm_xml_add(ack, F_CIB_OPERATION, CRM_OP_REGISTER);
             crm_xml_add(ack, F_CIB_CLIENTID, cib_client->id);
             pcmk__ipc_send_xml(cib_client, id, ack, flags);
             cib_client->request_id = 0;
             free_xml(ack);
         }
         return;
 
     } else if (pcmk__str_eq(op, T_CIB_NOTIFY, pcmk__str_none)) {
         /* Update the notify filters for this client */
         int on_off = 0;
         crm_exit_t status = CRM_EX_OK;
         uint64_t bit = UINT64_C(0);
         const char *type = crm_element_value(op_request, F_CIB_NOTIFY_TYPE);
 
         crm_element_value_int(op_request, F_CIB_NOTIFY_ACTIVATE, &on_off);
 
         crm_debug("Setting %s callbacks %s for client %s",
                   type, (on_off? "on" : "off"), pcmk__client_name(cib_client));
 
         if (pcmk__str_eq(type, T_CIB_POST_NOTIFY, pcmk__str_casei)) {
             bit = cib_notify_post;
 
         } else if (pcmk__str_eq(type, T_CIB_PRE_NOTIFY, pcmk__str_casei)) {
             bit = cib_notify_pre;
 
         } else if (pcmk__str_eq(type, T_CIB_UPDATE_CONFIRM, pcmk__str_casei)) {
             bit = cib_notify_confirm;
 
         } else if (pcmk__str_eq(type, T_CIB_DIFF_NOTIFY, pcmk__str_casei)) {
             bit = cib_notify_diff;
 
         } else if (pcmk__str_eq(type, T_CIB_REPLACE_NOTIFY, pcmk__str_casei)) {
             bit = cib_notify_replace;
 
         } else {
             status = CRM_EX_INVALID_PARAM;
         }
 
         if (bit != 0) {
             if (on_off) {
                 pcmk__set_client_flags(cib_client, bit);
             } else {
                 pcmk__clear_client_flags(cib_client, bit);
             }
         }
 
         pcmk__ipc_send_ack(cib_client, id, flags, "ack", NULL, status);
         return;
     }
 
     cib_process_request(op_request, privileged, cib_client);
 }
 
 int32_t
 cib_common_callback(qb_ipcs_connection_t * c, void *data, size_t size, gboolean privileged)
 {
     uint32_t id = 0;
     uint32_t flags = 0;
     int call_options = 0;
     pcmk__client_t *cib_client = pcmk__find_client(c);
     xmlNode *op_request = pcmk__client_data2xml(cib_client, data, &id, &flags);
 
     if (op_request) {
         crm_element_value_int(op_request, F_CIB_CALLOPTS, &call_options);
     }
 
     if (op_request == NULL) {
         crm_trace("Invalid message from %p", c);
         pcmk__ipc_send_ack(cib_client, id, flags, "nack", NULL, CRM_EX_PROTOCOL);
         return 0;
 
     } else if(cib_client == NULL) {
         crm_trace("Invalid client %p", c);
         return 0;
     }
 
     if (pcmk_is_set(call_options, cib_sync_call)) {
         CRM_LOG_ASSERT(flags & crm_ipc_client_response);
         CRM_LOG_ASSERT(cib_client->request_id == 0);    /* This means the client has two synchronous events in-flight */
         cib_client->request_id = id;    /* Reply only to the last one */
     }
 
     if (cib_client->name == NULL) {
         const char *value = crm_element_value(op_request, F_CIB_CLIENTNAME);
 
         if (value == NULL) {
             cib_client->name = pcmk__itoa(cib_client->pid);
         } else {
             cib_client->name = strdup(value);
             if (crm_is_daemon_name(value)) {
                 pcmk__set_client_flags(cib_client, cib_is_daemon);
             }
         }
     }
 
     /* Allow cluster daemons more leeway before being evicted */
     if (pcmk_is_set(cib_client->flags, cib_is_daemon)) {
         const char *qmax = cib_config_lookup("cluster-ipc-limit");
 
         if (pcmk__set_client_queue_max(cib_client, qmax)) {
             crm_trace("IPC threshold for client %s[%u] is now %u",
                       pcmk__client_name(cib_client), cib_client->pid,
                       cib_client->queue_max);
         }
     }
 
     crm_xml_add(op_request, F_CIB_CLIENTID, cib_client->id);
     crm_xml_add(op_request, F_CIB_CLIENTNAME, cib_client->name);
 
     CRM_LOG_ASSERT(cib_client->user != NULL);
     pcmk__update_acl_user(op_request, F_CIB_USER, cib_client->user);
 
     cib_common_callback_worker(id, flags, op_request, cib_client, privileged);
     free_xml(op_request);
 
     return 0;
 }
 
 static uint64_t ping_seq = 0;
 static char *ping_digest = NULL;
 static bool ping_modified_since = FALSE;
 int sync_our_cib(xmlNode * request, gboolean all);
 
 static gboolean
 cib_digester_cb(gpointer data)
 {
     if (cib_is_master) {
         char buffer[32];
         xmlNode *ping = create_xml_node(NULL, "ping");
 
         ping_seq++;
         free(ping_digest);
         ping_digest = NULL;
         ping_modified_since = FALSE;
         snprintf(buffer, 32, "%" U64T, ping_seq);
         crm_trace("Requesting peer digests (%s)", buffer);
 
         crm_xml_add(ping, F_TYPE, "cib");
         crm_xml_add(ping, F_CIB_OPERATION, CRM_OP_PING);
         crm_xml_add(ping, F_CIB_PING_ID, buffer);
 
         crm_xml_add(ping, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
         send_cluster_message(NULL, crm_msg_cib, ping, TRUE);
 
         free_xml(ping);
     }
     return FALSE;
 }
 
 static void
 process_ping_reply(xmlNode *reply) 
 {
     uint64_t seq = 0;
     const char *host = crm_element_value(reply, F_ORIG);
 
     xmlNode *pong = get_message_xml(reply, F_CIB_CALLDATA);
     const char *seq_s = crm_element_value(pong, F_CIB_PING_ID);
     const char *digest = crm_element_value(pong, XML_ATTR_DIGEST);
 
     if (seq_s == NULL) {
         crm_debug("Ignoring ping reply with no " F_CIB_PING_ID);
         return;
 
     } else {
         long long seq_ll;
 
         if (pcmk__scan_ll(seq_s, &seq_ll, 0LL) != pcmk_rc_ok) {
             return;
         }
         seq = (uint64_t) seq_ll;
     }
 
     if(digest == NULL) {
         crm_trace("Ignoring ping reply %s from %s with no digest", seq_s, host);
 
     } else if(seq != ping_seq) {
         crm_trace("Ignoring out of sequence ping reply %s from %s", seq_s, host);
 
     } else if(ping_modified_since) {
         crm_trace("Ignoring ping reply %s from %s: cib updated since", seq_s, host);
 
     } else {
         const char *version = crm_element_value(pong, XML_ATTR_CRM_VERSION);
 
         if(ping_digest == NULL) {
             crm_trace("Calculating new digest");
             ping_digest = calculate_xml_versioned_digest(the_cib, FALSE, TRUE, version);
         }
 
         crm_trace("Processing ping reply %s from %s (%s)", seq_s, host, digest);
         if (!pcmk__str_eq(ping_digest, digest, pcmk__str_casei)) {
             xmlNode *remote_cib = get_message_xml(pong, F_CIB_CALLDATA);
 
             crm_notice("Local CIB %s.%s.%s.%s differs from %s: %s.%s.%s.%s %p",
                        crm_element_value(the_cib, XML_ATTR_GENERATION_ADMIN),
                        crm_element_value(the_cib, XML_ATTR_GENERATION),
                        crm_element_value(the_cib, XML_ATTR_NUMUPDATES),
                        ping_digest, host,
                        remote_cib?crm_element_value(remote_cib, XML_ATTR_GENERATION_ADMIN):"_",
                        remote_cib?crm_element_value(remote_cib, XML_ATTR_GENERATION):"_",
                        remote_cib?crm_element_value(remote_cib, XML_ATTR_NUMUPDATES):"_",
                        digest, remote_cib);
 
             if(remote_cib && remote_cib->children) {
                 /* Additional debug */
                 xml_calculate_changes(the_cib, remote_cib);
                 xml_log_changes(LOG_INFO, __func__, remote_cib);
                 crm_trace("End of differences");
             }
 
             free_xml(remote_cib);
             sync_our_cib(reply, FALSE);
         }
     }
 }
 
 static void
 do_local_notify(xmlNode * notify_src, const char *client_id,
                 gboolean sync_reply, gboolean from_peer)
 {
     int rid = 0;
     int call_id = 0;
     pcmk__client_t *client_obj = NULL;
 
     CRM_ASSERT(notify_src && client_id);
 
     crm_element_value_int(notify_src, F_CIB_CALLID, &call_id);
 
     client_obj = pcmk__find_client_by_id(client_id);
     if (client_obj == NULL) {
         crm_debug("Could not send response %d: client %s not found",
                   call_id, client_id);
         return;
     }
 
     if (sync_reply) {
         if (client_obj->ipcs) {
             CRM_LOG_ASSERT(client_obj->request_id);
 
             rid = client_obj->request_id;
             client_obj->request_id = 0;
 
             crm_trace("Sending response %d to client %s%s",
                       rid, pcmk__client_name(client_obj),
                       (from_peer? " (originator of delegated request)" : ""));
         } else {
             crm_trace("Sending response (call %d) to client %s%s",
                       call_id, pcmk__client_name(client_obj),
                       (from_peer? " (originator of delegated request)" : ""));
         }
 
     } else {
         crm_trace("Sending event %d to client %s%s",
                   call_id, pcmk__client_name(client_obj),
                   (from_peer? " (originator of delegated request)" : ""));
     }
 
     switch (PCMK__CLIENT_TYPE(client_obj)) {
         case pcmk__client_ipc:
             {
                 int rc = pcmk__ipc_send_xml(client_obj, rid, notify_src,
                                             (sync_reply? crm_ipc_flags_none
                                              : crm_ipc_server_event));
 
                 if (rc != pcmk_rc_ok) {
                     crm_warn("%s reply to client %s failed: %s " CRM_XS " rc=%d",
                              (sync_reply? "Synchronous" : "Asynchronous"),
                              pcmk__client_name(client_obj), pcmk_rc_str(rc),
                              rc);
                 }
             }
             break;
 #ifdef HAVE_GNUTLS_GNUTLS_H
         case pcmk__client_tls:
 #endif
         case pcmk__client_tcp:
             pcmk__remote_send_xml(client_obj->remote, notify_src);
             break;
         default:
             crm_err("Unknown transport for client %s "
                     CRM_XS " flags=%#016" PRIx64,
                     pcmk__client_name(client_obj), client_obj->flags);
     }
 }
 
 static void
 local_notify_destroy_callback(gpointer data)
 {
     cib_local_notify_t *notify = data;
 
     free_xml(notify->notify_src);
     free(notify->client_id);
     free(notify);
 }
 
 static void
 check_local_notify(int bcast_id)
 {
     cib_local_notify_t *notify = NULL;
 
     if (!local_notify_queue) {
         return;
     }
 
     notify = pcmk__intkey_table_lookup(local_notify_queue, bcast_id);
 
     if (notify) {
         do_local_notify(notify->notify_src, notify->client_id, notify->sync_reply,
                         notify->from_peer);
         pcmk__intkey_table_remove(local_notify_queue, bcast_id);
     }
 }
 
 static void
 queue_local_notify(xmlNode * notify_src, const char *client_id, gboolean sync_reply,
                    gboolean from_peer)
 {
     cib_local_notify_t *notify = calloc(1, sizeof(cib_local_notify_t));
 
     notify->notify_src = notify_src;
     notify->client_id = strdup(client_id);
     notify->sync_reply = sync_reply;
     notify->from_peer = from_peer;
 
     if (!local_notify_queue) {
         local_notify_queue = pcmk__intkey_table(local_notify_destroy_callback);
     }
     pcmk__intkey_table_insert(local_notify_queue, cib_local_bcast_num, notify);
     // cppcheck doesn't know notify will get freed when hash table is destroyed
     // cppcheck-suppress memleak
 }
 
 static void
 parse_local_options_v1(pcmk__client_t *cib_client, int call_type,
                        int call_options, const char *host, const char *op,
                        gboolean *local_notify, gboolean *needs_reply,
                        gboolean *process, gboolean *needs_forward)
 {
     if (cib_op_modifies(call_type)
         && !(call_options & cib_inhibit_bcast)) {
         /* we need to send an update anyway */
         *needs_reply = TRUE;
     } else {
         *needs_reply = FALSE;
     }
 
     if (host == NULL && (call_options & cib_scope_local)) {
         crm_trace("Processing locally scoped %s op from client %s",
                   op, pcmk__client_name(cib_client));
         *local_notify = TRUE;
 
     } else if (host == NULL && cib_is_master) {
         crm_trace("Processing master %s op locally from client %s",
                   op, pcmk__client_name(cib_client));
         *local_notify = TRUE;
 
     } else if (pcmk__str_eq(host, cib_our_uname, pcmk__str_casei)) {
         crm_trace("Processing locally addressed %s op from client %s",
                   op, pcmk__client_name(cib_client));
         *local_notify = TRUE;
 
     } else if (stand_alone) {
         *needs_forward = FALSE;
         *local_notify = TRUE;
         *process = TRUE;
 
     } else {
         crm_trace("%s op from %s needs to be forwarded to client %s",
                   op, pcmk__client_name(cib_client),
                   (host? host : "the master instance"));
         *needs_forward = TRUE;
         *process = FALSE;
     }
 }
 
 static void
 parse_local_options_v2(pcmk__client_t *cib_client, int call_type,
                        int call_options, const char *host, const char *op,
                        gboolean *local_notify, gboolean *needs_reply,
                        gboolean *process, gboolean *needs_forward)
 {
     if (cib_op_modifies(call_type)) {
         if (pcmk__str_any_of(op, PCMK__CIB_REQUEST_PRIMARY,
                              PCMK__CIB_REQUEST_SECONDARY, NULL)) {
             /* Always handle these locally */
             *process = TRUE;
             *needs_reply = FALSE;
             *local_notify = TRUE;
             *needs_forward = FALSE;
             return;
 
         } else {
             /* Redirect all other updates via CPG */
             *needs_reply = TRUE;
             *needs_forward = TRUE;
             *process = FALSE;
             crm_trace("%s op from %s needs to be forwarded to client %s",
                       op, pcmk__client_name(cib_client),
                       (host? host : "the master instance"));
             return;
         }
     }
 
 
     *process = TRUE;
     *needs_reply = FALSE;
     *local_notify = TRUE;
     *needs_forward = FALSE;
 
     if (stand_alone) {
         crm_trace("Processing %s op from client %s (stand-alone)",
                   op, pcmk__client_name(cib_client));
 
     } else if (host == NULL) {
         crm_trace("Processing unaddressed %s op from client %s",
                   op, pcmk__client_name(cib_client));
 
     } else if (pcmk__str_eq(host, cib_our_uname, pcmk__str_casei)) {
         crm_trace("Processing locally addressed %s op from client %s",
                   op, pcmk__client_name(cib_client));
 
     } else {
         crm_trace("%s op from %s needs to be forwarded to client %s",
                   op, pcmk__client_name(cib_client), host);
         *needs_forward = TRUE;
         *process = FALSE;
     }
 }
 
 static void
 parse_local_options(pcmk__client_t *cib_client, int call_type,
                     int call_options, const char *host, const char *op,
                     gboolean *local_notify, gboolean *needs_reply,
                     gboolean *process, gboolean *needs_forward)
 {
     if(cib_legacy_mode()) {
         parse_local_options_v1(cib_client, call_type, call_options, host,
                                op, local_notify, needs_reply, process, needs_forward);
     } else {
         parse_local_options_v2(cib_client, call_type, call_options, host,
                                op, local_notify, needs_reply, process, needs_forward);
     }
 }
 
 static gboolean
 parse_peer_options_v1(int call_type, xmlNode * request,
                    gboolean * local_notify, gboolean * needs_reply, gboolean * process,
                    gboolean * needs_forward)
 {
     const char *op = NULL;
     const char *host = NULL;
     const char *delegated = NULL;
     const char *originator = crm_element_value(request, F_ORIG);
     const char *reply_to = crm_element_value(request, F_CIB_ISREPLY);
 
     gboolean is_reply = pcmk__str_eq(reply_to, cib_our_uname, pcmk__str_casei);
 
     if (pcmk__xe_attr_is_true(request, F_CIB_GLOBAL_UPDATE)) {
         *needs_reply = FALSE;
         if (is_reply) {
             *local_notify = TRUE;
             crm_trace("Processing global/peer update from %s"
                       " that originated from us", originator);
         } else {
             crm_trace("Processing global/peer update from %s", originator);
         }
         return TRUE;
     }
 
     op = crm_element_value(request, F_CIB_OPERATION);
     crm_trace("Processing %s request sent by %s", op, originator);
     if (pcmk__str_eq(op, "cib_shutdown_req", pcmk__str_casei)) {
         /* Always process these */
         *local_notify = FALSE;
         if (reply_to == NULL || is_reply) {
             *process = TRUE;
         }
         if (is_reply) {
             *needs_reply = FALSE;
         }
         return *process;
     }
 
     if (is_reply && pcmk__str_eq(op, CRM_OP_PING, pcmk__str_casei)) {
         process_ping_reply(request);
         return FALSE;
     }
 
     if (is_reply) {
         crm_trace("Forward reply sent from %s to local clients", originator);
         *process = FALSE;
         *needs_reply = FALSE;
         *local_notify = TRUE;
         return TRUE;
     }
 
     host = crm_element_value(request, F_CIB_HOST);
     if (host != NULL && pcmk__str_eq(host, cib_our_uname, pcmk__str_casei)) {
         crm_trace("Processing %s request sent to us from %s", op, originator);
         return TRUE;
 
     } else if(is_reply == FALSE && pcmk__str_eq(op, CRM_OP_PING, pcmk__str_casei)) {
         crm_trace("Processing %s request sent to %s by %s", op, host?host:"everyone", originator);
         *needs_reply = TRUE;
         return TRUE;
 
     } else if (host == NULL && cib_is_master == TRUE) {
         crm_trace("Processing %s request sent to master instance from %s", op, originator);
         return TRUE;
     }
 
     delegated = crm_element_value(request, F_CIB_DELEGATED);
     if (delegated != NULL) {
         crm_trace("Ignoring msg for master instance");
 
     } else if (host != NULL) {
         /* this is for a specific instance and we're not it */
         crm_trace("Ignoring msg for instance on %s", host);
 
     } else if (reply_to == NULL && cib_is_master == FALSE) {
         /* this is for the master instance and we're not it */
         crm_trace("Ignoring reply for primary instance");
 
     } else if (pcmk__str_eq(op, "cib_shutdown_req", pcmk__str_casei)) {
         if (reply_to != NULL) {
             crm_debug("Processing %s from %s", op, originator);
             *needs_reply = FALSE;
 
         } else {
             crm_debug("Processing %s reply from %s", op, originator);
         }
         return TRUE;
 
     } else {
         crm_err("Nothing for us to do?");
         crm_log_xml_err(request, "Peer[inbound]");
     }
 
     return FALSE;
 }
 
 static gboolean
 parse_peer_options_v2(int call_type, xmlNode * request,
                    gboolean * local_notify, gboolean * needs_reply, gboolean * process,
                    gboolean * needs_forward)
 {
     const char *host = NULL;
     const char *delegated = crm_element_value(request, F_CIB_DELEGATED);
     const char *op = crm_element_value(request, F_CIB_OPERATION);
     const char *originator = crm_element_value(request, F_ORIG);
     const char *reply_to = crm_element_value(request, F_CIB_ISREPLY);
 
     gboolean is_reply = pcmk__str_eq(reply_to, cib_our_uname, pcmk__str_casei);
 
     if (pcmk__str_eq(op, PCMK__CIB_REQUEST_REPLACE, pcmk__str_none)) {
         /* sync_our_cib() sets F_CIB_ISREPLY */
         if (reply_to) {
             delegated = reply_to;
         }
         goto skip_is_reply;
 
     } else if (pcmk__str_eq(op, PCMK__CIB_REQUEST_SYNC_TO_ALL,
                             pcmk__str_none)) {
         // Nothing to do
 
     } else if (is_reply && pcmk__str_eq(op, CRM_OP_PING, pcmk__str_casei)) {
         process_ping_reply(request);
         return FALSE;
 
     } else if (pcmk__str_eq(op, PCMK__CIB_REQUEST_UPGRADE, pcmk__str_none)) {
         /* Only the DC (node with the oldest software) should process
          * this operation if F_CIB_SCHEMA_MAX is unset
          *
          * If the DC is happy it will then send out another
          * PCMK__CIB_REQUEST_UPGRADE which will tell all nodes to do the actual
          * upgrade.
          *
          * Except this time F_CIB_SCHEMA_MAX will be set which puts a
          * limit on how far newer nodes will go
          */
         const char *max = crm_element_value(request, F_CIB_SCHEMA_MAX);
         const char *upgrade_rc = crm_element_value(request, F_CIB_UPGRADE_RC);
 
         crm_trace("Parsing %s operation%s for %s with max=%s and upgrade_rc=%s",
                   op, (is_reply? " reply" : ""),
                   (cib_is_master? "master" : "slave"),
                   (max? max : "none"), (upgrade_rc? upgrade_rc : "none"));
 
         if (upgrade_rc != NULL) {
             // Our upgrade request was rejected by DC, notify clients of result
             crm_xml_add(request, F_CIB_RC, upgrade_rc);
 
         } else if ((max == NULL) && cib_is_master) {
             /* We are the DC, check if this upgrade is allowed */
             goto skip_is_reply;
 
         } else if(max) {
             /* Ok, go ahead and upgrade to 'max' */
             goto skip_is_reply;
 
         } else {
             // Ignore broadcast client requests when we're not DC
             return FALSE;
         }
 
     } else if (pcmk__xe_attr_is_true(request, F_CIB_GLOBAL_UPDATE)) {
         crm_info("Detected legacy %s global update from %s", op, originator);
         send_sync_request(NULL);
         legacy_mode = TRUE;
         return FALSE;
 
     } else if (is_reply && cib_op_modifies(call_type)) {
         crm_trace("Ignoring legacy %s reply sent from %s to local clients", op, originator);
         return FALSE;
 
     } else if (pcmk__str_eq(op, "cib_shutdown_req", pcmk__str_casei)) {
         /* Legacy handling */
         crm_debug("Legacy handling of %s message from %s", op, originator);
         *local_notify = FALSE;
         if (reply_to == NULL) {
             *process = TRUE;
         }
         return *process;
     }
 
     if(is_reply) {
         crm_trace("Handling %s reply sent from %s to local clients", op, originator);
         *process = FALSE;
         *needs_reply = FALSE;
         *local_notify = TRUE;
         return TRUE;
     }
 
   skip_is_reply:
     *process = TRUE;
     *needs_reply = FALSE;
 
     if(pcmk__str_eq(delegated, cib_our_uname, pcmk__str_casei)) {
         *local_notify = TRUE;
     } else {
         *local_notify = FALSE;
     }
 
     host = crm_element_value(request, F_CIB_HOST);
     if (host != NULL && pcmk__str_eq(host, cib_our_uname, pcmk__str_casei)) {
         crm_trace("Processing %s request sent to us from %s", op, originator);
         *needs_reply = TRUE;
         return TRUE;
 
     } else if (host != NULL) {
         /* this is for a specific instance and we're not it */
         crm_trace("Ignoring %s operation for instance on %s", op, host);
         return FALSE;
 
     } else if(is_reply == FALSE && pcmk__str_eq(op, CRM_OP_PING, pcmk__str_casei)) {
         *needs_reply = TRUE;
     }
 
     crm_trace("Processing %s request sent to everyone by %s/%s on %s %s", op,
               crm_element_value(request, F_CIB_CLIENTNAME),
               crm_element_value(request, F_CIB_CALLID),
               originator, (*local_notify)?"(notify)":"");
     return TRUE;
 }
 
 static gboolean
 parse_peer_options(int call_type, xmlNode * request,
                    gboolean * local_notify, gboolean * needs_reply, gboolean * process,
                    gboolean * needs_forward)
 {
     /* TODO: What happens when an update comes in after node A
      * requests the CIB from node B, but before it gets the reply (and
      * sends out the replace operation)
      */
     if(cib_legacy_mode()) {
         return parse_peer_options_v1(
             call_type, request, local_notify, needs_reply, process, needs_forward);
     } else {
         return parse_peer_options_v2(
             call_type, request, local_notify, needs_reply, process, needs_forward);
     }
 }
 
 static void
 forward_request(xmlNode * request, pcmk__client_t *cib_client, int call_options)
 {
     const char *op = crm_element_value(request, F_CIB_OPERATION);
     const char *host = crm_element_value(request, F_CIB_HOST);
 
     crm_xml_add(request, F_CIB_DELEGATED, cib_our_uname);
 
     if (host != NULL) {
         crm_trace("Forwarding %s op to %s", op, host);
         send_cluster_message(crm_get_peer(0, host), crm_msg_cib, request, FALSE);
 
     } else {
         crm_trace("Forwarding %s op to master instance", op);
         send_cluster_message(NULL, crm_msg_cib, request, FALSE);
     }
 
     /* Return the request to its original state */
     xml_remove_prop(request, F_CIB_DELEGATED);
 
     if (call_options & cib_discard_reply) {
         crm_trace("Client not interested in reply");
     }
 }
 
 static gboolean
 send_peer_reply(xmlNode * msg, xmlNode * result_diff, const char *originator, gboolean broadcast)
 {
     CRM_ASSERT(msg != NULL);
 
     if (broadcast) {
         /* this (successful) call modified the CIB _and_ the
          * change needs to be broadcast...
          *   send via HA to other nodes
          */
         int diff_add_updates = 0;
         int diff_add_epoch = 0;
         int diff_add_admin_epoch = 0;
 
         int diff_del_updates = 0;
         int diff_del_epoch = 0;
         int diff_del_admin_epoch = 0;
 
         const char *digest = NULL;
         int format = 1;
 
         CRM_LOG_ASSERT(result_diff != NULL);
         digest = crm_element_value(result_diff, XML_ATTR_DIGEST);
         crm_element_value_int(result_diff, "format", &format);
 
         cib_diff_version_details(result_diff,
                                  &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
                                  &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
 
         crm_trace("Sending update diff %d.%d.%d -> %d.%d.%d %s",
                   diff_del_admin_epoch, diff_del_epoch, diff_del_updates,
                   diff_add_admin_epoch, diff_add_epoch, diff_add_updates, digest);
 
         crm_xml_add(msg, F_CIB_ISREPLY, originator);
         pcmk__xe_set_bool_attr(msg, F_CIB_GLOBAL_UPDATE, true);
         crm_xml_add(msg, F_CIB_OPERATION, PCMK__CIB_REQUEST_APPLY_PATCH);
         crm_xml_add(msg, F_CIB_USER, CRM_DAEMON_USER);
 
         if (format == 1) {
             CRM_ASSERT(digest != NULL);
         }
 
         add_message_xml(msg, F_CIB_UPDATE_DIFF, result_diff);
         crm_log_xml_explicit(msg, "copy");
         return send_cluster_message(NULL, crm_msg_cib, msg, TRUE);
 
     } else if (originator != NULL) {
         /* send reply via HA to originating node */
         crm_trace("Sending request result to %s only", originator);
         crm_xml_add(msg, F_CIB_ISREPLY, originator);
         return send_cluster_message(crm_get_peer(0, originator), crm_msg_cib, msg, FALSE);
     }
 
     return FALSE;
 }
 
 /*!
  * \internal
  * \brief Handle an IPC or CPG message containing a request
  *
  * \param[in] request            Request XML
  * \param[in] privileged         Whether privileged commands may be run
  *                               (see cib_server_ops[] definition)
  * \param[in] cib_client         IPC client that sent request (or NULL if CPG)
  */
 static void
 cib_process_request(xmlNode *request, gboolean privileged,
                     pcmk__client_t *cib_client)
 {
     int call_type = 0;
     int call_options = 0;
 
     gboolean process = TRUE;        // Whether to process request locally now
     gboolean is_update = TRUE;      // Whether request would modify CIB
     gboolean needs_reply = TRUE;    // Whether to build a reply
     gboolean local_notify = FALSE;  // Whether to notify (local) requester
     gboolean needs_forward = FALSE; // Whether to forward request somewhere else
 
     xmlNode *op_reply = NULL;
     xmlNode *result_diff = NULL;
 
     int rc = pcmk_ok;
     const char *op = crm_element_value(request, F_CIB_OPERATION);
     const char *originator = crm_element_value(request, F_ORIG);
     const char *host = crm_element_value(request, F_CIB_HOST);
     const char *target = NULL;
     const char *call_id = crm_element_value(request, F_CIB_CALLID);
     const char *client_id = crm_element_value(request, F_CIB_CLIENTID);
     const char *client_name = crm_element_value(request, F_CIB_CLIENTNAME);
     const char *reply_to = crm_element_value(request, F_CIB_ISREPLY);
 
     crm_element_value_int(request, F_CIB_CALLOPTS, &call_options);
 
     if ((host != NULL) && (*host == '\0')) {
         host = NULL;
     }
 
     if (host) {
         target = host;
 
     } else if (call_options & cib_scope_local) {
         target = "local host";
 
     } else {
         target = "master";
     }
 
     if (cib_client == NULL) {
         crm_trace("Processing peer %s operation from %s/%s on %s intended for %s (reply=%s)",
                   op, client_name, call_id, originator, target, reply_to);
     } else {
         crm_xml_add(request, F_ORIG, cib_our_uname);
         crm_trace("Processing local %s operation from %s/%s intended for %s", op, client_name, call_id, target);
     }
 
     rc = cib_get_operation_id(op, &call_type);
     if (rc != pcmk_ok) {
         /* TODO: construct error reply? */
         crm_err("Pre-processing of command failed: %s", pcmk_strerror(rc));
         return;
     }
 
     if (cib_client != NULL) {
         parse_local_options(cib_client, call_type, call_options, host, op,
                             &local_notify, &needs_reply, &process, &needs_forward);
 
     } else if (parse_peer_options(call_type, request, &local_notify,
                                   &needs_reply, &process, &needs_forward) == FALSE) {
         return;
     }
 
     is_update = cib_op_modifies(call_type);
 
     if (call_options & cib_discard_reply) {
         /* If the request will modify the CIB, and we are in legacy mode, we
          * need to build a reply so we can broadcast a diff, even if the
          * requester doesn't want one.
          */
         needs_reply = is_update && cib_legacy_mode();
         local_notify = FALSE;
     }
 
     if (needs_forward) {
         const char *section = crm_element_value(request, F_CIB_SECTION);
         int log_level = LOG_INFO;
 
-        if (pcmk__str_eq(op, CRM_OP_NOOP, pcmk__str_casei)) {
+        if (pcmk__str_eq(op, PCMK__CIB_REQUEST_NOOP, pcmk__str_none)) {
             log_level = LOG_DEBUG;
         }
 
         do_crm_log(log_level,
                    "Forwarding %s operation for section %s to %s (origin=%s/%s/%s)",
                    op,
                    section ? section : "'all'",
                    host ? host : cib_legacy_mode() ? "master" : "all",
                    originator ? originator : "local",
                    client_name, call_id);
 
         forward_request(request, cib_client, call_options);
         return;
     }
 
     if (cib_status != pcmk_ok) {
         const char *call = crm_element_value(request, F_CIB_CALLID);
 
         rc = cib_status;
         crm_err("Operation ignored, cluster configuration is invalid."
                 " Please repair and restart: %s", pcmk_strerror(cib_status));
 
         op_reply = create_xml_node(NULL, "cib-reply");
         crm_xml_add(op_reply, F_TYPE, T_CIB);
         crm_xml_add(op_reply, F_CIB_OPERATION, op);
         crm_xml_add(op_reply, F_CIB_CALLID, call);
         crm_xml_add(op_reply, F_CIB_CLIENTID, client_id);
         crm_xml_add_int(op_reply, F_CIB_CALLOPTS, call_options);
         crm_xml_add_int(op_reply, F_CIB_RC, rc);
 
         crm_trace("Attaching reply output");
         add_message_xml(op_reply, F_CIB_CALLDATA, the_cib);
 
         crm_log_xml_explicit(op_reply, "cib:reply");
 
     } else if (process) {
         time_t finished = 0;
         time_t now = time(NULL);
         int level = LOG_INFO;
         const char *section = crm_element_value(request, F_CIB_SECTION);
 
         rc = cib_process_command(request, &op_reply, &result_diff, privileged);
 
         if (!is_update) {
             level = LOG_TRACE;
 
         } else if (pcmk__xe_attr_is_true(request, F_CIB_GLOBAL_UPDATE)) {
             switch (rc) {
                 case pcmk_ok:
                     level = LOG_INFO;
                     break;
                 case -pcmk_err_old_data:
                 case -pcmk_err_diff_resync:
                 case -pcmk_err_diff_failed:
                     level = LOG_TRACE;
                     break;
                 default:
                     level = LOG_ERR;
             }
 
         } else if (rc != pcmk_ok) {
             level = LOG_WARNING;
         }
 
         do_crm_log(level,
                    "Completed %s operation for section %s: %s (rc=%d, origin=%s/%s/%s, version=%s.%s.%s)",
                    op, section ? section : "'all'", pcmk_strerror(rc), rc,
                    originator ? originator : "local", client_name, call_id,
                    the_cib ? crm_element_value(the_cib, XML_ATTR_GENERATION_ADMIN) : "0",
                    the_cib ? crm_element_value(the_cib, XML_ATTR_GENERATION) : "0",
                    the_cib ? crm_element_value(the_cib, XML_ATTR_NUMUPDATES) : "0");
 
         finished = time(NULL);
         if ((finished - now) > 3) {
             crm_trace("%s operation took %lds to complete", op, (long)(finished - now));
             crm_write_blackbox(0, NULL);
         }
 
         if (op_reply == NULL && (needs_reply || local_notify)) {
             crm_err("Unexpected NULL reply to message");
             crm_log_xml_err(request, "null reply");
             needs_reply = FALSE;
             local_notify = FALSE;
         }
     }
 
     if (is_update && !cib_legacy_mode()) {
         crm_trace("Completed pre-sync update from %s/%s/%s%s",
                   originator ? originator : "local", client_name, call_id,
                   local_notify?" with local notification":"");
 
     } else if (!needs_reply || stand_alone) {
         // This was a non-originating slave update
         crm_trace("Completed slave update");
 
     } else if (cib_legacy_mode() &&
                rc == pcmk_ok && result_diff != NULL && !(call_options & cib_inhibit_bcast)) {
         gboolean broadcast = FALSE;
 
         cib_local_bcast_num++;
         crm_xml_add_int(request, F_CIB_LOCAL_NOTIFY_ID, cib_local_bcast_num);
         broadcast = send_peer_reply(request, result_diff, originator, TRUE);
 
         if (broadcast && client_id && local_notify && op_reply) {
 
             /* If we have been asked to sync the reply,
              * and a bcast msg has gone out, we queue the local notify
              * until we know the bcast message has been received */
             local_notify = FALSE;
             crm_trace("Queuing local %ssync notification for %s",
                       (call_options & cib_sync_call) ? "" : "a-", client_id);
 
             queue_local_notify(op_reply, client_id,
                                pcmk_is_set(call_options, cib_sync_call),
                                (cib_client == NULL));
             op_reply = NULL;    /* the reply is queued, so don't free here */
         }
 
     } else if (call_options & cib_discard_reply) {
         crm_trace("Caller isn't interested in reply");
 
     } else if (cib_client == NULL) {
         if (is_update == FALSE || result_diff == NULL) {
             crm_trace("Request not broadcast: R/O call");
 
         } else if (call_options & cib_inhibit_bcast) {
             crm_trace("Request not broadcast: inhibited");
 
         } else if (rc != pcmk_ok) {
             crm_trace("Request not broadcast: call failed: %s", pcmk_strerror(rc));
 
         } else {
             crm_trace("Directing reply to %s", originator);
         }
 
         send_peer_reply(op_reply, result_diff, originator, FALSE);
     }
 
     if (local_notify && client_id) {
         crm_trace("Performing local %ssync notification for %s",
                   (pcmk_is_set(call_options, cib_sync_call)? "" : "a"),
                   client_id);
         if (process == FALSE) {
             do_local_notify(request, client_id,
                             pcmk_is_set(call_options, cib_sync_call),
                             (cib_client == NULL));
         } else {
             do_local_notify(op_reply, client_id,
                             pcmk_is_set(call_options, cib_sync_call),
                             (cib_client == NULL));
         }
     }
 
     free_xml(op_reply);
     free_xml(result_diff);
 
     return;
 }
 
 static char *
 calculate_section_digest(const char *xpath, xmlNode * xml_obj)
 {
     xmlNode *xml_section = NULL;
 
     if (xml_obj == NULL) {
         return NULL;
     }
 
     xml_section = get_xpath_object(xpath, xml_obj, LOG_TRACE);
     if (xml_section == NULL) {
         return NULL;
     }
     return calculate_xml_versioned_digest(xml_section, FALSE, TRUE, CRM_FEATURE_SET); 
 
 }
 
 static int
 cib_process_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff, gboolean privileged)
 {
     xmlNode *input = NULL;
     xmlNode *output = NULL;
     xmlNode *result_cib = NULL;
     xmlNode *current_cib = NULL;
 
     int call_type = 0;
     int call_options = 0;
 
     const char *op = NULL;
     const char *section = NULL;
     const char *call_id = crm_element_value(request, F_CIB_CALLID);
 
     int rc = pcmk_ok;
     int rc2 = pcmk_ok;
 
     gboolean send_r_notify = FALSE;
     gboolean global_update = FALSE;
     gboolean config_changed = FALSE;
     gboolean manage_counters = TRUE;
 
     static mainloop_timer_t *digest_timer = NULL;
 
     char *current_nodes_digest = NULL;
     char *current_alerts_digest = NULL;
     char *current_status_digest = NULL;
     int change_section = cib_change_section_nodes | cib_change_section_alerts | cib_change_section_status;
 
     CRM_ASSERT(cib_status == pcmk_ok);
 
     if(digest_timer == NULL) {
         digest_timer = mainloop_timer_add("digester", 5000, FALSE, cib_digester_cb, NULL);
     }
 
     *reply = NULL;
     *cib_diff = NULL;
     current_cib = the_cib;
 
     /* Start processing the request... */
     op = crm_element_value(request, F_CIB_OPERATION);
     crm_element_value_int(request, F_CIB_CALLOPTS, &call_options);
     rc = cib_get_operation_id(op, &call_type);
 
     if (rc == pcmk_ok && privileged == FALSE) {
         rc = cib_op_can_run(call_type, call_options, privileged, global_update);
     }
 
     rc2 = cib_op_prepare(call_type, request, &input, &section);
     if (rc == pcmk_ok) {
         rc = rc2;
     }
 
     if (rc != pcmk_ok) {
         crm_trace("Call setup failed: %s", pcmk_strerror(rc));
         goto done;
 
     } else if (cib_op_modifies(call_type) == FALSE) {
         rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE,
                             section, request, input, FALSE, &config_changed,
                             current_cib, &result_cib, NULL, &output);
 
         CRM_CHECK(result_cib == NULL, free_xml(result_cib));
         goto done;
     }
 
     /* Handle a valid write action */
     if (pcmk__xe_attr_is_true(request, F_CIB_GLOBAL_UPDATE)) {
         /* legacy code */
         manage_counters = FALSE;
         cib__set_call_options(call_options, "call", cib_force_diff);
         crm_trace("Global update detected");
 
         CRM_CHECK(call_type == 3 || call_type == 4, crm_err("Call type: %d", call_type);
                   crm_log_xml_err(request, "bad op"));
     }
 
     if (rc == pcmk_ok) {
         ping_modified_since = TRUE;
         if (call_options & cib_inhibit_bcast) {
             /* skip */
             crm_trace("Skipping update: inhibit broadcast");
             manage_counters = FALSE;
         }
 
         if (!pcmk_is_set(call_options, cib_dryrun)
             && pcmk__str_eq(section, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
             /* Copying large CIBs accounts for a huge percentage of our CIB usage */
             cib__set_call_options(call_options, "call", cib_zero_copy);
         } else {
             cib__clear_call_options(call_options, "call", cib_zero_copy);
         }
 
         /* Calculate the hash value of the section before the change. */
         if (pcmk__str_eq(PCMK__CIB_REQUEST_REPLACE, op, pcmk__str_none)) {
             current_nodes_digest = calculate_section_digest("//" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES, current_cib);
             current_alerts_digest = calculate_section_digest("//" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_ALERTS, current_cib);
             current_status_digest = calculate_section_digest("//" XML_TAG_CIB "/" XML_CIB_TAG_STATUS, current_cib);
             crm_trace("current-digest %s:%s:%s", current_nodes_digest, current_alerts_digest, current_status_digest);
         }
 
         /* result_cib must not be modified after cib_perform_op() returns */
         rc = cib_perform_op(op, call_options, cib_op_func(call_type), FALSE,
                             section, request, input, manage_counters, &config_changed,
                             current_cib, &result_cib, cib_diff, &output);
 
         if (manage_counters == FALSE) {
             int format = 1;
             /* Legacy code
              * If the diff is NULL at this point, it's because nothing changed
              */
             if (*cib_diff) {
                 crm_element_value_int(*cib_diff, "format", &format);
             }
 
             if (format == 1) {
                 config_changed = cib_config_changed(NULL, NULL, cib_diff);
             }
         }
 
         /* Always write to disk for replace ops,
          * this also negates the need to detect ordering changes
          */
         if (pcmk__str_eq(PCMK__CIB_REQUEST_REPLACE, op, pcmk__str_none)) {
             config_changed = TRUE;
         }
     }
 
     if (rc == pcmk_ok && !pcmk_is_set(call_options, cib_dryrun)) {
         crm_trace("Activating %s->%s%s%s",
                   crm_element_value(current_cib, XML_ATTR_NUMUPDATES),
                   crm_element_value(result_cib, XML_ATTR_NUMUPDATES),
                   (pcmk_is_set(call_options, cib_zero_copy)? " zero-copy" : ""),
                   (config_changed? " changed" : ""));
         if (!pcmk_is_set(call_options, cib_zero_copy)) {
             rc = activateCibXml(result_cib, config_changed, op);
             crm_trace("Activated %s (%d)",
                       crm_element_value(current_cib, XML_ATTR_NUMUPDATES), rc);
         }
 
         if (rc == pcmk_ok && cib_internal_config_changed(*cib_diff)) {
             cib_read_config(config_hash, result_cib);
         }
 
         if (pcmk__str_eq(PCMK__CIB_REQUEST_REPLACE, op, pcmk__str_none)) {
             char *result_nodes_digest = NULL;
             char *result_alerts_digest = NULL;
             char *result_status_digest = NULL;
 
             /* Calculate the hash value of the changed section. */
             result_nodes_digest = calculate_section_digest("//" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES, result_cib);
             result_alerts_digest = calculate_section_digest("//" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_ALERTS, result_cib);
             result_status_digest = calculate_section_digest("//" XML_TAG_CIB "/" XML_CIB_TAG_STATUS, result_cib);
             crm_trace("result-digest %s:%s:%s", result_nodes_digest, result_alerts_digest, result_status_digest);
 
             if (pcmk__str_eq(current_nodes_digest, result_nodes_digest, pcmk__str_none)) {
                 change_section = change_section ^ cib_change_section_nodes;
             }
             if (pcmk__str_eq(current_alerts_digest, result_alerts_digest, pcmk__str_none)) {
                 change_section = change_section ^ cib_change_section_alerts;
             }
             if (pcmk__str_eq(current_status_digest, result_status_digest, pcmk__str_none)) {
                 change_section = change_section ^ cib_change_section_status;
             }
 
             if (change_section) {
                 send_r_notify = TRUE;
             }
             
             free(result_nodes_digest);
             free(result_alerts_digest);
             free(result_status_digest);
 
         } else if (pcmk__str_eq(PCMK__CIB_REQUEST_ERASE, op, pcmk__str_none)) {
             send_r_notify = TRUE;
         }
 
         mainloop_timer_stop(digest_timer);
         mainloop_timer_start(digest_timer);
 
     } else if (rc == -pcmk_err_schema_validation) {
         CRM_ASSERT(!pcmk_is_set(call_options, cib_zero_copy));
 
         if (output != NULL) {
             crm_log_xml_info(output, "cib:output");
             free_xml(output);
         }
 
         output = result_cib;
 
     } else {
         crm_trace("Not activating %d %d %s", rc,
                   pcmk_is_set(call_options, cib_dryrun),
                   crm_element_value(result_cib, XML_ATTR_NUMUPDATES));
         if (!pcmk_is_set(call_options, cib_zero_copy)) {
             free_xml(result_cib);
         }
     }
 
     if ((call_options & (cib_inhibit_notify|cib_dryrun)) == 0) {
         const char *client = crm_element_value(request, F_CIB_CLIENTNAME);
 
         crm_trace("Sending notifications %d",
                   pcmk_is_set(call_options, cib_dryrun));
         cib_diff_notify(call_options, client, call_id, op, input, rc, *cib_diff);
     }
 
     if (send_r_notify) {
         const char *origin = crm_element_value(request, F_ORIG);
 
         cib_replace_notify(origin, the_cib, rc, *cib_diff, change_section);
     }
 
     xml_log_patchset(LOG_TRACE, "cib:diff", *cib_diff);
   done:
     if (!pcmk_is_set(call_options, cib_discard_reply) || cib_legacy_mode()) {
         const char *caller = crm_element_value(request, F_CIB_CLIENTID);
 
         *reply = create_xml_node(NULL, "cib-reply");
         crm_xml_add(*reply, F_TYPE, T_CIB);
         crm_xml_add(*reply, F_CIB_OPERATION, op);
         crm_xml_add(*reply, F_CIB_CALLID, call_id);
         crm_xml_add(*reply, F_CIB_CLIENTID, caller);
         crm_xml_add_int(*reply, F_CIB_CALLOPTS, call_options);
         crm_xml_add_int(*reply, F_CIB_RC, rc);
 
         if (output != NULL) {
             crm_trace("Attaching reply output");
             add_message_xml(*reply, F_CIB_CALLDATA, output);
         }
 
         crm_log_xml_explicit(*reply, "cib:reply");
     }
 
     crm_trace("cleanup");
 
     if (cib_op_modifies(call_type) == FALSE && output != current_cib) {
         free_xml(output);
         output = NULL;
     }
 
     if (call_type >= 0) {
         cib_op_cleanup(call_type, call_options, &input, &output);
     }
 
     free(current_nodes_digest);
     free(current_alerts_digest);
     free(current_status_digest);
 
     crm_trace("done");
     return rc;
 }
 
 void
 cib_peer_callback(xmlNode * msg, void *private_data)
 {
     const char *reason = NULL;
     const char *originator = crm_element_value(msg, F_ORIG);
 
     if (cib_legacy_mode() && pcmk__str_eq(originator, cib_our_uname, pcmk__str_null_matches)) {
         /* message is from ourselves */
         int bcast_id = 0;
 
         if (!(crm_element_value_int(msg, F_CIB_LOCAL_NOTIFY_ID, &bcast_id))) {
             check_local_notify(bcast_id);
         }
         return;
 
     } else if (crm_peer_cache == NULL) {
         reason = "membership not established";
         goto bail;
     }
 
     if (crm_element_value(msg, F_CIB_CLIENTNAME) == NULL) {
         crm_xml_add(msg, F_CIB_CLIENTNAME, originator);
     }
 
     /* crm_log_xml_trace(msg, "Peer[inbound]"); */
     cib_process_request(msg, TRUE, NULL);
     return;
 
   bail:
     if (reason) {
         const char *seq = crm_element_value(msg, F_SEQ);
         const char *op = crm_element_value(msg, F_CIB_OPERATION);
 
         crm_warn("Discarding %s message (%s) from %s: %s", op, seq, originator, reason);
     }
 }
 
 static gboolean
 cib_force_exit(gpointer data)
 {
     crm_notice("Forcing exit!");
     terminate_cib(__func__, CRM_EX_ERROR);
     return FALSE;
 }
 
 static void
 disconnect_remote_client(gpointer key, gpointer value, gpointer user_data)
 {
     pcmk__client_t *a_client = value;
 
     crm_err("Can't disconnect client %s: Not implemented",
             pcmk__client_name(a_client));
 }
 
 void
 cib_shutdown(int nsig)
 {
     struct qb_ipcs_stats srv_stats;
 
     if (cib_shutdown_flag == FALSE) {
         int disconnects = 0;
         qb_ipcs_connection_t *c = NULL;
 
         cib_shutdown_flag = TRUE;
 
         c = qb_ipcs_connection_first_get(ipcs_rw);
         while (c != NULL) {
             qb_ipcs_connection_t *last = c;
 
             c = qb_ipcs_connection_next_get(ipcs_rw, last);
 
             crm_debug("Disconnecting r/w client %p...", last);
             qb_ipcs_disconnect(last);
             qb_ipcs_connection_unref(last);
             disconnects++;
         }
 
         c = qb_ipcs_connection_first_get(ipcs_ro);
         while (c != NULL) {
             qb_ipcs_connection_t *last = c;
 
             c = qb_ipcs_connection_next_get(ipcs_ro, last);
 
             crm_debug("Disconnecting r/o client %p...", last);
             qb_ipcs_disconnect(last);
             qb_ipcs_connection_unref(last);
             disconnects++;
         }
 
         c = qb_ipcs_connection_first_get(ipcs_shm);
         while (c != NULL) {
             qb_ipcs_connection_t *last = c;
 
             c = qb_ipcs_connection_next_get(ipcs_shm, last);
 
             crm_debug("Disconnecting non-blocking r/w client %p...", last);
             qb_ipcs_disconnect(last);
             qb_ipcs_connection_unref(last);
             disconnects++;
         }
 
         disconnects += pcmk__ipc_client_count();
 
         crm_debug("Disconnecting %d remote clients", pcmk__ipc_client_count());
         pcmk__foreach_ipc_client(disconnect_remote_client, NULL);
         crm_info("Disconnected %d clients", disconnects);
     }
 
     qb_ipcs_stats_get(ipcs_rw, &srv_stats, QB_FALSE);
 
     if (pcmk__ipc_client_count() == 0) {
         crm_info("All clients disconnected (%d)", srv_stats.active_connections);
         initiate_exit();
 
     } else {
         crm_info("Waiting on %d clients to disconnect (%d)",
                  pcmk__ipc_client_count(), srv_stats.active_connections);
     }
 }
 
 void
 initiate_exit(void)
 {
     int active = 0;
     xmlNode *leaving = NULL;
 
     active = crm_active_peers();
     if (active < 2) {
         terminate_cib(__func__, 0);
         return;
     }
 
     crm_info("Sending disconnect notification to %d peers...", active);
 
     leaving = create_xml_node(NULL, "exit-notification");
     crm_xml_add(leaving, F_TYPE, "cib");
     crm_xml_add(leaving, F_CIB_OPERATION, "cib_shutdown_req");
 
     send_cluster_message(NULL, crm_msg_cib, leaving, TRUE);
     free_xml(leaving);
 
     g_timeout_add(EXIT_ESCALATION_MS, cib_force_exit, NULL);
 }
 
 extern int remote_fd;
 extern int remote_tls_fd;
 
 /*!
  * \internal
  * \brief Close remote sockets, free the global CIB and quit
  *
  * \param[in] caller           Name of calling function (for log message)
  * \param[in] fast             If -1, skip disconnect; if positive, exit that
  */
 void
 terminate_cib(const char *caller, int fast)
 {
     crm_info("%s: Exiting%s...", caller,
              (fast > 0)? " fast" : mainloop ? " from mainloop" : "");
 
     if (remote_fd > 0) {
         close(remote_fd);
         remote_fd = 0;
     }
     if (remote_tls_fd > 0) {
         close(remote_tls_fd);
         remote_tls_fd = 0;
     }
 
     uninitializeCib();
 
     if (fast > 0) {
         /* Quit fast on error */
         pcmk__stop_based_ipc(ipcs_ro, ipcs_rw, ipcs_shm);
         crm_exit(fast);
 
     } else if ((mainloop != NULL) && g_main_loop_is_running(mainloop)) {
         /* Quit via returning from the main loop. If fast == -1, we skip the
          * disconnect here, and it will be done when the main loop returns
          * (this allows the peer status callback to avoid messing with the
          * peer caches).
          */
         if (fast == 0) {
             crm_cluster_disconnect(&crm_cluster);
         }
         g_main_loop_quit(mainloop);
 
     } else {
         /* Quit via clean exit. Even the peer status callback can disconnect
          * here, because we're not returning control to the caller. */
         crm_cluster_disconnect(&crm_cluster);
         pcmk__stop_based_ipc(ipcs_ro, ipcs_rw, ipcs_shm);
         crm_exit(CRM_EX_OK);
     }
 }
diff --git a/daemons/based/based_common.c b/daemons/based/based_common.c
index 29e006cd93..0d32e4c40a 100644
--- a/daemons/based/based_common.c
+++ b/daemons/based/based_common.c
@@ -1,362 +1,362 @@
 /*
  * Copyright 2008-2022 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/ipc.h>
 #include <crm/cluster.h>
 
 #include <crm/common/xml.h>
 
 #include <pacemaker-based.h>
 
 gboolean stand_alone = FALSE;
 
 extern int cib_perform_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff,
                                gboolean privileged);
 
 static xmlNode *
 cib_prepare_common(xmlNode * root, const char *section)
 {
     xmlNode *data = NULL;
 
     /* extract the CIB from the fragment */
     if (root == NULL) {
         return NULL;
 
     } else if (pcmk__strcase_any_of(crm_element_name(root), XML_TAG_FRAGMENT,
                                     F_CRM_DATA, F_CIB_CALLDATA, NULL)) {
         data = first_named_child(root, XML_TAG_CIB);
 
     } else {
         data = root;
     }
 
     /* grab the section specified for the command */
     if (section != NULL && data != NULL && pcmk__str_eq(crm_element_name(data), XML_TAG_CIB, pcmk__str_none)) {
         data = pcmk_find_cib_element(data, section);
     }
 
     /* crm_log_xml_trace(root, "cib:input"); */
     return data;
 }
 
 static int
 cib_prepare_none(xmlNode * request, xmlNode ** data, const char **section)
 {
     *data = NULL;
     *section = crm_element_value(request, F_CIB_SECTION);
     return pcmk_ok;
 }
 
 static int
 cib_prepare_data(xmlNode * request, xmlNode ** data, const char **section)
 {
     xmlNode *input_fragment = get_message_xml(request, F_CIB_CALLDATA);
 
     *section = crm_element_value(request, F_CIB_SECTION);
     *data = cib_prepare_common(input_fragment, *section);
     /* crm_log_xml_debug(*data, "data"); */
     return pcmk_ok;
 }
 
 static int
 cib_prepare_sync(xmlNode * request, xmlNode ** data, const char **section)
 {
     *data = NULL;
     *section = crm_element_value(request, F_CIB_SECTION);
     return pcmk_ok;
 }
 
 static int
 cib_prepare_diff(xmlNode * request, xmlNode ** data, const char **section)
 {
     xmlNode *input_fragment = NULL;
 
     *data = NULL;
     *section = NULL;
 
     if (pcmk__xe_attr_is_true(request, F_CIB_GLOBAL_UPDATE)) {
         input_fragment = get_message_xml(request, F_CIB_UPDATE_DIFF);
     } else {
         input_fragment = get_message_xml(request, F_CIB_CALLDATA);
     }
 
     CRM_CHECK(input_fragment != NULL, crm_log_xml_warn(request, "no input"));
     *data = cib_prepare_common(input_fragment, NULL);
     return pcmk_ok;
 }
 
 static int
 cib_cleanup_query(int options, xmlNode ** data, xmlNode ** output)
 {
     CRM_LOG_ASSERT(*data == NULL);
     if ((options & cib_no_children)
         || pcmk__str_eq(crm_element_name(*output), "xpath-query", pcmk__str_casei)) {
         free_xml(*output);
     }
     return pcmk_ok;
 }
 
 static int
 cib_cleanup_data(int options, xmlNode ** data, xmlNode ** output)
 {
     free_xml(*output);
     *data = NULL;
     return pcmk_ok;
 }
 
 static int
 cib_cleanup_output(int options, xmlNode ** data, xmlNode ** output)
 {
     free_xml(*output);
     return pcmk_ok;
 }
 
 static int
 cib_cleanup_none(int options, xmlNode ** data, xmlNode ** output)
 {
     CRM_LOG_ASSERT(*data == NULL);
     CRM_LOG_ASSERT(*output == NULL);
     return pcmk_ok;
 }
 
 static cib_operation_t cib_server_ops[] = {
     // Booleans are modifies_cib, needs_privileges, needs_quorum
     {
         NULL, FALSE, FALSE, FALSE,
         cib_prepare_none, cib_cleanup_none, cib_process_default
     },
     {
         PCMK__CIB_REQUEST_QUERY, FALSE, FALSE, FALSE,
         cib_prepare_none, cib_cleanup_query, cib_process_query
     },
     {
         PCMK__CIB_REQUEST_MODIFY, TRUE, TRUE, TRUE,
         cib_prepare_data, cib_cleanup_data, cib_process_modify
     },
     {
         PCMK__CIB_REQUEST_APPLY_PATCH, TRUE, TRUE, TRUE,
         cib_prepare_diff, cib_cleanup_data, cib_server_process_diff
     },
     {
         PCMK__CIB_REQUEST_REPLACE, TRUE, TRUE, TRUE,
         cib_prepare_data, cib_cleanup_data, cib_process_replace_svr
     },
     {
         PCMK__CIB_REQUEST_CREATE, TRUE, TRUE, TRUE,
         cib_prepare_data, cib_cleanup_data, cib_process_create
     },
     {
         PCMK__CIB_REQUEST_DELETE, TRUE, TRUE, TRUE,
         cib_prepare_data, cib_cleanup_data, cib_process_delete
     },
     {
         PCMK__CIB_REQUEST_SYNC_TO_ALL, FALSE, TRUE, FALSE,
         cib_prepare_sync, cib_cleanup_none, cib_process_sync
     },
     {
         PCMK__CIB_REQUEST_BUMP, TRUE, TRUE, TRUE,
         cib_prepare_none, cib_cleanup_output, cib_process_bump
     },
     {
         PCMK__CIB_REQUEST_ERASE, TRUE, TRUE, TRUE,
         cib_prepare_none, cib_cleanup_output, cib_process_erase
     },
     {
-        CRM_OP_NOOP, FALSE, FALSE, FALSE,
+        PCMK__CIB_REQUEST_NOOP, FALSE, FALSE, FALSE,
         cib_prepare_none, cib_cleanup_none, cib_process_default
     },
     {
         PCMK__CIB_REQUEST_ABS_DELETE, TRUE, TRUE, TRUE,
         cib_prepare_data, cib_cleanup_data, cib_process_delete_absolute
     },
     {
         PCMK__CIB_REQUEST_UPGRADE, TRUE, TRUE, TRUE,
         cib_prepare_none, cib_cleanup_output, cib_process_upgrade_server
     },
     {
         PCMK__CIB_REQUEST_SECONDARY, FALSE, TRUE, FALSE,
         cib_prepare_none, cib_cleanup_none, cib_process_readwrite
     },
     {
         PCMK__CIB_REQUEST_ALL_SECONDARY, FALSE, TRUE, FALSE,
         cib_prepare_none, cib_cleanup_none, cib_process_readwrite
     },
     {
         PCMK__CIB_REQUEST_SYNC_TO_ONE, FALSE, TRUE, FALSE,
         cib_prepare_sync, cib_cleanup_none, cib_process_sync_one
     },
     {
         PCMK__CIB_REQUEST_PRIMARY, TRUE, TRUE, FALSE,
         cib_prepare_data, cib_cleanup_data, cib_process_readwrite
     },
     {
         PCMK__CIB_REQUEST_IS_PRIMARY, FALSE, TRUE, FALSE,
         cib_prepare_none, cib_cleanup_none, cib_process_readwrite
     },
     {
         "cib_shutdown_req", FALSE, TRUE, FALSE,
         cib_prepare_sync, cib_cleanup_none, cib_process_shutdown_req
     },
     {
         CRM_OP_PING, FALSE, FALSE, FALSE,
         cib_prepare_none, cib_cleanup_output, cib_process_ping
     },
 };
 
 int
 cib_get_operation_id(const char *op, int *operation)
 {
     static GHashTable *operation_hash = NULL;
 
     if (operation_hash == NULL) {
         int lpc = 0;
         int max_msg_types = PCMK__NELEM(cib_server_ops);
 
         operation_hash = pcmk__strkey_table(NULL, free);
         for (lpc = 1; lpc < max_msg_types; lpc++) {
             int *value = malloc(sizeof(int));
 
             if(value) {
                 *value = lpc;
                 g_hash_table_insert(operation_hash, (gpointer) cib_server_ops[lpc].operation, value);
             }
         }
     }
 
     if (op != NULL) {
         int *value = g_hash_table_lookup(operation_hash, op);
 
         if (value) {
             *operation = *value;
             return pcmk_ok;
         }
     }
     crm_err("Operation %s is not valid", op);
     *operation = -1;
     return -EINVAL;
 }
 
 xmlNode *
 cib_msg_copy(xmlNode * msg, gboolean with_data)
 {
     int lpc = 0;
     const char *field = NULL;
     const char *value = NULL;
     xmlNode *value_struct = NULL;
 
     static const char *field_list[] = {
         F_XML_TAGNAME,
         F_TYPE,
         F_CIB_CLIENTID,
         F_CIB_CALLOPTS,
         F_CIB_CALLID,
         F_CIB_OPERATION,
         F_CIB_ISREPLY,
         F_CIB_SECTION,
         F_CIB_HOST,
         F_CIB_RC,
         F_CIB_DELEGATED,
         F_CIB_OBJID,
         F_CIB_OBJTYPE,
         F_CIB_EXISTING,
         F_CIB_SEENCOUNT,
         F_CIB_TIMEOUT,
         F_CIB_CALLBACK_TOKEN,
         F_CIB_GLOBAL_UPDATE,
         F_CIB_CLIENTNAME,
         F_CIB_USER,
         F_CIB_NOTIFY_TYPE,
         F_CIB_NOTIFY_ACTIVATE
     };
 
     static const char *data_list[] = {
         F_CIB_CALLDATA,
         F_CIB_UPDATE,
         F_CIB_UPDATE_RESULT
     };
 
     xmlNode *copy = create_xml_node(NULL, "copy");
 
     CRM_ASSERT(copy != NULL);
 
     for (lpc = 0; lpc < PCMK__NELEM(field_list); lpc++) {
         field = field_list[lpc];
         value = crm_element_value(msg, field);
         if (value != NULL) {
             crm_xml_add(copy, field, value);
         }
     }
     for (lpc = 0; with_data && lpc < PCMK__NELEM(data_list); lpc++) {
         field = data_list[lpc];
         value_struct = get_message_xml(msg, field);
         if (value_struct != NULL) {
             add_message_xml(copy, field, value_struct);
         }
     }
 
     return copy;
 }
 
 cib_op_t *
 cib_op_func(int call_type)
 {
     return &(cib_server_ops[call_type].fn);
 }
 
 gboolean
 cib_op_modifies(int call_type)
 {
     return cib_server_ops[call_type].modifies_cib;
 }
 
 int
 cib_op_can_run(int call_type, int call_options, gboolean privileged, gboolean global_update)
 {
     if (privileged == FALSE && cib_server_ops[call_type].needs_privileges) {
         /* abort */
         return -EACCES;
     }
 #if 0
     if (rc == pcmk_ok
         && stand_alone == FALSE
         && global_update == FALSE
         && (call_options & cib_quorum_override) == 0 && cib_server_ops[call_type].needs_quorum) {
         return -pcmk_err_no_quorum;
     }
 #endif
     return pcmk_ok;
 }
 
 int
 cib_op_prepare(int call_type, xmlNode * request, xmlNode ** input, const char **section)
 {
     crm_trace("Prepare %d", call_type);
     return cib_server_ops[call_type].prepare(request, input, section);
 }
 
 int
 cib_op_cleanup(int call_type, int options, xmlNode ** input, xmlNode ** output)
 {
     crm_trace("Cleanup %d", call_type);
     return cib_server_ops[call_type].cleanup(options, input, output);
 }
diff --git a/daemons/based/based_messages.c b/daemons/based/based_messages.c
index 9d665f2022..386163f89f 100644
--- a/daemons/based/based_messages.c
+++ b/daemons/based/based_messages.c
@@ -1,443 +1,440 @@
 /*
  * Copyright 2004-2022 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <time.h>
 
 #include <sys/param.h>
 #include <sys/types.h>
 
 #include <crm/crm.h>
 #include <crm/cib/internal.h>
 #include <crm/msg_xml.h>
 
 #include <crm/common/xml.h>
 #include <crm/common/ipc_internal.h>
 #include <crm/common/xml_internal.h>
 #include <crm/cluster/internal.h>
 
 #include <pacemaker-based.h>
 
 /* Maximum number of diffs to ignore while waiting for a resync */
 #define MAX_DIFF_RETRY 5
 
 gboolean cib_is_master = FALSE;
 
 xmlNode *the_cib = NULL;
 int revision_check(xmlNode * cib_update, xmlNode * cib_copy, int flags);
 int get_revision(xmlNode * xml_obj, int cur_revision);
 
 int updateList(xmlNode * local_cib, xmlNode * update_command, xmlNode * failed,
                int operation, const char *section);
 
 gboolean update_results(xmlNode * failed, xmlNode * target, const char *operation, int return_code);
 
 int cib_update_counter(xmlNode * xml_obj, const char *field, gboolean reset);
 
 int sync_our_cib(xmlNode * request, gboolean all);
 
 int
 cib_process_shutdown_req(const char *op, int options, const char *section, xmlNode * req,
                          xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                          xmlNode ** answer)
 {
     const char *host = crm_element_value(req, F_ORIG);
 
     *answer = NULL;
 
     if (crm_element_value(req, F_CIB_ISREPLY) == NULL) {
         crm_info("Peer %s is requesting to shut down", host);
         return pcmk_ok;
     }
 
     if (cib_shutdown_flag == FALSE) {
         crm_err("Peer %s mistakenly thinks we wanted to shut down", host);
         return -EINVAL;
     }
 
     crm_info("Peer %s has acknowledged our shutdown request", host);
     terminate_cib(__func__, 0);
     return pcmk_ok;
 }
 
 int
 cib_process_default(const char *op, int options, const char *section, xmlNode * req,
                     xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                     xmlNode ** answer)
 {
     int result = pcmk_ok;
 
     crm_trace("Processing \"%s\" event", op);
     *answer = NULL;
 
     if (op == NULL) {
         result = -EINVAL;
         crm_err("No operation specified");
 
-    } else if (strcasecmp(CRM_OP_NOOP, op) == 0) {
-        ;
-
-    } else {
+    } else if (strcmp(PCMK__CIB_REQUEST_NOOP, op) != 0) {
         result = -EPROTONOSUPPORT;
         crm_err("Action [%s] is not supported by the CIB manager", op);
     }
     return result;
 }
 
 int
 cib_process_readwrite(const char *op, int options, const char *section, xmlNode * req,
                       xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                       xmlNode ** answer)
 {
     int result = pcmk_ok;
 
     crm_trace("Processing \"%s\" event", op);
 
     if (pcmk__str_eq(op, PCMK__CIB_REQUEST_IS_PRIMARY, pcmk__str_none)) {
         if (cib_is_master == TRUE) {
             result = pcmk_ok;
         } else {
             result = -EPERM;
         }
         return result;
     }
 
     if (pcmk__str_eq(op, PCMK__CIB_REQUEST_PRIMARY, pcmk__str_none)) {
         if (cib_is_master == FALSE) {
             crm_info("We are now in R/W mode");
             cib_is_master = TRUE;
         } else {
             crm_debug("We are still in R/W mode");
         }
 
     } else if (cib_is_master) {
         crm_info("We are now in R/O mode");
         cib_is_master = FALSE;
     }
 
     return result;
 }
 
 /* Set to 1 when a sync is requested, incremented when a diff is ignored,
  * reset to 0 when a sync is received
  */
 static int sync_in_progress = 0;
 
 void
 send_sync_request(const char *host)
 {
     xmlNode *sync_me = create_xml_node(NULL, "sync-me");
 
     crm_info("Requesting re-sync from %s", (host? host : "all peers"));
     sync_in_progress = 1;
 
     crm_xml_add(sync_me, F_TYPE, "cib");
     crm_xml_add(sync_me, F_CIB_OPERATION, PCMK__CIB_REQUEST_SYNC_TO_ONE);
     crm_xml_add(sync_me, F_CIB_DELEGATED, cib_our_uname);
 
     send_cluster_message(host ? crm_get_peer(0, host) : NULL, crm_msg_cib, sync_me, FALSE);
     free_xml(sync_me);
 }
 
 int
 cib_process_ping(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                  xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 {
     const char *host = crm_element_value(req, F_ORIG);
     const char *seq = crm_element_value(req, F_CIB_PING_ID);
     char *digest = calculate_xml_versioned_digest(the_cib, FALSE, TRUE, CRM_FEATURE_SET);
 
     static struct qb_log_callsite *cs = NULL;
 
     crm_trace("Processing \"%s\" event %s from %s", op, seq, host);
     *answer = create_xml_node(NULL, XML_CRM_TAG_PING);
 
     crm_xml_add(*answer, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
     crm_xml_add(*answer, XML_ATTR_DIGEST, digest);
     crm_xml_add(*answer, F_CIB_PING_ID, seq);
 
     if (cs == NULL) {
         cs = qb_log_callsite_get(__func__, __FILE__, __func__, LOG_TRACE,
                                  __LINE__, crm_trace_nonlog);
     }
     if (cs && cs->targets) {
         /* Append additional detail so the reciever can log the differences */
         add_message_xml(*answer, F_CIB_CALLDATA, the_cib);
 
     } else {
         /* Always include at least the version details */
         const char *tag = TYPE(the_cib);
         xmlNode *shallow = create_xml_node(NULL, tag);
 
         copy_in_properties(shallow, the_cib);
         add_message_xml(*answer, F_CIB_CALLDATA, shallow);
         free_xml(shallow);
     }
 
     crm_info("Reporting our current digest to %s: %s for %s.%s.%s (%p %d)",
              host, digest,
              crm_element_value(existing_cib, XML_ATTR_GENERATION_ADMIN),
              crm_element_value(existing_cib, XML_ATTR_GENERATION),
              crm_element_value(existing_cib, XML_ATTR_NUMUPDATES),
              existing_cib,
              cs && cs->targets);
 
     free(digest);
 
     return pcmk_ok;
 }
 
 int
 cib_process_sync(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                  xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 {
     return sync_our_cib(req, TRUE);
 }
 
 int
 cib_process_upgrade_server(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                            xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 {
     int rc = pcmk_ok;
 
     *answer = NULL;
 
     if(crm_element_value(req, F_CIB_SCHEMA_MAX)) {
         /* The originator of an upgrade request sends it to the DC, without
          * F_CIB_SCHEMA_MAX. If an upgrade is needed, the DC re-broadcasts the
          * request with F_CIB_SCHEMA_MAX, and each node performs the upgrade
          * (and notifies its local clients) here.
          */
         return cib_process_upgrade(
             op, options, section, req, input, existing_cib, result_cib, answer);
 
     } else {
         int new_version = 0;
         int current_version = 0;
         xmlNode *scratch = copy_xml(existing_cib);
         const char *host = crm_element_value(req, F_ORIG);
         const char *value = crm_element_value(existing_cib, XML_ATTR_VALIDATION);
         const char *client_id = crm_element_value(req, F_CIB_CLIENTID);
         const char *call_opts = crm_element_value(req, F_CIB_CALLOPTS);
         const char *call_id = crm_element_value(req, F_CIB_CALLID);
 
         crm_trace("Processing \"%s\" event", op);
         if (value != NULL) {
             current_version = get_schema_version(value);
         }
 
         rc = update_validation(&scratch, &new_version, 0, TRUE, TRUE);
         if (new_version > current_version) {
             xmlNode *up = create_xml_node(NULL, __func__);
 
             rc = pcmk_ok;
             crm_notice("Upgrade request from %s verified", host);
 
             crm_xml_add(up, F_TYPE, "cib");
             crm_xml_add(up, F_CIB_OPERATION, PCMK__CIB_REQUEST_UPGRADE);
             crm_xml_add(up, F_CIB_SCHEMA_MAX, get_schema_name(new_version));
             crm_xml_add(up, F_CIB_DELEGATED, host);
             crm_xml_add(up, F_CIB_CLIENTID, client_id);
             crm_xml_add(up, F_CIB_CALLOPTS, call_opts);
             crm_xml_add(up, F_CIB_CALLID, call_id);
 
             if (cib_legacy_mode() && cib_is_master) {
                 rc = cib_process_upgrade(
                     op, options, section, up, input, existing_cib, result_cib, answer);
 
             } else {
                 send_cluster_message(NULL, crm_msg_cib, up, FALSE);
             }
 
             free_xml(up);
 
         } else if(rc == pcmk_ok) {
             rc = -pcmk_err_schema_unchanged;
         }
 
         if (rc != pcmk_ok) {
             // Notify originating peer so it can notify its local clients
             crm_node_t *origin = pcmk__search_cluster_node_cache(0, host);
 
             crm_info("Rejecting upgrade request from %s: %s "
                      CRM_XS " rc=%d peer=%s", host, pcmk_strerror(rc), rc,
                      (origin? origin->uname : "lost"));
 
             if (origin) {
                 xmlNode *up = create_xml_node(NULL, __func__);
 
                 crm_xml_add(up, F_TYPE, "cib");
                 crm_xml_add(up, F_CIB_OPERATION, PCMK__CIB_REQUEST_UPGRADE);
                 crm_xml_add(up, F_CIB_DELEGATED, host);
                 crm_xml_add(up, F_CIB_ISREPLY, host);
                 crm_xml_add(up, F_CIB_CLIENTID, client_id);
                 crm_xml_add(up, F_CIB_CALLOPTS, call_opts);
                 crm_xml_add(up, F_CIB_CALLID, call_id);
                 crm_xml_add_int(up, F_CIB_UPGRADE_RC, rc);
                 if (send_cluster_message(origin, crm_msg_cib, up, TRUE)
                     == FALSE) {
                     crm_warn("Could not send CIB upgrade result to %s", host);
                 }
                 free_xml(up);
             }
         }
         free_xml(scratch);
     }
     return rc;
 }
 
 int
 cib_process_sync_one(const char *op, int options, const char *section, xmlNode * req,
                      xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                      xmlNode ** answer)
 {
     return sync_our_cib(req, FALSE);
 }
 
 int
 cib_server_process_diff(const char *op, int options, const char *section, xmlNode * req,
                         xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                         xmlNode ** answer)
 {
     int rc = pcmk_ok;
 
     if (sync_in_progress > MAX_DIFF_RETRY) {
         /* Don't ignore diffs forever; the last request may have been lost.
          * If the diff fails, we'll ask for another full resync.
          */
         sync_in_progress = 0;
     }
 
     /* The master should never ignore a diff */
     if (sync_in_progress && !cib_is_master) {
         int diff_add_updates = 0;
         int diff_add_epoch = 0;
         int diff_add_admin_epoch = 0;
 
         int diff_del_updates = 0;
         int diff_del_epoch = 0;
         int diff_del_admin_epoch = 0;
 
         cib_diff_version_details(input,
                                  &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates,
                                  &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
 
         sync_in_progress++;
         crm_notice("Not applying diff %d.%d.%d -> %d.%d.%d (sync in progress)",
                    diff_del_admin_epoch, diff_del_epoch, diff_del_updates,
                    diff_add_admin_epoch, diff_add_epoch, diff_add_updates);
         return -pcmk_err_diff_resync;
     }
 
     rc = cib_process_diff(op, options, section, req, input, existing_cib, result_cib, answer);
     crm_trace("result: %s (%d), %s", pcmk_strerror(rc), rc, cib_is_master?"master":"slave");
 
     if (rc == -pcmk_err_diff_resync && cib_is_master == FALSE) {
         free_xml(*result_cib);
         *result_cib = NULL;
         send_sync_request(NULL);
 
     } else if (rc == -pcmk_err_diff_resync) {
         rc = -pcmk_err_diff_failed;
         if (options & cib_force_diff) {
             crm_warn("Not requesting full refresh in R/W mode");
         }
 
     } else if ((rc != pcmk_ok) && !cib_is_master && cib_legacy_mode()) {
         crm_warn("Requesting full CIB refresh because update failed: %s"
                  CRM_XS " rc=%d", pcmk_strerror(rc), rc);
         xml_log_patchset(LOG_INFO, __func__, input);
         free_xml(*result_cib);
         *result_cib = NULL;
         send_sync_request(NULL);
     }
 
     return rc;
 }
 
 int
 cib_process_replace_svr(const char *op, int options, const char *section, xmlNode * req,
                         xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                         xmlNode ** answer)
 {
     const char *tag = crm_element_name(input);
     int rc =
         cib_process_replace(op, options, section, req, input, existing_cib, result_cib, answer);
     if (rc == pcmk_ok && pcmk__str_eq(tag, XML_TAG_CIB, pcmk__str_casei)) {
         sync_in_progress = 0;
     }
     return rc;
 }
 
 int
 cib_process_delete_absolute(const char *op, int options, const char *section, xmlNode * req,
                             xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                             xmlNode ** answer)
 {
     return -EINVAL;
 }
 
 int
 sync_our_cib(xmlNode * request, gboolean all)
 {
     int result = pcmk_ok;
     char *digest = NULL;
     const char *host = crm_element_value(request, F_ORIG);
     const char *op = crm_element_value(request, F_CIB_OPERATION);
 
     xmlNode *replace_request = NULL;
 
     CRM_CHECK(the_cib != NULL, return -EINVAL);
 
     replace_request = cib_msg_copy(request, FALSE);
     CRM_CHECK(replace_request != NULL, return -EINVAL);
 
     crm_debug("Syncing CIB to %s", all ? "all peers" : host);
     if (all == FALSE && host == NULL) {
         crm_log_xml_err(request, "bad sync");
     }
 
     /* remove the "all == FALSE" condition
      *
      * sync_from was failing, the local client wasn't being notified
      *    because it didn't know it was a reply
      * setting this does not prevent the other nodes from applying it
      *    if all == TRUE
      */
     if (host != NULL) {
         crm_xml_add(replace_request, F_CIB_ISREPLY, host);
     }
     if (all) {
         xml_remove_prop(replace_request, F_CIB_HOST);
     }
 
     crm_xml_add(replace_request, F_CIB_OPERATION, PCMK__CIB_REQUEST_REPLACE);
     crm_xml_add(replace_request, "original_" F_CIB_OPERATION, op);
     pcmk__xe_set_bool_attr(replace_request, F_CIB_GLOBAL_UPDATE, true);
 
     crm_xml_add(replace_request, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
     digest = calculate_xml_versioned_digest(the_cib, FALSE, TRUE, CRM_FEATURE_SET);
     crm_xml_add(replace_request, XML_ATTR_DIGEST, digest);
 
     add_message_xml(replace_request, F_CIB_CALLDATA, the_cib);
 
     if (send_cluster_message
         (all ? NULL : crm_get_peer(0, host), crm_msg_cib, replace_request, FALSE) == FALSE) {
         result = -ENOTCONN;
     }
     free_xml(replace_request);
     free(digest);
     return result;
 }
diff --git a/include/crm/cib/internal.h b/include/crm/cib/internal.h
index 9b2dbf7aeb..ff64a6eac4 100644
--- a/include/crm/cib/internal.h
+++ b/include/crm/cib/internal.h
@@ -1,264 +1,265 @@
 /*
  * Copyright 2004-2022 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.
  */
 
 #ifndef CIB_INTERNAL__H
 #  define CIB_INTERNAL__H
 #  include <crm/cib.h>
 #  include <crm/common/ipc_internal.h>
 #  include <crm/common/output_internal.h>
 
 // Request types for CIB manager IPC/CPG
 #define PCMK__CIB_REQUEST_SECONDARY     "cib_slave"
 #define PCMK__CIB_REQUEST_ALL_SECONDARY "cib_slave_all"
 #define PCMK__CIB_REQUEST_PRIMARY       "cib_master"
 #define PCMK__CIB_REQUEST_SYNC_TO_ALL   "cib_sync"
 #define PCMK__CIB_REQUEST_SYNC_TO_ONE   "cib_sync_one"
 #define PCMK__CIB_REQUEST_IS_PRIMARY    "cib_ismaster"
 #define PCMK__CIB_REQUEST_BUMP          "cib_bump"
 #define PCMK__CIB_REQUEST_QUERY         "cib_query"
 #define PCMK__CIB_REQUEST_CREATE        "cib_create"
 #define PCMK__CIB_REQUEST_MODIFY        "cib_modify"
 #define PCMK__CIB_REQUEST_DELETE        "cib_delete"
 #define PCMK__CIB_REQUEST_ERASE         "cib_erase"
 #define PCMK__CIB_REQUEST_REPLACE       "cib_replace"
 #define PCMK__CIB_REQUEST_APPLY_PATCH   "cib_apply_diff"
 #define PCMK__CIB_REQUEST_UPGRADE       "cib_upgrade"
 #define PCMK__CIB_REQUEST_ABS_DELETE    "cib_delete_alt"
+#define PCMK__CIB_REQUEST_NOOP          "noop"
 
 #  define F_CIB_CLIENTID  "cib_clientid"
 #  define F_CIB_CALLOPTS  "cib_callopt"
 #  define F_CIB_CALLID    "cib_callid"
 #  define F_CIB_CALLDATA  "cib_calldata"
 #  define F_CIB_OPERATION "cib_op"
 #  define F_CIB_ISREPLY   "cib_isreplyto"
 #  define F_CIB_SECTION   "cib_section"
 #  define F_CIB_HOST	"cib_host"
 #  define F_CIB_RC	"cib_rc"
 #  define F_CIB_UPGRADE_RC      "cib_upgrade_rc"
 #  define F_CIB_DELEGATED	"cib_delegated_from"
 #  define F_CIB_OBJID	"cib_object"
 #  define F_CIB_OBJTYPE	"cib_object_type"
 #  define F_CIB_EXISTING	"cib_existing_object"
 #  define F_CIB_SEENCOUNT	"cib_seen"
 #  define F_CIB_TIMEOUT	"cib_timeout"
 #  define F_CIB_UPDATE	"cib_update"
 #  define F_CIB_CALLBACK_TOKEN	"cib_async_id"
 #  define F_CIB_GLOBAL_UPDATE	"cib_update"
 #  define F_CIB_UPDATE_RESULT	"cib_update_result"
 #  define F_CIB_CLIENTNAME	"cib_clientname"
 #  define F_CIB_NOTIFY_TYPE	"cib_notify_type"
 #  define F_CIB_NOTIFY_ACTIVATE	"cib_notify_activate"
 #  define F_CIB_UPDATE_DIFF	"cib_update_diff"
 #  define F_CIB_USER		"cib_user"
 #  define F_CIB_LOCAL_NOTIFY_ID	"cib_local_notify_id"
 #  define F_CIB_PING_ID         "cib_ping_id"
 #  define F_CIB_SCHEMA_MAX      "cib_schema_max"
 #  define F_CIB_CHANGE_SECTION  "cib_change_section"
 
 #  define T_CIB			"cib"
 #  define T_CIB_NOTIFY		"cib_notify"
 /* notify sub-types */
 #  define T_CIB_PRE_NOTIFY	"cib_pre_notify"
 #  define T_CIB_POST_NOTIFY	"cib_post_notify"
 #  define T_CIB_UPDATE_CONFIRM	"cib_update_confirmation"
 #  define T_CIB_REPLACE_NOTIFY	"cib_refresh_notify"
 
 enum cib_change_section_info {
     cib_change_section_none     = 0x00000000,
     cib_change_section_nodes    = 0x00000001,
     cib_change_section_alerts   = 0x00000002,
     cib_change_section_status   = 0x00000004
 };
 
 
 gboolean cib_diff_version_details(xmlNode * diff, int *admin_epoch, int *epoch, int *updates,
                                   int *_admin_epoch, int *_epoch, int *_updates);
 
 gboolean cib_read_config(GHashTable * options, xmlNode * current_cib);
 void verify_cib_options(GHashTable * options);
 gboolean cib_internal_config_changed(xmlNode * diff);
 
 typedef struct cib_notify_client_s {
     const char *event;
     const char *obj_id;         /* implement one day */
     const char *obj_type;       /* implement one day */
     void (*callback) (const char *event, xmlNode * msg);
 
 } cib_notify_client_t;
 
 typedef struct cib_callback_client_s {
     void (*callback) (xmlNode *, int, int, xmlNode *, void *);
     const char *id;
     void *user_data;
     gboolean only_success;
     struct timer_rec_s *timer;
     void (*free_func)(void *);
 } cib_callback_client_t;
 
 struct timer_rec_s {
     int call_id;
     int timeout;
     guint ref;
     cib_t *cib;
 };
 
 #define cib__set_call_options(cib_call_opts, call_for, flags_to_set) do {   \
         cib_call_opts = pcmk__set_flags_as(__func__, __LINE__,              \
             LOG_TRACE, "CIB call", (call_for), (cib_call_opts),             \
             (flags_to_set), #flags_to_set); \
     } while (0)
 
 #define cib__clear_call_options(cib_call_opts, call_for, flags_to_clear) do {  \
         cib_call_opts = pcmk__clear_flags_as(__func__, __LINE__,               \
             LOG_TRACE, "CIB call", (call_for), (cib_call_opts),                \
             (flags_to_clear), #flags_to_clear);                                \
     } while (0)
 
 typedef int (*cib_op_t) (const char *, int, const char *, xmlNode *,
                          xmlNode *, xmlNode *, xmlNode **, xmlNode **);
 
 cib_t *cib_new_variant(void);
 
 int cib_perform_op(const char *op, int call_options, cib_op_t * fn, gboolean is_query,
                    const char *section, xmlNode * req, xmlNode * input,
                    gboolean manage_counters, gboolean * config_changed,
                    xmlNode * current_cib, xmlNode ** result_cib, xmlNode ** diff,
                    xmlNode ** output);
 
 xmlNode *cib_create_op(int call_id, const char *token, const char *op, const char *host,
                        const char *section, xmlNode * data, int call_options,
                        const char *user_name);
 
 void cib_native_callback(cib_t * cib, xmlNode * msg, int call_id, int rc);
 void cib_native_notify(gpointer data, gpointer user_data);
 int cib_native_register_notification(cib_t * cib, const char *callback, int enabled);
 gboolean cib_client_register_callback(cib_t * cib, int call_id, int timeout, gboolean only_success,
                                       void *user_data, const char *callback_name,
                                       void (*callback) (xmlNode *, int, int, xmlNode *, void *));
 gboolean cib_client_register_callback_full(cib_t *cib, int call_id,
                                            int timeout, gboolean only_success,
                                            void *user_data,
                                            const char *callback_name,
                                            void (*callback)(xmlNode *, int, int,
                                                             xmlNode *, void *),
                                            void (*free_func)(void *));
 
 int cib_process_query(const char *op, int options, const char *section, xmlNode * req,
                       xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                       xmlNode ** answer);
 
 int cib_process_erase(const char *op, int options, const char *section, xmlNode * req,
                       xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                       xmlNode ** answer);
 
 int cib_process_bump(const char *op, int options, const char *section, xmlNode * req,
                      xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                      xmlNode ** answer);
 
 int cib_process_replace(const char *op, int options, const char *section, xmlNode * req,
                         xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                         xmlNode ** answer);
 
 int cib_process_create(const char *op, int options, const char *section, xmlNode * req,
                        xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                        xmlNode ** answer);
 
 int cib_process_modify(const char *op, int options, const char *section, xmlNode * req,
                        xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                        xmlNode ** answer);
 
 int cib_process_delete(const char *op, int options, const char *section, xmlNode * req,
                        xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                        xmlNode ** answer);
 
 int cib_process_diff(const char *op, int options, const char *section, xmlNode * req,
                      xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                      xmlNode ** answer);
 
 int cib_process_upgrade(const char *op, int options, const char *section, xmlNode * req,
                         xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                         xmlNode ** answer);
 
 /*!
  * \internal
  * \brief Query or modify a CIB
  *
  * \param[in]     op            PCMK__CIB_REQUEST_* operation to be performed
  * \param[in]     options       Flag set of \c cib_call_options
  * \param[in]     section       XPath to query or modify
  * \param[in]     req           unused
  * \param[in]     input         Portion of CIB to modify (used with
  *                              PCMK__CIB_REQUEST_CREATE,
  *                              PCMK__CIB_REQUEST_MODIFY, and
  *                              PCMK__CIB_REQUEST_REPLACE)
  * \param[in]     existing_cib  Input CIB (used with PCMK__CIB_REQUEST_QUERY)
  * \param[in,out] result_cib    CIB copy to make changes in (used with
  *                              PCMK__CIB_REQUEST_CREATE,
  *                              PCMK__CIB_REQUEST_MODIFY,
  *                              PCMK__CIB_REQUEST_DELETE, and
  *                              PCMK__CIB_REQUEST_REPLACE)
  * \param[out]    answer        Query result (used with PCMK__CIB_REQUEST_QUERY)
  *
  * \return Legacy Pacemaker return code
  */
 int cib_process_xpath(const char *op, int options, const char *section, xmlNode * req,
                       xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                       xmlNode ** answer);
 
 gboolean cib_config_changed(xmlNode * last, xmlNode * next, xmlNode ** diff);
 gboolean update_results(xmlNode * failed, xmlNode * target, const char *operation, int return_code);
 int cib_update_counter(xmlNode * xml_obj, const char *field, gboolean reset);
 
 int cib_internal_op(cib_t * cib, const char *op, const char *host,
                     const char *section, xmlNode * data,
                     xmlNode ** output_data, int call_options, const char *user_name);
 
 
 int cib_file_read_and_verify(const char *filename, const char *sigfile,
                              xmlNode **root);
 int cib_file_write_with_digest(xmlNode *cib_root, const char *cib_dirname,
                                const char *cib_filename);
 
 void cib__set_output(cib_t *cib, pcmk__output_t *out);
 
 cib_callback_client_t* cib__lookup_id (int call_id);
 
 /*!
  * \internal
  * \brief Connect to, query, and optionally disconnect from the CIB, returning
  *        the resulting XML object.
  *
  * \param[out] cib        If non-NULL, a pointer to where to store the CIB
  *                        connection.  In this case, it is up to the caller to
  *                        disconnect from the CIB when finished.
  * \param[out] cib_object A pointer to where to store the XML query result.
  *
  * \return A standard Pacemaker return code
  */
 int cib__signon_query(cib_t **cib, xmlNode **cib_object);
 
 int cib__clean_up_connection(cib_t **cib);
 
 int cib__update_node_attr(pcmk__output_t *out, cib_t *cib, int call_options,
                           const char *section, const char *node_uuid, const char *set_type,
                           const char *set_name, const char *attr_id, const char *attr_name,
                           const char *attr_value, const char *user_name,
                           const char *node_type);
 
 int cib__get_node_attrs(pcmk__output_t *out, cib_t *cib, const char *section,
                         const char *node_uuid, const char *set_type, const char *set_name,
                         const char *attr_id, const char *attr_name, const char *user_name,
                         xmlNode **result);
 
 int cib__delete_node_attr(pcmk__output_t *out, cib_t *cib, int options,
                           const char *section, const char *node_uuid, const char *set_type,
                           const char *set_name, const char *attr_id, const char *attr_name,
                           const char *attr_value, const char *user_name);
 
 #endif
diff --git a/lib/cib/cib_client.c b/lib/cib/cib_client.c
index 5006d0faaf..21bf54ccf2 100644
--- a/lib/cib/cib_client.c
+++ b/lib/cib/cib_client.c
@@ -1,719 +1,720 @@
 /*
  * Copyright 2004-2022 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 <crm_internal.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
 #include <pwd.h>
 
 #include <sys/stat.h>
 #include <sys/types.h>
 
 #include <glib.h>
 
 #include <crm/crm.h>
 #include <crm/cib/internal.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 
 static GHashTable *cib_op_callback_table = NULL;
 
 int cib_client_set_op_callback(cib_t * cib, void (*callback) (const xmlNode * msg, int call_id,
                                                               int rc, xmlNode * output));
 
 int cib_client_add_notify_callback(cib_t * cib, const char *event,
                                    void (*callback) (const char *event, xmlNode * msg));
 
 int cib_client_del_notify_callback(cib_t * cib, const char *event,
                                    void (*callback) (const char *event, xmlNode * msg));
 
 gint ciblib_GCompareFunc(gconstpointer a, gconstpointer b);
 
 #define op_common(cib) do {                                             \
         if(cib == NULL) {                                               \
             return -EINVAL;						\
         } else if(cib->delegate_fn == NULL) {                           \
             return -EPROTONOSUPPORT;                                    \
         }                                                               \
     } while(0)
 
 static int
 cib_client_noop(cib_t * cib, int call_options)
 {
     op_common(cib);
-    return cib_internal_op(cib, CRM_OP_NOOP, NULL, NULL, NULL, NULL, call_options, NULL);
+    return cib_internal_op(cib, PCMK__CIB_REQUEST_NOOP, NULL, NULL, NULL, NULL,
+                           call_options, NULL);
 }
 
 static int
 cib_client_ping(cib_t * cib, xmlNode ** output_data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, CRM_OP_PING, NULL, NULL, NULL, output_data, call_options, NULL);
 }
 
 static int
 cib_client_query(cib_t * cib, const char *section, xmlNode ** output_data, int call_options)
 {
     return cib->cmds->query_from(cib, NULL, section, output_data, call_options);
 }
 
 static int
 cib_client_query_from(cib_t * cib, const char *host, const char *section,
                       xmlNode ** output_data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_QUERY, host, section, NULL,
                            output_data, call_options, NULL);
 }
 
 static int
 cib_client_is_master(cib_t * cib)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_IS_PRIMARY, NULL, NULL, NULL,
                            NULL, cib_scope_local|cib_sync_call, NULL);
 }
 
 static int
 cib_client_set_slave(cib_t * cib, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_SECONDARY, NULL, NULL, NULL,
                            NULL, call_options, NULL);
 }
 
 static int
 cib_client_set_slave_all(cib_t * cib, int call_options)
 {
     return -EPROTONOSUPPORT;
 }
 
 static int
 cib_client_set_master(cib_t * cib, int call_options)
 {
     op_common(cib);
     crm_trace("Adding cib_scope_local to options");
     return cib_internal_op(cib, PCMK__CIB_REQUEST_PRIMARY, NULL, NULL, NULL,
                            NULL, call_options|cib_scope_local, NULL);
 }
 
 static int
 cib_client_bump_epoch(cib_t * cib, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_BUMP, NULL, NULL, NULL, NULL,
                            call_options, NULL);
 }
 
 static int
 cib_client_upgrade(cib_t * cib, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_UPGRADE, NULL, NULL, NULL,
                            NULL, call_options, NULL);
 }
 
 static int
 cib_client_sync(cib_t * cib, const char *section, int call_options)
 {
     return cib->cmds->sync_from(cib, NULL, section, call_options);
 }
 
 static int
 cib_client_sync_from(cib_t * cib, const char *host, const char *section, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_SYNC_TO_ALL, host, section,
                            NULL, NULL, call_options, NULL);
 }
 
 static int
 cib_client_create(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_CREATE, NULL, section, data,
                            NULL, call_options, NULL);
 }
 
 static int
 cib_client_modify(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_MODIFY, NULL, section, data,
                            NULL, call_options, NULL);
 }
 
 static int
 cib_client_update(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_MODIFY, NULL, section, data,
                            NULL, call_options, NULL);
 }
 
 static int
 cib_client_replace(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_REPLACE, NULL, section, data,
                            NULL, call_options, NULL);
 }
 
 static int
 cib_client_delete(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_DELETE, NULL, section, data,
                            NULL, call_options, NULL);
 }
 
 static int
 cib_client_delete_absolute(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_ABS_DELETE, NULL, section,
                            data, NULL, call_options, NULL);
 }
 
 static int
 cib_client_erase(cib_t * cib, xmlNode ** output_data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_ERASE, NULL, NULL, NULL,
                            output_data, call_options, NULL);
 }
 
 static void
 cib_destroy_op_callback(gpointer data)
 {
     cib_callback_client_t *blob = data;
 
     if (blob->timer && blob->timer->ref > 0) {
         g_source_remove(blob->timer->ref);
     }
     free(blob->timer);
 
     if (blob->user_data && blob->free_func) {
         blob->free_func(blob->user_data);
     }
 
     free(blob);
 }
 
 static void
 destroy_op_callback_table(void)
 {
     if (cib_op_callback_table != NULL) {
         g_hash_table_destroy(cib_op_callback_table);
         cib_op_callback_table = NULL;
     }
 }
 
 char *
 get_shadow_file(const char *suffix)
 {
     char *cib_home = NULL;
     char *fullname = NULL;
     char *name = crm_strdup_printf("shadow.%s", suffix);
     const char *dir = getenv("CIB_shadow_dir");
 
     if (dir == NULL) {
         uid_t uid = geteuid();
         struct passwd *pwent = getpwuid(uid);
         const char *user = NULL;
 
         if (pwent) {
             user = pwent->pw_name;
         } else {
             user = getenv("USER");
             crm_perror(LOG_ERR,
                        "Assuming %s because cannot get user details for user ID %d",
                        (user? user : "unprivileged user"), uid);
         }
 
         if (pcmk__strcase_any_of(user, "root", CRM_DAEMON_USER, NULL)) {
             dir = CRM_CONFIG_DIR;
 
         } else {
             const char *home = NULL;
 
             if ((home = getenv("HOME")) == NULL) {
                 if (pwent) {
                     home = pwent->pw_dir;
                 }
             }
 
             dir = pcmk__get_tmpdir();
             if (home && home[0] == '/') {
                 int rc = 0;
 
                 cib_home = crm_strdup_printf("%s/.cib", home);
 
                 rc = mkdir(cib_home, 0700);
                 if (rc < 0 && errno != EEXIST) {
                     crm_perror(LOG_ERR, "Couldn't create user-specific shadow directory: %s",
                                cib_home);
                     errno = 0;
 
                 } else {
                     dir = cib_home;
                 }
             }
         }
     }
 
     fullname = crm_strdup_printf("%s/%s", dir, name);
     free(cib_home);
     free(name);
 
     return fullname;
 }
 
 cib_t *
 cib_shadow_new(const char *shadow)
 {
     cib_t *new_cib = NULL;
     char *shadow_file = NULL;
 
     CRM_CHECK(shadow != NULL, return NULL);
 
     shadow_file = get_shadow_file(shadow);
     new_cib = cib_file_new(shadow_file);
     free(shadow_file);
 
     return new_cib;
 }
 
 cib_t *
 cib_new_no_shadow(void)
 {
     unsetenv("CIB_shadow");
     return cib_new();
 }
 
 cib_t *
 cib_new(void)
 {
     const char *value = getenv("CIB_shadow");
     int port;
 
     if (value && value[0] != 0) {
         return cib_shadow_new(value);
     }
 
     value = getenv("CIB_file");
     if (value) {
         return cib_file_new(value);
     }
 
     value = getenv("CIB_port");
     if (value) {
         gboolean encrypted = TRUE;
         const char *server = getenv("CIB_server");
         const char *user = getenv("CIB_user");
         const char *pass = getenv("CIB_passwd");
 
         /* We don't ensure port is valid (>= 0) because cib_new() currently
          * can't return NULL in practice, and introducing a NULL return here
          * could cause core dumps that would previously just cause signon()
          * failures.
          */
         pcmk__scan_port(value, &port);
 
         value = getenv("CIB_encrypted");
         if (value && crm_is_true(value) == FALSE) {
             crm_info("Disabling TLS");
             encrypted = FALSE;
         }
 
         if (user == NULL) {
             user = CRM_DAEMON_USER;
             crm_info("Defaulting to user: %s", user);
         }
 
         if (server == NULL) {
             server = "localhost";
             crm_info("Defaulting to localhost");
         }
 
         return cib_remote_new(server, user, pass, port, encrypted);
     }
 
     return cib_native_new();
 }
 
 /*!
  * \internal
  * \brief Create a generic CIB connection instance
  *
  * \return Newly allocated and initialized cib_t instance
  *
  * \note This is called by each variant's cib_*_new() function before setting
  *       variant-specific values.
  */
 cib_t *
 cib_new_variant(void)
 {
     cib_t *new_cib = NULL;
 
     new_cib = calloc(1, sizeof(cib_t));
 
     if (new_cib == NULL) {
         return NULL;
     }
 
     remove_cib_op_callback(0, TRUE); /* remove all */
 
     new_cib->call_id = 1;
     new_cib->variant = cib_undefined;
 
     new_cib->type = cib_no_connection;
     new_cib->state = cib_disconnected;
 
     new_cib->op_callback = NULL;
     new_cib->variant_opaque = NULL;
     new_cib->notify_list = NULL;
 
     /* the rest will get filled in by the variant constructor */
     new_cib->cmds = calloc(1, sizeof(cib_api_operations_t));
 
     if (new_cib->cmds == NULL) {
         free(new_cib);
         return NULL;
     }
 
     new_cib->cmds->set_op_callback = cib_client_set_op_callback;
     new_cib->cmds->add_notify_callback = cib_client_add_notify_callback;
     new_cib->cmds->del_notify_callback = cib_client_del_notify_callback;
     new_cib->cmds->register_callback = cib_client_register_callback;
     new_cib->cmds->register_callback_full = cib_client_register_callback_full;
 
     new_cib->cmds->noop = cib_client_noop;
     new_cib->cmds->ping = cib_client_ping;
     new_cib->cmds->query = cib_client_query;
     new_cib->cmds->sync = cib_client_sync;
 
     new_cib->cmds->query_from = cib_client_query_from;
     new_cib->cmds->sync_from = cib_client_sync_from;
 
     new_cib->cmds->is_master = cib_client_is_master;
     new_cib->cmds->set_master = cib_client_set_master;
     new_cib->cmds->set_slave = cib_client_set_slave;
     new_cib->cmds->set_slave_all = cib_client_set_slave_all;
 
     new_cib->cmds->upgrade = cib_client_upgrade;
     new_cib->cmds->bump_epoch = cib_client_bump_epoch;
 
     new_cib->cmds->create = cib_client_create;
     new_cib->cmds->modify = cib_client_modify;
     new_cib->cmds->update = cib_client_update;
     new_cib->cmds->replace = cib_client_replace;
     new_cib->cmds->remove = cib_client_delete;
     new_cib->cmds->erase = cib_client_erase;
 
     new_cib->cmds->delete_absolute = cib_client_delete_absolute;
 
     return new_cib;
 }
 
 void 
 cib_free_notify(cib_t *cib)
 {
 
     if (cib) {
         GList *list = cib->notify_list;
 
         while (list != NULL) {
             cib_notify_client_t *client = g_list_nth_data(list, 0);
 
             list = g_list_remove(list, client);
             free(client);
         }
         cib->notify_list = NULL;
     }
 }
 /*!
  * \brief Free all callbacks for a CIB connection
  *
  * \param[in] cib  CIB connection to clean up
  */
 void
 cib_free_callbacks(cib_t *cib)
 {
     cib_free_notify(cib);
 
     destroy_op_callback_table();
 }
 
 /*!
  * \brief Free all memory used by CIB connection
  *
  * \param[in] cib  CIB connection to delete
  */
 void
 cib_delete(cib_t *cib)
 {
     cib_free_callbacks(cib);
     if (cib) {
         cib->cmds->free(cib);
     }
 }
 
 int
 cib_client_set_op_callback(cib_t * cib, void (*callback) (const xmlNode * msg, int call_id,
                                                           int rc, xmlNode * output))
 {
     if (callback == NULL) {
         crm_info("Un-Setting operation callback");
 
     } else {
         crm_trace("Setting operation callback");
     }
     cib->op_callback = callback;
     return pcmk_ok;
 }
 
 int
 cib_client_add_notify_callback(cib_t * cib, const char *event,
                                void (*callback) (const char *event, xmlNode * msg))
 {
     GList *list_item = NULL;
     cib_notify_client_t *new_client = NULL;
 
     if (cib->variant != cib_native && cib->variant != cib_remote) {
         return -EPROTONOSUPPORT;
     }
 
     crm_trace("Adding callback for %s events (%d)", event, g_list_length(cib->notify_list));
 
     new_client = calloc(1, sizeof(cib_notify_client_t));
     new_client->event = event;
     new_client->callback = callback;
 
     list_item = g_list_find_custom(cib->notify_list, new_client, ciblib_GCompareFunc);
 
     if (list_item != NULL) {
         crm_warn("Callback already present");
         free(new_client);
         return -EINVAL;
 
     } else {
         cib->notify_list = g_list_append(cib->notify_list, new_client);
 
         cib->cmds->register_notification(cib, event, 1);
 
         crm_trace("Callback added (%d)", g_list_length(cib->notify_list));
     }
     return pcmk_ok;
 }
 
 static int 
 get_notify_list_event_count(cib_t * cib, const char *event)
 {
     GList *l = NULL;
     int count = 0;
 
     for (l = g_list_first(cib->notify_list); l; l = g_list_next(l)) {
         cib_notify_client_t *client = (cib_notify_client_t *)l->data;
         
         if (strcmp(client->event, event) == 0) {
             count++;
         }
     }
     crm_trace("event(%s) count : %d", event, count);
     return count;
 }
 
 int
 cib_client_del_notify_callback(cib_t * cib, const char *event,
                                void (*callback) (const char *event, xmlNode * msg))
 {
     GList *list_item = NULL;
     cib_notify_client_t *new_client = NULL;
 
     if (cib->variant != cib_native && cib->variant != cib_remote) {
         return -EPROTONOSUPPORT;
     }
 
     if (get_notify_list_event_count(cib, event) == 0) {
         crm_debug("The callback of the event does not exist(%s)", event);
         return pcmk_ok;
     }
 
     crm_debug("Removing callback for %s events", event);
 
     new_client = calloc(1, sizeof(cib_notify_client_t));
     new_client->event = event;
     new_client->callback = callback;
 
     list_item = g_list_find_custom(cib->notify_list, new_client, ciblib_GCompareFunc);
 
     if (list_item != NULL) {
         cib_notify_client_t *list_client = list_item->data;
 
         cib->notify_list = g_list_remove(cib->notify_list, list_client);
         free(list_client);
 
         crm_trace("Removed callback");
 
     } else {
         crm_trace("Callback not present");
     }
 
     if (get_notify_list_event_count(cib, event) == 0) {
         /* When there is not the registration of the event, the processing turns off a notice. */
         cib->cmds->register_notification(cib, event, 0);
     }
 
     free(new_client);
     return pcmk_ok;
 }
 
 gint
 ciblib_GCompareFunc(gconstpointer a, gconstpointer b)
 {
     int rc = 0;
     const cib_notify_client_t *a_client = a;
     const cib_notify_client_t *b_client = b;
 
     CRM_CHECK(a_client->event != NULL && b_client->event != NULL, return 0);
     rc = strcmp(a_client->event, b_client->event);
     if (rc == 0) {
         if (a_client->callback == b_client->callback) {
             return 0;
         } else if (((long)a_client->callback) < ((long)b_client->callback)) {
             crm_trace("callbacks for %s are not equal: %p < %p",
                       a_client->event, a_client->callback, b_client->callback);
             return -1;
         }
         crm_trace("callbacks for %s are not equal: %p > %p",
                   a_client->event, a_client->callback, b_client->callback);
         return 1;
     }
     return rc;
 }
 
 static gboolean
 cib_async_timeout_handler(gpointer data)
 {
     struct timer_rec_s *timer = data;
 
     crm_debug("Async call %d timed out after %ds", timer->call_id, timer->timeout);
     cib_native_callback(timer->cib, NULL, timer->call_id, -ETIME);
 
     /* Always return TRUE, never remove the handler
      * We do that in remove_cib_op_callback()
      */
     return TRUE;
 }
 
 gboolean
 cib_client_register_callback(cib_t * cib, int call_id, int timeout, gboolean only_success,
                              void *user_data, const char *callback_name,
                              void (*callback) (xmlNode *, int, int, xmlNode *, void *))
 {
     return cib_client_register_callback_full(cib, call_id, timeout,
                                              only_success, user_data,
                                              callback_name, callback, NULL);
 }
 
 gboolean
 cib_client_register_callback_full(cib_t *cib, int call_id, int timeout,
                                   gboolean only_success, void *user_data,
                                   const char *callback_name,
                                   void (*callback)(xmlNode *, int, int,
                                                    xmlNode *, void *),
                                   void (*free_func)(void *))
 {
     cib_callback_client_t *blob = NULL;
 
     if (call_id < 0) {
         if (only_success == FALSE) {
             callback(NULL, call_id, call_id, NULL, user_data);
         } else {
             crm_warn("CIB call failed: %s", pcmk_strerror(call_id));
         }
         if (user_data && free_func) {
             free_func(user_data);
         }
         return FALSE;
     }
 
     blob = calloc(1, sizeof(cib_callback_client_t));
     blob->id = callback_name;
     blob->only_success = only_success;
     blob->user_data = user_data;
     blob->callback = callback;
     blob->free_func = free_func;
 
     if (timeout > 0) {
         struct timer_rec_s *async_timer = NULL;
 
         async_timer = calloc(1, sizeof(struct timer_rec_s));
         blob->timer = async_timer;
 
         async_timer->cib = cib;
         async_timer->call_id = call_id;
         async_timer->timeout = timeout * 1000;
         async_timer->ref =
             g_timeout_add(async_timer->timeout, cib_async_timeout_handler, async_timer);
     }
 
     crm_trace("Adding callback %s for call %d", callback_name, call_id);
     pcmk__intkey_table_insert(cib_op_callback_table, call_id, blob);
 
     return TRUE;
 }
 
 void
 remove_cib_op_callback(int call_id, gboolean all_callbacks)
 {
     if (all_callbacks) {
         destroy_op_callback_table();
         cib_op_callback_table = pcmk__intkey_table(cib_destroy_op_callback);
     } else {
         pcmk__intkey_table_remove(cib_op_callback_table, call_id);
     }
 }
 
 int
 num_cib_op_callbacks(void)
 {
     if (cib_op_callback_table == NULL) {
         return 0;
     }
     return g_hash_table_size(cib_op_callback_table);
 }
 
 static void
 cib_dump_pending_op(gpointer key, gpointer value, gpointer user_data)
 {
     int call = GPOINTER_TO_INT(key);
     cib_callback_client_t *blob = value;
 
     crm_debug("Call %d (%s): pending", call, pcmk__s(blob->id, "without ID"));
 }
 
 void
 cib_dump_pending_callbacks(void)
 {
     if (cib_op_callback_table == NULL) {
         return;
     }
     return g_hash_table_foreach(cib_op_callback_table, cib_dump_pending_op, NULL);
 }
 
 cib_callback_client_t*
 cib__lookup_id (int call_id)
 {
     return pcmk__intkey_table_lookup(cib_op_callback_table, call_id);
 }