diff --git a/lib/cib/cib_file.c b/lib/cib/cib_file.c
index 5e5e1bdaa4..7d319e661d 100644
--- a/lib/cib/cib_file.c
+++ b/lib/cib/cib_file.c
@@ -1,907 +1,896 @@
 /*
  * Original copyright 2004 International Business Machines
  * Later changes copyright 2008-2023 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 <limits.h>
 #include <stdlib.h>
 #include <stdint.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/ipc.h>
 #include <crm/common/xml.h>
 #include <crm/common/xml_internal.h>
 
 enum cib_file_flags {
     cib_file_flag_dirty = (1 << 0),
     cib_file_flag_live  = (1 << 1),
 };
 
 typedef struct cib_file_opaque_s {
     uint32_t flags; // Group of enum cib_file_flags
     char *filename;
 } cib_file_opaque_t;
 
 #define cib_set_file_flags(cibfile, flags_to_set) do {                  \
         (cibfile)->flags = pcmk__set_flags_as(__func__, __LINE__,       \
                                               LOG_TRACE, "CIB file",    \
                                               cibfile->filename,        \
                                               (cibfile)->flags,         \
                                               (flags_to_set),           \
                                               #flags_to_set);           \
     } while (0)
 
 #define cib_clear_file_flags(cibfile, flags_to_clear) do {              \
         (cibfile)->flags = pcmk__clear_flags_as(__func__, __LINE__,     \
                                                 LOG_TRACE, "CIB file",  \
                                                 cibfile->filename,      \
                                                 (cibfile)->flags,       \
                                                 (flags_to_clear),       \
                                                 #flags_to_clear);       \
     } while (0)
 
-int cib_file_perform_op(cib_t * cib, const char *op, const char *host, const char *section,
-                        xmlNode * data, xmlNode ** output_data, int call_options);
-
 int cib_file_perform_op_delegate(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_signon(cib_t * cib, const char *name, enum cib_conn_type type);
 int cib_file_signoff(cib_t * cib);
 int cib_file_free(cib_t * cib);
 
 static int
 cib_file_inputfd(cib_t * cib)
 {
     return -EPROTONOSUPPORT;
 }
 
 static int
 cib_file_set_connection_dnotify(cib_t * cib, void (*dnotify) (gpointer user_data))
 {
     return -EPROTONOSUPPORT;
 }
 
 static int
 cib_file_register_notification(cib_t * cib, const char *callback, int enabled)
 {
     return -EPROTONOSUPPORT;
 }
 
 /*!
  * \internal
  * \brief Compare the calculated digest of an XML tree against a signature file
  *
  * \param[in] root     Root of XML tree to compare
  * \param[in] sigfile  Name of signature file containing digest to compare
  *
  * \return TRUE if digests match or signature file does not exist, else FALSE
  */
 static gboolean
 cib_file_verify_digest(xmlNode *root, const char *sigfile)
 {
     gboolean passed = FALSE;
     char *expected;
     int rc = pcmk__file_contents(sigfile, &expected);
 
     switch (rc) {
         case pcmk_rc_ok:
             if (expected == NULL) {
                 crm_err("On-disk digest at %s is empty", sigfile);
                 return FALSE;
             }
             break;
         case ENOENT:
             crm_warn("No on-disk digest present at %s", sigfile);
             return TRUE;
         default:
             crm_err("Could not read on-disk digest from %s: %s",
                     sigfile, pcmk_rc_str(rc));
             return FALSE;
     }
     passed = pcmk__verify_digest(root, expected);
     free(expected);
     return passed;
 }
 
 /*!
  * \internal
  * \brief Read an XML tree from a file and verify its digest
  *
  * \param[in]  filename  Name of XML file to read
  * \param[in]  sigfile   Name of signature file containing digest to compare
  * \param[out] root      If non-NULL, will be set to pointer to parsed XML tree
  *
  * \return 0 if file was successfully read, parsed and verified, otherwise:
  *         -errno on stat() failure,
  *         -pcmk_err_cib_corrupt if file size is 0 or XML is not parseable, or
  *         -pcmk_err_cib_modified if digests do not match
  * \note If root is non-NULL, it is the caller's responsibility to free *root on
  *       successful return.
  */
 int
 cib_file_read_and_verify(const char *filename, const char *sigfile, xmlNode **root)
 {
     int s_res;
     struct stat buf;
     char *local_sigfile = NULL;
     xmlNode *local_root = NULL;
 
     CRM_ASSERT(filename != NULL);
     if (root) {
         *root = NULL;
     }
 
     /* Verify that file exists and its size is nonzero */
     s_res = stat(filename, &buf);
     if (s_res < 0) {
         crm_perror(LOG_WARNING, "Could not verify cluster configuration file %s", filename);
         return -errno;
     } else if (buf.st_size == 0) {
         crm_warn("Cluster configuration file %s is corrupt (size is zero)", filename);
         return -pcmk_err_cib_corrupt;
     }
 
     /* Parse XML */
     local_root = filename2xml(filename);
     if (local_root == NULL) {
         crm_warn("Cluster configuration file %s is corrupt (unparseable as XML)", filename);
         return -pcmk_err_cib_corrupt;
     }
 
     /* If sigfile is not specified, use original file name plus .sig */
     if (sigfile == NULL) {
         sigfile = local_sigfile = crm_strdup_printf("%s.sig", filename);
     }
 
     /* Verify that digests match */
     if (cib_file_verify_digest(local_root, sigfile) == FALSE) {
         free(local_sigfile);
         free_xml(local_root);
         return -pcmk_err_cib_modified;
     }
 
     free(local_sigfile);
     if (root) {
         *root = local_root;
     } else {
         free_xml(local_root);
     }
     return pcmk_ok;
 }
 
 #define CIB_SERIES "cib"
 #define CIB_SERIES_MAX 100
 #define CIB_SERIES_BZIP FALSE /* Must be false because archived copies are
                                  created with hard links
                                */
 
 #define CIB_LIVE_NAME CIB_SERIES ".xml"
 
 /*!
  * \internal
  * \brief Check whether a file is the live CIB
  *
  * \param[in] filename Name of file to check
  *
  * \return TRUE if file exists and its real path is same as live CIB's
  */
 static gboolean
 cib_file_is_live(const char *filename)
 {
     gboolean same = FALSE;
 
     if (filename != NULL) {
         // Canonicalize file names for true comparison
         char *real_filename = NULL;
 
         if (pcmk__real_path(filename, &real_filename) == pcmk_rc_ok) {
             char *real_livename = NULL;
 
             if (pcmk__real_path(CRM_CONFIG_DIR "/" CIB_LIVE_NAME,
                                 &real_livename) == pcmk_rc_ok) {
                 same = !strcmp(real_filename, real_livename);
                 free(real_livename);
             }
             free(real_filename);
         }
     }
     return same;
 }
 
 /* cib_file_backup() and cib_file_write_with_digest() need to chown the
  * written files only in limited circumstances, so these variables allow
  * that to be indicated without affecting external callers
  */
 static uid_t cib_file_owner = 0;
 static uid_t cib_file_group = 0;
 static gboolean cib_do_chown = FALSE;
 
 /*!
  * \internal
  * \brief Back up a CIB
  *
  * \param[in] cib_dirname Directory containing CIB file and backups
  * \param[in] cib_filename Name (relative to cib_dirname) of CIB file to back up
  *
  * \return 0 on success, -1 on error
  */
 static int
 cib_file_backup(const char *cib_dirname, const char *cib_filename)
 {
     int rc = 0;
     unsigned int seq;
     char *cib_path = crm_strdup_printf("%s/%s", cib_dirname, cib_filename);
     char *cib_digest = crm_strdup_printf("%s.sig", cib_path);
     char *backup_path;
     char *backup_digest;
 
     // Determine backup and digest file names
     if (pcmk__read_series_sequence(cib_dirname, CIB_SERIES,
                                    &seq) != pcmk_rc_ok) {
         // @TODO maybe handle errors better ...
         seq = 0;
     }
     backup_path = pcmk__series_filename(cib_dirname, CIB_SERIES, seq,
                                         CIB_SERIES_BZIP);
     backup_digest = crm_strdup_printf("%s.sig", backup_path);
 
     /* Remove the old backups if they exist */
     unlink(backup_path);
     unlink(backup_digest);
 
     /* Back up the CIB, by hard-linking it to the backup name */
     if ((link(cib_path, backup_path) < 0) && (errno != ENOENT)) {
         crm_perror(LOG_ERR, "Could not archive %s by linking to %s",
                    cib_path, backup_path);
         rc = -1;
 
     /* Back up the CIB signature similarly */
     } else if ((link(cib_digest, backup_digest) < 0) && (errno != ENOENT)) {
         crm_perror(LOG_ERR, "Could not archive %s by linking to %s",
                    cib_digest, backup_digest);
         rc = -1;
 
     /* Update the last counter and ensure everything is sync'd to media */
     } else {
         pcmk__write_series_sequence(cib_dirname, CIB_SERIES, ++seq,
                                     CIB_SERIES_MAX);
         if (cib_do_chown) {
             int rc2;
 
             if ((chown(backup_path, cib_file_owner, cib_file_group) < 0)
                     && (errno != ENOENT)) {
                 crm_perror(LOG_ERR, "Could not set owner of %s", backup_path);
                 rc = -1;
             }
             if ((chown(backup_digest, cib_file_owner, cib_file_group) < 0)
                     && (errno != ENOENT)) {
                 crm_perror(LOG_ERR, "Could not set owner of %s", backup_digest);
                 rc = -1;
             }
             rc2 = pcmk__chown_series_sequence(cib_dirname, CIB_SERIES,
                                               cib_file_owner, cib_file_group);
             if (rc2 != pcmk_rc_ok) {
                 crm_err("Could not set owner of sequence file in %s: %s",
                         cib_dirname, pcmk_rc_str(rc2));
                 rc = -1;
             }
         }
         pcmk__sync_directory(cib_dirname);
         crm_info("Archived previous version as %s", backup_path);
     }
 
     free(cib_path);
     free(cib_digest);
     free(backup_path);
     free(backup_digest);
     return rc;
 }
 
 /*!
  * \internal
  * \brief Prepare CIB XML to be written to disk
  *
  * Set num_updates to 0, set cib-last-written to the current timestamp,
  * and strip out the status section.
  *
  * \param[in,out] root  Root of CIB XML tree
  *
  * \return void
  */
 static void
 cib_file_prepare_xml(xmlNode *root)
 {
     xmlNode *cib_status_root = NULL;
 
     /* Always write out with num_updates=0 and current last-written timestamp */
     crm_xml_add(root, XML_ATTR_NUMUPDATES, "0");
     pcmk__xe_add_last_written(root);
 
     /* Delete status section before writing to file, because
      * we discard it on startup anyway, and users get confused by it */
     cib_status_root = find_xml_node(root, XML_CIB_TAG_STATUS, TRUE);
     CRM_LOG_ASSERT(cib_status_root != NULL);
     if (cib_status_root != NULL) {
         free_xml(cib_status_root);
     }
 }
 
 /*!
  * \internal
  * \brief Write CIB to disk, along with a signature file containing its digest
  *
  * \param[in,out] cib_root      Root of XML tree to write
  * \param[in]     cib_dirname   Directory containing CIB and signature files
  * \param[in]     cib_filename  Name (relative to cib_dirname) of file to write
  *
  * \return pcmk_ok on success,
  *         pcmk_err_cib_modified if existing cib_filename doesn't match digest,
  *         pcmk_err_cib_backup if existing cib_filename couldn't be backed up,
  *         or pcmk_err_cib_save if new cib_filename couldn't be saved
  */
 int
 cib_file_write_with_digest(xmlNode *cib_root, const char *cib_dirname,
                            const char *cib_filename)
 {
     int exit_rc = pcmk_ok;
     int rc, fd;
     char *digest = NULL;
 
     /* Detect CIB version for diagnostic purposes */
     const char *epoch = crm_element_value(cib_root, XML_ATTR_GENERATION);
     const char *admin_epoch = crm_element_value(cib_root,
                                                 XML_ATTR_GENERATION_ADMIN);
 
     /* Determine full CIB and signature pathnames */
     char *cib_path = crm_strdup_printf("%s/%s", cib_dirname, cib_filename);
     char *digest_path = crm_strdup_printf("%s.sig", cib_path);
 
     /* Create temporary file name patterns for writing out CIB and signature */
     char *tmp_cib = crm_strdup_printf("%s/cib.XXXXXX", cib_dirname);
     char *tmp_digest = crm_strdup_printf("%s/cib.XXXXXX", cib_dirname);
 
     CRM_ASSERT((cib_path != NULL) && (digest_path != NULL)
                && (tmp_cib != NULL) && (tmp_digest != NULL));
 
     /* Ensure the admin didn't modify the existing CIB underneath us */
     crm_trace("Reading cluster configuration file %s", cib_path);
     rc = cib_file_read_and_verify(cib_path, NULL, NULL);
     if ((rc != pcmk_ok) && (rc != -ENOENT)) {
         crm_err("%s was manually modified while the cluster was active!",
                 cib_path);
         exit_rc = pcmk_err_cib_modified;
         goto cleanup;
     }
 
     /* Back up the existing CIB */
     if (cib_file_backup(cib_dirname, cib_filename) < 0) {
         exit_rc = pcmk_err_cib_backup;
         goto cleanup;
     }
 
     crm_debug("Writing CIB to disk");
     umask(S_IWGRP | S_IWOTH | S_IROTH);
     cib_file_prepare_xml(cib_root);
 
     /* Write the CIB to a temporary file, so we can deploy (near) atomically */
     fd = mkstemp(tmp_cib);
     if (fd < 0) {
         crm_perror(LOG_ERR, "Couldn't open temporary file %s for writing CIB",
                    tmp_cib);
         exit_rc = pcmk_err_cib_save;
         goto cleanup;
     }
 
     /* Protect the temporary file */
     if (fchmod(fd, S_IRUSR | S_IWUSR) < 0) {
         crm_perror(LOG_ERR, "Couldn't protect temporary file %s for writing CIB",
                    tmp_cib);
         exit_rc = pcmk_err_cib_save;
         goto cleanup;
     }
     if (cib_do_chown && (fchown(fd, cib_file_owner, cib_file_group) < 0)) {
         crm_perror(LOG_ERR, "Couldn't protect temporary file %s for writing CIB",
                    tmp_cib);
         exit_rc = pcmk_err_cib_save;
         goto cleanup;
     }
 
     /* Write out the CIB */
     if (write_xml_fd(cib_root, tmp_cib, fd, FALSE) <= 0) {
         crm_err("Changes couldn't be written to %s", tmp_cib);
         exit_rc = pcmk_err_cib_save;
         goto cleanup;
     }
 
     /* Calculate CIB digest */
     digest = calculate_on_disk_digest(cib_root);
     CRM_ASSERT(digest != NULL);
     crm_info("Wrote version %s.%s.0 of the CIB to disk (digest: %s)",
              (admin_epoch ? admin_epoch : "0"), (epoch ? epoch : "0"), digest);
 
     /* Write the CIB digest to a temporary file */
     fd = mkstemp(tmp_digest);
     if (fd < 0) {
         crm_perror(LOG_ERR, "Could not create temporary file for CIB digest");
         exit_rc = pcmk_err_cib_save;
         goto cleanup;
     }
     if (cib_do_chown && (fchown(fd, cib_file_owner, cib_file_group) < 0)) {
         crm_perror(LOG_ERR, "Couldn't protect temporary file %s for writing CIB",
                    tmp_cib);
         exit_rc = pcmk_err_cib_save;
         close(fd);
         goto cleanup;
     }
     rc = pcmk__write_sync(fd, digest);
     if (rc != pcmk_rc_ok) {
         crm_err("Could not write digest to %s: %s",
                 tmp_digest, pcmk_rc_str(rc));
         exit_rc = pcmk_err_cib_save;
         close(fd);
         goto cleanup;
     }
     close(fd);
     crm_debug("Wrote digest %s to disk", digest);
 
     /* Verify that what we wrote is sane */
     crm_info("Reading cluster configuration file %s (digest: %s)",
              tmp_cib, tmp_digest);
     rc = cib_file_read_and_verify(tmp_cib, tmp_digest, NULL);
     CRM_ASSERT(rc == 0);
 
     /* Rename temporary files to live, and sync directory changes to media */
     crm_debug("Activating %s", tmp_cib);
     if (rename(tmp_cib, cib_path) < 0) {
         crm_perror(LOG_ERR, "Couldn't rename %s as %s", tmp_cib, cib_path);
         exit_rc = pcmk_err_cib_save;
     }
     if (rename(tmp_digest, digest_path) < 0) {
         crm_perror(LOG_ERR, "Couldn't rename %s as %s", tmp_digest,
                    digest_path);
         exit_rc = pcmk_err_cib_save;
     }
     pcmk__sync_directory(cib_dirname);
 
   cleanup:
     free(cib_path);
     free(digest_path);
     free(digest);
     free(tmp_digest);
     free(tmp_cib);
     return exit_rc;
 }
 
 cib_t *
 cib_file_new(const char *cib_location)
 {
     cib_file_opaque_t *private = NULL;
     cib_t *cib = cib_new_variant();
 
     if (cib == NULL) {
         return NULL;
     }
 
     private = calloc(1, sizeof(cib_file_opaque_t));
 
     if (private == NULL) {
         free(cib);
         return NULL;
     }
 
     cib->variant = cib_file;
     cib->variant_opaque = private;
 
     if (cib_location == NULL) {
         cib_location = getenv("CIB_file");
         CRM_CHECK(cib_location != NULL, return NULL); // Shouldn't be possible
     }
     private->flags = 0;
     if (cib_file_is_live(cib_location)) {
         cib_set_file_flags(private, cib_file_flag_live);
         crm_trace("File %s detected as live CIB", cib_location);
     }
     private->filename = strdup(cib_location);
 
     /* assign variant specific ops */
     cib->delegate_fn = cib_file_perform_op_delegate;
     cib->cmds->signon = cib_file_signon;
     cib->cmds->signoff = cib_file_signoff;
     cib->cmds->free = cib_file_free;
     cib->cmds->inputfd = cib_file_inputfd;
 
     cib->cmds->register_notification = cib_file_register_notification;
     cib->cmds->set_connection_dnotify = cib_file_set_connection_dnotify;
 
     return cib;
 }
 
 static xmlNode *in_mem_cib = NULL;
 
 /*!
  * \internal
  * \brief Read CIB from disk and validate it against XML schema
  *
  * \param[in] filename Name of file to read CIB from
  *
  * \return pcmk_ok on success,
  *         -ENXIO if file does not exist (or stat() otherwise fails), or
  *         -pcmk_err_schema_validation if XML doesn't parse or validate
  * \note If filename is the live CIB, this will *not* verify its digest,
  *       though that functionality would be trivial to add here.
  *       Also, this will *not* verify that the file is writable,
  *       because some callers might not need to write.
  */
 static int
 load_file_cib(const char *filename)
 {
     struct stat buf;
     xmlNode *root = NULL;
 
     /* Ensure file is readable */
     if (strcmp(filename, "-") && (stat(filename, &buf) < 0)) {
         return -ENXIO;
     }
 
     /* Parse XML from file */
     root = filename2xml(filename);
     if (root == NULL) {
         return -pcmk_err_schema_validation;
     }
 
     /* Add a status section if not already present */
     if (find_xml_node(root, XML_CIB_TAG_STATUS, FALSE) == NULL) {
         create_xml_node(root, XML_CIB_TAG_STATUS);
     }
 
     /* Validate XML against its specified schema */
     if (validate_xml(root, NULL, TRUE) == FALSE) {
         const char *schema = crm_element_value(root, XML_ATTR_VALIDATION);
 
         crm_err("CIB does not validate against %s", schema);
         free_xml(root);
         return -pcmk_err_schema_validation;
     }
 
     /* Remember the parsed XML for later use */
     in_mem_cib = root;
     return pcmk_ok;
 }
 
 int
 cib_file_signon(cib_t * cib, const char *name, enum cib_conn_type type)
 {
     int rc = pcmk_ok;
     cib_file_opaque_t *private = cib->variant_opaque;
 
     if (private->filename == NULL) {
         rc = -EINVAL;
     } else {
         rc = load_file_cib(private->filename);
     }
 
     if (rc == pcmk_ok) {
         crm_debug("Opened connection to local file '%s' for %s",
                   private->filename, name);
         cib->state = cib_connected_command;
         cib->type = cib_command;
 
     } else {
         crm_info("Connection to local file '%s' for %s failed: %s\n",
                  private->filename, name, pcmk_strerror(rc));
     }
     return rc;
 }
 
 /*!
  * \internal
  * \brief Write out the in-memory CIB to a live CIB file
  *
  * param[in,out] path  Full path to file to write
  *
  * \return 0 on success, -1 on failure
  */
 static int
 cib_file_write_live(char *path)
 {
     uid_t uid = geteuid();
     struct passwd *daemon_pwent;
     char *sep = strrchr(path, '/');
     const char *cib_dirname, *cib_filename;
     int rc = 0;
 
     /* Get the desired uid/gid */
     errno = 0;
     daemon_pwent = getpwnam(CRM_DAEMON_USER);
     if (daemon_pwent == NULL) {
         crm_perror(LOG_ERR, "Could not find %s user", CRM_DAEMON_USER);
         return -1;
     }
 
     /* If we're root, we can change the ownership;
      * if we're daemon, anything we create will be OK;
      * otherwise, block access so we don't create wrong owner
      */
     if ((uid != 0) && (uid != daemon_pwent->pw_uid)) {
         crm_perror(LOG_ERR, "Must be root or %s to modify live CIB",
                    CRM_DAEMON_USER);
         return 0;
     }
 
     /* fancy footwork to separate dirname from filename
      * (we know the canonical name maps to the live CIB,
      * but the given name might be relative, or symlinked)
      */
     if (sep == NULL) { /* no directory component specified */
         cib_dirname = "./";
         cib_filename = path;
     } else if (sep == path) { /* given name is in / */
         cib_dirname = "/";
         cib_filename = path + 1;
     } else { /* typical case; split given name into parts */
         *sep = '\0';
         cib_dirname = path;
         cib_filename = sep + 1;
     }
 
     /* if we're root, we want to update the file ownership */
     if (uid == 0) {
         cib_file_owner = daemon_pwent->pw_uid;
         cib_file_group = daemon_pwent->pw_gid;
         cib_do_chown = TRUE;
     }
 
     /* write the file */
     if (cib_file_write_with_digest(in_mem_cib, cib_dirname,
                                    cib_filename) != pcmk_ok) {
         rc = -1;
     }
 
     /* turn off file ownership changes, for other callers */
     if (uid == 0) {
         cib_do_chown = FALSE;
     }
 
     /* undo fancy stuff */
     if ((sep != NULL) && (*sep == '\0')) {
         *sep = '/';
     }
 
     return rc;
 }
 
 /*!
  * \internal
  * \brief Sign-off method for CIB file variants
  *
  * This will write the file to disk if needed, and free the in-memory CIB. If
  * the file is the live CIB, it will compute and write a signature as well.
  *
  * \param[in,out] cib  CIB object to sign off
  *
  * \return pcmk_ok on success, pcmk_err_generic on failure
  * \todo This method should refuse to write the live CIB if the CIB manager is
  *       running.
  */
 int
 cib_file_signoff(cib_t * cib)
 {
     int rc = pcmk_ok;
     cib_file_opaque_t *private = cib->variant_opaque;
 
     crm_debug("Disconnecting from the CIB manager");
     cib->state = cib_disconnected;
     cib->type = cib_no_connection;
 
     /* If the in-memory CIB has been changed, write it to disk */
     if (pcmk_is_set(private->flags, cib_file_flag_dirty)) {
 
         /* If this is the live CIB, write it out with a digest */
         if (pcmk_is_set(private->flags, cib_file_flag_live)) {
             if (cib_file_write_live(private->filename) < 0) {
                 rc = pcmk_err_generic;
             }
 
         /* Otherwise, it's a simple write */
         } else {
             gboolean do_bzip = pcmk__ends_with_ext(private->filename, ".bz2");
 
             if (write_xml_file(in_mem_cib, private->filename, do_bzip) <= 0) {
                 rc = pcmk_err_generic;
             }
         }
 
         if (rc == pcmk_ok) {
             crm_info("Wrote CIB to %s", private->filename);
             cib_clear_file_flags(private, cib_file_flag_dirty);
         } else {
             crm_err("Could not write CIB to %s", private->filename);
         }
     }
 
     /* Free the in-memory CIB */
     free_xml(in_mem_cib);
     in_mem_cib = NULL;
     return rc;
 }
 
 int
 cib_file_free(cib_t * cib)
 {
     int rc = pcmk_ok;
 
     if (cib->state != cib_disconnected) {
         rc = cib_file_signoff(cib);
     }
 
     if (rc == pcmk_ok) {
         cib_file_opaque_t *private = cib->variant_opaque;
 
         free(private->filename);
         free(cib->cmds);
         free(private);
         free(cib);
 
     } else {
         fprintf(stderr, "Couldn't sign off: %d\n", rc);
     }
 
     return rc;
 }
 
 struct cib_func_entry {
     const char *op;
     gboolean read_only;
     cib_op_t fn;
 };
 
 /* *INDENT-OFF* */
 static struct cib_func_entry cib_file_ops[] = {
     { PCMK__CIB_REQUEST_QUERY,      TRUE,   cib_process_query},
     { PCMK__CIB_REQUEST_MODIFY,     FALSE,  cib_process_modify},
     { PCMK__CIB_REQUEST_APPLY_PATCH,FALSE,  cib_process_diff},
     { PCMK__CIB_REQUEST_BUMP,       FALSE,  cib_process_bump },
     { PCMK__CIB_REQUEST_REPLACE,    FALSE,  cib_process_replace},
     { PCMK__CIB_REQUEST_CREATE,     FALSE,  cib_process_create },
     { PCMK__CIB_REQUEST_DELETE,     FALSE,  cib_process_delete},
     { PCMK__CIB_REQUEST_ERASE,      FALSE,  cib_process_erase},
     { PCMK__CIB_REQUEST_UPGRADE,    FALSE,  cib_process_upgrade},
 };
 /* *INDENT-ON* */
 
-int
-cib_file_perform_op(cib_t * cib, const char *op, const char *host, const char *section,
-                    xmlNode * data, xmlNode ** output_data, int call_options)
-{
-    return cib_file_perform_op_delegate(cib, op, host, section, data, output_data, call_options,
-                                        NULL);
-}
-
 int
 cib_file_perform_op_delegate(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 rc = pcmk_ok;
     char *effective_user = NULL;
     gboolean query = FALSE;
     gboolean changed = FALSE;
     xmlNode *request = NULL;
     xmlNode *output = NULL;
     xmlNode *cib_diff = NULL;
     xmlNode *result_cib = NULL;
     cib_op_t *fn = NULL;
     int lpc = 0;
     static int max_msg_types = PCMK__NELEM(cib_file_ops);
     cib_file_opaque_t *private = cib->variant_opaque;
 
     crm_info("Handling %s operation for %s as %s",
              (op? op : "invalid"), (section? section : "entire CIB"),
              (user_name? user_name : "default user"));
 
     cib__set_call_options(call_options, "file operation",
                           cib_no_mtime|cib_inhibit_bcast|cib_scope_local);
 
     if (cib->state == cib_disconnected) {
         return -ENOTCONN;
     }
 
     if (output_data != NULL) {
         *output_data = NULL;
     }
 
     if (op == NULL) {
         return -EINVAL;
     }
 
     for (lpc = 0; lpc < max_msg_types; lpc++) {
         if (pcmk__str_eq(op, cib_file_ops[lpc].op, pcmk__str_casei)) {
             fn = &(cib_file_ops[lpc].fn);
             query = cib_file_ops[lpc].read_only;
             break;
         }
     }
 
     if (fn == NULL) {
         return -EPROTONOSUPPORT;
     }
 
     cib->call_id++;
     request = cib_create_op(cib->call_id, "dummy-token", op, host, section, data, call_options, user_name);
     if(user_name) {
         crm_xml_add(request, XML_ACL_TAG_USER, user_name);
     }
 
     /* Mirror the logic in cib_prepare_common() */
     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);
     }
 
     rc = cib_perform_op(op, call_options, fn, query,
                         section, request, data, TRUE, &changed, in_mem_cib, &result_cib, &cib_diff,
                         &output);
 
     free_xml(request);
     if (rc == -pcmk_err_schema_validation) {
         validate_xml_verbose(result_cib);
     }
 
     if (rc != pcmk_ok) {
         free_xml(result_cib);
 
     } else if (query == FALSE) {
         pcmk__output_t *out = NULL;
 
         rc = pcmk_rc2legacy(pcmk__log_output_new(&out));
         CRM_CHECK(rc == pcmk_ok, goto done);
 
         pcmk__output_set_log_level(out, LOG_DEBUG);
         rc = out->message(out, "xml-patchset", cib_diff);
         out->finish(out, pcmk_rc2exitc(rc), true, NULL);
         pcmk__output_free(out);
         rc = pcmk_ok;
 
         free_xml(in_mem_cib);
         in_mem_cib = result_cib;
         cib_set_file_flags(private, cib_file_flag_dirty);
     }
 
     if (cib->op_callback != NULL) {
         cib->op_callback(NULL, cib->call_id, rc, output);
     }
 
     if ((output_data != NULL) && (output != NULL)) {
         *output_data = (output == in_mem_cib)? copy_xml(output) : output;
     }
 
 done:
     free_xml(cib_diff);
 
     if ((output_data == NULL) && (output != in_mem_cib)) {
         /* Don't free output if we're still using it. (output_data != NULL)
          * means we may have assigned *output_data = output above.
          */
         free_xml(output);
     }
     free(effective_user);
     return rc;
 }
diff --git a/lib/cib/cib_native.c b/lib/cib/cib_native.c
index 3eec33ece1..6545f388b0 100644
--- a/lib/cib/cib_native.c
+++ b/lib/cib/cib_native.c
@@ -1,489 +1,477 @@
 /*
  * Copyright 2004 International Business Machines
  * Later changes 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>
 
 #ifndef _GNU_SOURCE
 #  define _GNU_SOURCE
 #endif
 
 #include <errno.h>
 #include <crm_internal.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
 
 #include <glib.h>
 
 #include <crm/crm.h>
 #include <crm/cib/internal.h>
 
 #include <crm/msg_xml.h>
 #include <crm/common/mainloop.h>
 
 typedef struct cib_native_opaque_s {
     char *token;
     crm_ipc_t *ipc;
     void (*dnotify_fn) (gpointer user_data);
     mainloop_io_t *source;
-
 } cib_native_opaque_t;
 
-int cib_native_perform_op(cib_t * cib, const char *op, const char *host, const char *section,
-                          xmlNode * data, xmlNode ** output_data, int call_options);
-
 int cib_native_perform_op_delegate(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_native_free(cib_t * cib);
 int cib_native_signoff(cib_t * cib);
 int cib_native_signon(cib_t * cib, const char *name, enum cib_conn_type type);
 int cib_native_signon_raw(cib_t * cib, const char *name, enum cib_conn_type type, int *event_fd);
 
 int cib_native_set_connection_dnotify(cib_t * cib, void (*dnotify) (gpointer user_data));
 
 static int
 cib_native_register_notification(cib_t *cib, const char *callback, int enabled)
 {
     int rc = pcmk_ok;
     xmlNode *notify_msg = create_xml_node(NULL, "cib-callback");
     cib_native_opaque_t *native = cib->variant_opaque;
 
     if (cib->state != cib_disconnected) {
         crm_xml_add(notify_msg, F_CIB_OPERATION, T_CIB_NOTIFY);
         crm_xml_add(notify_msg, F_CIB_NOTIFY_TYPE, callback);
         crm_xml_add_int(notify_msg, F_CIB_NOTIFY_ACTIVATE, enabled);
         rc = crm_ipc_send(native->ipc, notify_msg, crm_ipc_client_response,
                           1000 * cib->call_timeout, NULL);
         if (rc <= 0) {
             crm_trace("Notification not registered: %d", rc);
             rc = -ECOMM;
         }
     }
 
     free_xml(notify_msg);
     return rc;
 }
 
 cib_t *
 cib_native_new(void)
 {
     cib_native_opaque_t *native = NULL;
     cib_t *cib = cib_new_variant();
 
     if (cib == NULL) {
         return NULL;
     }
 
     native = calloc(1, sizeof(cib_native_opaque_t));
 
     if (native == NULL) {
         free(cib);
         return NULL;
     }
 
     cib->variant = cib_native;
     cib->variant_opaque = native;
 
     native->ipc = NULL;
     native->source = NULL;
     native->dnotify_fn = NULL;
 
     /* assign variant specific ops */
     cib->delegate_fn = cib_native_perform_op_delegate;
     cib->cmds->signon = cib_native_signon;
     cib->cmds->signon_raw = cib_native_signon_raw;
     cib->cmds->signoff = cib_native_signoff;
     cib->cmds->free = cib_native_free;
 
     cib->cmds->register_notification = cib_native_register_notification;
     cib->cmds->set_connection_dnotify = cib_native_set_connection_dnotify;
 
     return cib;
 }
 
 int
 cib_native_signon(cib_t * cib, const char *name, enum cib_conn_type type)
 {
     return cib_native_signon_raw(cib, name, type, NULL);
 }
 
 static int
 cib_native_dispatch_internal(const char *buffer, ssize_t length, gpointer userdata)
 {
     const char *type = NULL;
     xmlNode *msg = NULL;
 
     cib_t *cib = userdata;
 
     crm_trace("dispatching %p", userdata);
 
     if (cib == NULL) {
         crm_err("No CIB!");
         return 0;
     }
 
     msg = string2xml(buffer);
 
     if (msg == NULL) {
         crm_warn("Received a NULL message from the CIB manager");
         return 0;
     }
 
     /* do callbacks */
     type = crm_element_value(msg, F_TYPE);
     crm_trace("Activating %s callbacks...", type);
     crm_log_xml_explicit(msg, "cib-reply");
 
     if (pcmk__str_eq(type, T_CIB, pcmk__str_casei)) {
         cib_native_callback(cib, msg, 0, 0);
 
     } else if (pcmk__str_eq(type, T_CIB_NOTIFY, pcmk__str_casei)) {
         g_list_foreach(cib->notify_list, cib_native_notify, msg);
 
     } else {
         crm_err("Unknown message type: %s", type);
     }
 
     free_xml(msg);
     return 0;
 }
 
 static void
 cib_native_destroy(void *userdata)
 {
     cib_t *cib = userdata;
     cib_native_opaque_t *native = cib->variant_opaque;
 
     crm_trace("destroying %p", userdata);
     cib->state = cib_disconnected;
     native->source = NULL;
     native->ipc = NULL;
 
     if (native->dnotify_fn) {
         native->dnotify_fn(userdata);
     }
 }
 
 int
 cib_native_signon_raw(cib_t * cib, const char *name, enum cib_conn_type type, int *async_fd)
 {
     int rc = pcmk_ok;
     const char *channel = NULL;
     cib_native_opaque_t *native = cib->variant_opaque;
 
     struct ipc_client_callbacks cib_callbacks = {
         .dispatch = cib_native_dispatch_internal,
         .destroy = cib_native_destroy
     };
 
     cib->call_timeout = PCMK__IPC_TIMEOUT;
 
     if (type == cib_command) {
         cib->state = cib_connected_command;
         channel = PCMK__SERVER_BASED_RW;
 
     } else if (type == cib_command_nonblocking) {
         cib->state = cib_connected_command;
         channel = PCMK__SERVER_BASED_SHM;
 
     } else if (type == cib_query) {
         cib->state = cib_connected_query;
         channel = PCMK__SERVER_BASED_RO;
 
     } else {
         return -ENOTCONN;
     }
 
     crm_trace("Connecting %s channel", channel);
 
     if (async_fd != NULL) {
         native->ipc = crm_ipc_new(channel, 0);
 
         if (native->ipc && crm_ipc_connect(native->ipc)) {
             *async_fd = crm_ipc_get_fd(native->ipc);
 
         } else if (native->ipc) {
             rc = -ENOTCONN;
         }
 
     } else {
         native->source =
             mainloop_add_ipc_client(channel, G_PRIORITY_HIGH, 512 * 1024 /* 512k */ , cib,
                                     &cib_callbacks);
         native->ipc = mainloop_get_ipc_client(native->source);
     }
 
     if (rc != pcmk_ok || native->ipc == NULL || !crm_ipc_connected(native->ipc)) {
         crm_info("Could not connect to CIB manager for %s", name);
         rc = -ENOTCONN;
     }
 
     if (rc == pcmk_ok) {
         xmlNode *reply = NULL;
         xmlNode *hello = create_xml_node(NULL, "cib_command");
 
         crm_xml_add(hello, F_TYPE, T_CIB);
         crm_xml_add(hello, F_CIB_OPERATION, CRM_OP_REGISTER);
         crm_xml_add(hello, F_CIB_CLIENTNAME, name);
         crm_xml_add_int(hello, F_CIB_CALLOPTS, cib_sync_call);
 
         if (crm_ipc_send(native->ipc, hello, crm_ipc_client_response, -1, &reply) > 0) {
             const char *msg_type = crm_element_value(reply, F_CIB_OPERATION);
 
             rc = pcmk_ok;
             crm_log_xml_trace(reply, "reg-reply");
 
             if (!pcmk__str_eq(msg_type, CRM_OP_REGISTER, pcmk__str_casei)) {
                 crm_info("Reply to CIB registration message has "
                          "unknown type '%s'", msg_type);
                 rc = -EPROTO;
 
             } else {
                 native->token = crm_element_value_copy(reply, F_CIB_CLIENTID);
                 if (native->token == NULL) {
                     rc = -EPROTO;
                 }
             }
             free_xml(reply);
 
         } else {
             rc = -ECOMM;
         }
 
         free_xml(hello);
     }
 
     if (rc == pcmk_ok) {
         crm_info("Successfully connected to CIB manager for %s", name);
         return pcmk_ok;
     }
 
     crm_info("Connection to CIB manager for %s failed: %s",
              name, pcmk_strerror(rc));
     cib_native_signoff(cib);
     return rc;
 }
 
 int
 cib_native_signoff(cib_t * cib)
 {
     cib_native_opaque_t *native = cib->variant_opaque;
 
     crm_debug("Disconnecting from the CIB manager");
 
     cib_free_notify(cib);
     remove_cib_op_callback(0, TRUE);
 
     if (native->source != NULL) {
         /* Attached to mainloop */
         mainloop_del_ipc_client(native->source);
         native->source = NULL;
         native->ipc = NULL;
 
     } else if (native->ipc) {
         /* Not attached to mainloop */
         crm_ipc_t *ipc = native->ipc;
 
         native->ipc = NULL;
         crm_ipc_close(ipc);
         crm_ipc_destroy(ipc);
     }
 
     cib->state = cib_disconnected;
     cib->type = cib_no_connection;
 
     return pcmk_ok;
 }
 
 int
 cib_native_free(cib_t * cib)
 {
     int rc = pcmk_ok;
 
     if (cib->state != cib_disconnected) {
         rc = cib_native_signoff(cib);
     }
 
     if (cib->state == cib_disconnected) {
         cib_native_opaque_t *native = cib->variant_opaque;
 
         free(native->token);
         free(cib->variant_opaque);
         free(cib->cmds);
         free(cib);
     }
 
     return rc;
 }
 
-int
-cib_native_perform_op(cib_t * cib, const char *op, const char *host, const char *section,
-                      xmlNode * data, xmlNode ** output_data, int call_options)
-{
-    return cib_native_perform_op_delegate(cib, op, host, section,
-                                          data, output_data, call_options, NULL);
-}
-
 int
 cib_native_perform_op_delegate(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 rc = pcmk_ok;
     int reply_id = 0;
     enum crm_ipc_flags ipc_flags = crm_ipc_flags_none;
 
     xmlNode *op_msg = NULL;
     xmlNode *op_reply = NULL;
 
     cib_native_opaque_t *native = cib->variant_opaque;
 
     if (cib->state == cib_disconnected) {
         return -ENOTCONN;
     }
 
     if (output_data != NULL) {
         *output_data = NULL;
     }
 
     if (op == NULL) {
         crm_err("No operation specified");
         return -EINVAL;
     }
 
     if (call_options & cib_sync_call) {
         pcmk__set_ipc_flags(ipc_flags, "client", crm_ipc_client_response);
     }
 
     cib->call_id++;
     if (cib->call_id < 1) {
         cib->call_id = 1;
     }
 
     CRM_CHECK(native->token != NULL,;
         );
     op_msg =
         cib_create_op(cib->call_id, native->token, op, host, section, data, call_options,
                       user_name);
     if (op_msg == NULL) {
         return -EPROTO;
     }
 
     crm_trace("Sending %s message to the CIB manager (timeout=%ds)", op, cib->call_timeout);
     rc = crm_ipc_send(native->ipc, op_msg, ipc_flags, cib->call_timeout * 1000, &op_reply);
     free_xml(op_msg);
 
     if (rc < 0) {
         crm_err("Couldn't perform %s operation (timeout=%ds): %s (%d)", op,
                 cib->call_timeout, pcmk_strerror(rc), rc);
         rc = -ECOMM;
         goto done;
     }
 
     crm_log_xml_trace(op_reply, "Reply");
 
     if (!(call_options & cib_sync_call)) {
         crm_trace("Async call, returning %d", cib->call_id);
         CRM_CHECK(cib->call_id != 0, return -ENOMSG);
         free_xml(op_reply);
         return cib->call_id;
     }
 
     rc = pcmk_ok;
     crm_element_value_int(op_reply, F_CIB_CALLID, &reply_id);
     if (reply_id == cib->call_id) {
         xmlNode *tmp = get_message_xml(op_reply, F_CIB_CALLDATA);
 
         crm_trace("Synchronous reply %d received", reply_id);
         if (crm_element_value_int(op_reply, F_CIB_RC, &rc) != 0) {
             rc = -EPROTO;
         }
 
         if (output_data == NULL || (call_options & cib_discard_reply)) {
             crm_trace("Discarding reply");
 
         } else if (tmp != NULL) {
             *output_data = copy_xml(tmp);
         }
 
     } else if (reply_id <= 0) {
         crm_err("Received bad reply: No id set");
         crm_log_xml_err(op_reply, "Bad reply");
         rc = -ENOMSG;
         goto done;
 
     } else {
         crm_err("Received bad reply: %d (wanted %d)", reply_id, cib->call_id);
         crm_log_xml_err(op_reply, "Old reply");
         rc = -ENOMSG;
         goto done;
     }
 
     if (op_reply == NULL && cib->state == cib_disconnected) {
         rc = -ENOTCONN;
 
     } else if (rc == pcmk_ok && op_reply == NULL) {
         rc = -ETIME;
     }
 
     switch (rc) {
         case pcmk_ok:
         case -EPERM:
             break;
 
             /* This is an internal value that clients do not and should not care about */
         case -pcmk_err_diff_resync:
             rc = pcmk_ok;
             break;
 
             /* These indicate internal problems */
         case -EPROTO:
         case -ENOMSG:
             crm_err("Call failed: %s", pcmk_strerror(rc));
             if (op_reply) {
                 crm_log_xml_err(op_reply, "Invalid reply");
             }
             break;
 
         default:
             if (!pcmk__str_eq(op, PCMK__CIB_REQUEST_QUERY, pcmk__str_none)) {
                 crm_warn("Call failed: %s", pcmk_strerror(rc));
             }
     }
 
   done:
     if (!crm_ipc_connected(native->ipc)) {
         crm_err("The CIB manager disconnected");
         cib->state = cib_disconnected;
     }
 
     free_xml(op_reply);
     return rc;
 }
 
 int
 cib_native_set_connection_dnotify(cib_t * cib, void (*dnotify) (gpointer user_data))
 {
     cib_native_opaque_t *native = NULL;
 
     if (cib == NULL) {
         crm_err("No CIB!");
         return FALSE;
     }
 
     native = cib->variant_opaque;
     native->dnotify_fn = dnotify;
 
     return pcmk_ok;
 }
diff --git a/lib/cib/cib_remote.c b/lib/cib/cib_remote.c
index a32b606f7a..42591f1f82 100644
--- a/lib/cib/cib_remote.c
+++ b/lib/cib/cib_remote.c
@@ -1,625 +1,614 @@
 /*
- * Copyright 2008-2022 the Pacemaker project contributors
+ * Copyright 2008-2023 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 <netdb.h>
 #include <termios.h>
 #include <sys/socket.h>
 
 #include <glib.h>
 
 #include <crm/crm.h>
 #include <crm/cib/internal.h>
 #include <crm/msg_xml.h>
 #include <crm/common/ipc_internal.h>
 #include <crm/common/mainloop.h>
 #include <crm/common/remote_internal.h>
 #include <crm/common/output_internal.h>
 
 #ifdef HAVE_GNUTLS_GNUTLS_H
 
 #  include <gnutls/gnutls.h>
 
 #  define TLS_HANDSHAKE_TIMEOUT_MS 5000
 
 static gnutls_anon_client_credentials_t anon_cred_c;
 static gboolean remote_gnutls_credentials_init = FALSE;
 
-#else
-
-typedef void gnutls_session_t;
-
 #endif // HAVE_GNUTLS_GNUTLS_H
 
 #include <arpa/inet.h>
 
-#define DH_BITS 1024
-
 typedef struct cib_remote_opaque_s {
-    int flags;
-    int socket;
     int port;
     char *server;
     char *user;
     char *passwd;
     gboolean encrypted;
     pcmk__remote_t command;
     pcmk__remote_t callback;
     pcmk__output_t *out;
-
 } cib_remote_opaque_t;
 
 void cib_remote_connection_destroy(gpointer user_data);
 int cib_remote_callback_dispatch(gpointer user_data);
 int cib_remote_command_dispatch(gpointer user_data);
 int cib_remote_signon(cib_t * cib, const char *name, enum cib_conn_type type);
 int cib_remote_signoff(cib_t * cib);
 int cib_remote_free(cib_t * cib);
 
 int cib_remote_perform_op(cib_t * cib, const char *op, const char *host, const char *section,
                           xmlNode * data, xmlNode ** output_data, int call_options,
                           const char *name);
 
 static int
 cib_remote_inputfd(cib_t * cib)
 {
     cib_remote_opaque_t *private = cib->variant_opaque;
 
     return private->callback.tcp_socket;
 }
 
 static int
 cib_remote_set_connection_dnotify(cib_t * cib, void (*dnotify) (gpointer user_data))
 {
     return -EPROTONOSUPPORT;
 }
 
 static int
 cib_remote_register_notification(cib_t * cib, const char *callback, int enabled)
 {
     xmlNode *notify_msg = create_xml_node(NULL, "cib_command");
     cib_remote_opaque_t *private = cib->variant_opaque;
 
     crm_xml_add(notify_msg, F_CIB_OPERATION, T_CIB_NOTIFY);
     crm_xml_add(notify_msg, F_CIB_NOTIFY_TYPE, callback);
     crm_xml_add_int(notify_msg, F_CIB_NOTIFY_ACTIVATE, enabled);
     pcmk__remote_send_xml(&private->callback, notify_msg);
     free_xml(notify_msg);
     return pcmk_ok;
 }
 
 cib_t *
 cib_remote_new(const char *server, const char *user, const char *passwd, int port,
                gboolean encrypted)
 {
     cib_remote_opaque_t *private = NULL;
     cib_t *cib = cib_new_variant();
 
     if (cib == NULL) {
         return NULL;
     }
 
     private = calloc(1, sizeof(cib_remote_opaque_t));
 
     if (private == NULL) {
         free(cib);
         return NULL;
     }
 
     cib->variant = cib_remote;
     cib->variant_opaque = private;
 
     pcmk__str_update(&private->server, server);
     pcmk__str_update(&private->user, user);
     pcmk__str_update(&private->passwd, passwd);
 
     private->port = port;
     private->encrypted = encrypted;
 
     /* assign variant specific ops */
     cib->delegate_fn = cib_remote_perform_op;
     cib->cmds->signon = cib_remote_signon;
     cib->cmds->signoff = cib_remote_signoff;
     cib->cmds->free = cib_remote_free;
     cib->cmds->inputfd = cib_remote_inputfd;
 
     cib->cmds->register_notification = cib_remote_register_notification;
     cib->cmds->set_connection_dnotify = cib_remote_set_connection_dnotify;
 
     return cib;
 }
 
 static int
 cib_tls_close(cib_t * cib)
 {
     cib_remote_opaque_t *private = cib->variant_opaque;
 
 #ifdef HAVE_GNUTLS_GNUTLS_H
     if (private->encrypted) {
         if (private->command.tls_session) {
             gnutls_bye(*(private->command.tls_session), GNUTLS_SHUT_RDWR);
             gnutls_deinit(*(private->command.tls_session));
             gnutls_free(private->command.tls_session);
         }
 
         if (private->callback.tls_session) {
             gnutls_bye(*(private->callback.tls_session), GNUTLS_SHUT_RDWR);
             gnutls_deinit(*(private->callback.tls_session));
             gnutls_free(private->callback.tls_session);
         }
         private->command.tls_session = NULL;
         private->callback.tls_session = NULL;
         if (remote_gnutls_credentials_init) {
             gnutls_anon_free_client_credentials(anon_cred_c);
             gnutls_global_deinit();
             remote_gnutls_credentials_init = FALSE;
         }
     }
 #endif
 
     if (private->command.tcp_socket) {
         shutdown(private->command.tcp_socket, SHUT_RDWR);       /* no more receptions */
         close(private->command.tcp_socket);
     }
     if (private->callback.tcp_socket) {
         shutdown(private->callback.tcp_socket, SHUT_RDWR);      /* no more receptions */
         close(private->callback.tcp_socket);
     }
     private->command.tcp_socket = 0;
     private->callback.tcp_socket = 0;
 
     free(private->command.buffer);
     free(private->callback.buffer);
     private->command.buffer = NULL;
     private->callback.buffer = NULL;
 
     return 0;
 }
 
 static int
 cib_tls_signon(cib_t *cib, pcmk__remote_t *connection, gboolean event_channel)
 {
     cib_remote_opaque_t *private = cib->variant_opaque;
     int rc;
 
     xmlNode *answer = NULL;
     xmlNode *login = NULL;
 
     static struct mainloop_fd_callbacks cib_fd_callbacks = { 0, };
 
     cib_fd_callbacks.dispatch =
         event_channel ? cib_remote_callback_dispatch : cib_remote_command_dispatch;
     cib_fd_callbacks.destroy = cib_remote_connection_destroy;
 
     connection->tcp_socket = -1;
 #ifdef HAVE_GNUTLS_GNUTLS_H
     connection->tls_session = NULL;
 #endif
     rc = pcmk__connect_remote(private->server, private->port, 0, NULL,
                               &(connection->tcp_socket), NULL, NULL);
     if (rc != pcmk_rc_ok) {
         crm_info("Remote connection to %s:%d failed: %s " CRM_XS " rc=%d",
                  private->server, private->port, pcmk_rc_str(rc), rc);
         return -ENOTCONN;
     }
 
     if (private->encrypted) {
         /* initialize GnuTls lib */
 #ifdef HAVE_GNUTLS_GNUTLS_H
         if (remote_gnutls_credentials_init == FALSE) {
             crm_gnutls_global_init();
             gnutls_anon_allocate_client_credentials(&anon_cred_c);
             remote_gnutls_credentials_init = TRUE;
         }
 
         /* bind the socket to GnuTls lib */
         connection->tls_session = pcmk__new_tls_session(connection->tcp_socket,
                                                         GNUTLS_CLIENT,
                                                         GNUTLS_CRD_ANON,
                                                         anon_cred_c);
         if (connection->tls_session == NULL) {
             cib_tls_close(cib);
             return -1;
         }
 
         if (pcmk__tls_client_handshake(connection, TLS_HANDSHAKE_TIMEOUT_MS)
                 != pcmk_rc_ok) {
             crm_err("Session creation for %s:%d failed", private->server, private->port);
 
             gnutls_deinit(*connection->tls_session);
             gnutls_free(connection->tls_session);
             connection->tls_session = NULL;
             cib_tls_close(cib);
             return -1;
         }
 #else
         return -EPROTONOSUPPORT;
 #endif
     }
 
     /* login to server */
     login = create_xml_node(NULL, "cib_command");
     crm_xml_add(login, "op", "authenticate");
     crm_xml_add(login, "user", private->user);
     crm_xml_add(login, "password", private->passwd);
     crm_xml_add(login, "hidden", "password");
 
     pcmk__remote_send_xml(connection, login);
     free_xml(login);
 
     rc = pcmk_ok;
     if (pcmk__read_remote_message(connection, -1) == ENOTCONN) {
         rc = -ENOTCONN;
     }
 
     answer = pcmk__remote_message_xml(connection);
 
     crm_log_xml_trace(answer, "Reply");
     if (answer == NULL) {
         rc = -EPROTO;
 
     } else {
         /* grab the token */
         const char *msg_type = crm_element_value(answer, F_CIB_OPERATION);
         const char *tmp_ticket = crm_element_value(answer, F_CIB_CLIENTID);
 
         if (!pcmk__str_eq(msg_type, CRM_OP_REGISTER, pcmk__str_casei)) {
             crm_err("Invalid registration message: %s", msg_type);
             rc = -EPROTO;
 
         } else if (tmp_ticket == NULL) {
             rc = -EPROTO;
 
         } else {
             connection->token = strdup(tmp_ticket);
         }
     }
     free_xml(answer);
     answer = NULL;
 
     if (rc != 0) {
         cib_tls_close(cib);
         return rc;
     }
 
     crm_trace("remote client connection established");
     connection->source = mainloop_add_fd("cib-remote", G_PRIORITY_HIGH,
                                          connection->tcp_socket, cib,
                                          &cib_fd_callbacks);
     return rc;
 }
 
 void
 cib_remote_connection_destroy(gpointer user_data)
 {
     crm_err("Connection destroyed");
 #ifdef HAVE_GNUTLS_GNUTLS_H
     cib_tls_close(user_data);
 #endif
     return;
 }
 
 int
 cib_remote_command_dispatch(gpointer user_data)
 {
     int rc;
     cib_t *cib = user_data;
     cib_remote_opaque_t *private = cib->variant_opaque;
 
     rc = pcmk__read_remote_message(&private->command, -1);
 
     free(private->command.buffer);
     private->command.buffer = NULL;
     crm_err("received late reply for remote cib connection, discarding");
 
     if (rc == ENOTCONN) {
         return -1;
     }
     return 0;
 }
 
 int
 cib_remote_callback_dispatch(gpointer user_data)
 {
     int rc;
     cib_t *cib = user_data;
     cib_remote_opaque_t *private = cib->variant_opaque;
 
     xmlNode *msg = NULL;
 
     crm_info("Message on callback channel");
 
     rc = pcmk__read_remote_message(&private->callback, -1);
 
     msg = pcmk__remote_message_xml(&private->callback);
     while (msg) {
         const char *type = crm_element_value(msg, F_TYPE);
 
         crm_trace("Activating %s callbacks...", type);
 
         if (pcmk__str_eq(type, T_CIB, pcmk__str_casei)) {
             cib_native_callback(cib, msg, 0, 0);
 
         } else if (pcmk__str_eq(type, T_CIB_NOTIFY, pcmk__str_casei)) {
             g_list_foreach(cib->notify_list, cib_native_notify, msg);
 
         } else {
             crm_err("Unknown message type: %s", type);
         }
 
         free_xml(msg);
         msg = pcmk__remote_message_xml(&private->callback);
     }
 
     if (rc == ENOTCONN) {
         return -1;
     }
 
     return 0;
 }
 
 int
 cib_remote_signon(cib_t * cib, const char *name, enum cib_conn_type type)
 {
     int rc = pcmk_ok;
     cib_remote_opaque_t *private = cib->variant_opaque;
 
     if (private->passwd == NULL) {
         if (private->out == NULL) {
             /* If no pcmk__output_t is set, just assume that a text prompt
              * is good enough.
              */
             pcmk__text_prompt("Password", false, &(private->passwd));
         } else {
             private->out->prompt("Password", false, &(private->passwd));
         }
     }
 
     if (private->server == NULL || private->user == NULL) {
         rc = -EINVAL;
     }
 
     if (rc == pcmk_ok) {
         rc = cib_tls_signon(cib, &(private->command), FALSE);
     }
 
     if (rc == pcmk_ok) {
         rc = cib_tls_signon(cib, &(private->callback), TRUE);
     }
 
     if (rc == pcmk_ok) {
         xmlNode *hello =
             cib_create_op(0, private->callback.token, CRM_OP_REGISTER, NULL, NULL, NULL, 0, NULL);
         crm_xml_add(hello, F_CIB_CLIENTNAME, name);
         pcmk__remote_send_xml(&private->command, hello);
         free_xml(hello);
     }
 
     if (rc == pcmk_ok) {
         crm_info("Opened connection to %s:%d for %s",
                  private->server, private->port, name);
         cib->state = cib_connected_command;
         cib->type = cib_command;
 
     } else {
         crm_info("Connection to %s:%d for %s failed: %s\n",
                  private->server, private->port, name, pcmk_strerror(rc));
     }
 
     return rc;
 }
 
 int
 cib_remote_signoff(cib_t * cib)
 {
     int rc = pcmk_ok;
 
-    /* cib_remote_opaque_t *private = cib->variant_opaque; */
-
     crm_debug("Disconnecting from the CIB manager");
 #ifdef HAVE_GNUTLS_GNUTLS_H
     cib_tls_close(cib);
 #endif
 
     cib->state = cib_disconnected;
     cib->type = cib_no_connection;
 
     return rc;
 }
 
 int
 cib_remote_free(cib_t * cib)
 {
     int rc = pcmk_ok;
 
     crm_warn("Freeing CIB");
     if (cib->state != cib_disconnected) {
         rc = cib_remote_signoff(cib);
         if (rc == pcmk_ok) {
             cib_remote_opaque_t *private = cib->variant_opaque;
 
             free(private->server);
             free(private->user);
             free(private->passwd);
             free(cib->cmds);
             free(private);
             free(cib);
         }
     }
 
     return rc;
 }
 
 int
 cib_remote_perform_op(cib_t * cib, const char *op, const char *host, const char *section,
                       xmlNode * data, xmlNode ** output_data, int call_options, const char *name)
 {
     int rc;
     int remaining_time = 0;
     time_t start_time;
 
     xmlNode *op_msg = NULL;
     xmlNode *op_reply = NULL;
 
     cib_remote_opaque_t *private = cib->variant_opaque;
 
     if (cib->state == cib_disconnected) {
         return -ENOTCONN;
     }
 
     if (output_data != NULL) {
         *output_data = NULL;
     }
 
     if (op == NULL) {
         crm_err("No operation specified");
         return -EINVAL;
     }
 
     cib->call_id++;
     if (cib->call_id < 1) {
         cib->call_id = 1;
     }
 
     op_msg =
         cib_create_op(cib->call_id, private->callback.token, op, host, section, data, call_options,
                       NULL);
     if (op_msg == NULL) {
         return -EPROTO;
     }
 
     crm_trace("Sending %s message to the CIB manager", op);
     if (!(call_options & cib_sync_call)) {
         pcmk__remote_send_xml(&private->callback, op_msg);
     } else {
         pcmk__remote_send_xml(&private->command, op_msg);
     }
     free_xml(op_msg);
 
     if ((call_options & cib_discard_reply)) {
         crm_trace("Discarding reply");
         return pcmk_ok;
 
     } else if (!(call_options & cib_sync_call)) {
         return cib->call_id;
     }
 
     crm_trace("Waiting for a synchronous reply");
 
     start_time = time(NULL);
     remaining_time = cib->call_timeout ? cib->call_timeout : 60;
 
     rc = pcmk_rc_ok;
     while (remaining_time > 0 && (rc != ENOTCONN)) {
         int reply_id = -1;
         int msg_id = cib->call_id;
 
         rc = pcmk__read_remote_message(&private->command,
                                        remaining_time * 1000);
         op_reply = pcmk__remote_message_xml(&private->command);
 
         if (!op_reply) {
             break;
         }
 
         crm_element_value_int(op_reply, F_CIB_CALLID, &reply_id);
 
         if (reply_id == msg_id) {
             break;
 
         } else if (reply_id < msg_id) {
             crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id);
             crm_log_xml_trace(op_reply, "Old reply");
 
         } else if ((reply_id - 10000) > msg_id) {
             /* wrap-around case */
             crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id);
             crm_log_xml_trace(op_reply, "Old reply");
         } else {
             crm_err("Received a __future__ reply:" " %d (wanted %d)", reply_id, msg_id);
         }
 
         free_xml(op_reply);
         op_reply = NULL;
 
         /* wasn't the right reply, try and read some more */
         remaining_time = time(NULL) - start_time;
     }
 
     /* if(IPC_ISRCONN(native->command_channel) == FALSE) { */
     /*      crm_err("The CIB manager disconnected: %d",  */
     /*              native->command_channel->ch_status); */
     /*      cib->state = cib_disconnected; */
     /* } */
 
     if (rc == ENOTCONN) {
         crm_err("Disconnected while waiting for reply.");
         return -ENOTCONN;
     } else if (op_reply == NULL) {
         crm_err("No reply message - empty");
         return -ENOMSG;
     }
 
     crm_trace("Synchronous reply received");
 
     /* Start processing the reply... */
     if (crm_element_value_int(op_reply, F_CIB_RC, &rc) != 0) {
         rc = -EPROTO;
     }
 
     if (rc == -pcmk_err_diff_resync) {
         /* This is an internal value that clients do not and should not care about */
         rc = pcmk_ok;
     }
 
     if (rc == pcmk_ok || rc == -EPERM) {
         crm_log_xml_debug(op_reply, "passed");
 
     } else {
 /* 	} else if(rc == -ETIME) { */
         crm_err("Call failed: %s", pcmk_strerror(rc));
         crm_log_xml_warn(op_reply, "failed");
     }
 
     if (output_data == NULL) {
         /* do nothing more */
 
     } else if (!(call_options & cib_discard_reply)) {
         xmlNode *tmp = get_message_xml(op_reply, F_CIB_CALLDATA);
 
         if (tmp == NULL) {
             crm_trace("No output in reply to \"%s\" command %d", op, cib->call_id - 1);
         } else {
             *output_data = copy_xml(tmp);
         }
     }
 
     free_xml(op_reply);
 
     return rc;
 }
 
 void
 cib__set_output(cib_t *cib, pcmk__output_t *out)
 {
     cib_remote_opaque_t *private;
 
     if (cib->variant != cib_remote) {
         return;
     }
 
     private = cib->variant_opaque;
     private->out = out;
 }