1    	/*
2    	 * Copyright 2012-2026 the Pacemaker project contributors
3    	 *
4    	 * The version control history for this file may have further details.
5    	 *
6    	 * This source code is licensed under the GNU Lesser General Public License
7    	 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8    	 */
9    	
10   	#include <crm_internal.h>
11   	
12   	#include <errno.h>                  // EINVAL, ENOMEM, ENOTCONN
13   	#include <stdbool.h>                // true, bool, false
14   	#include <stdint.h>                 // uint32_t, uint64_t
15   	#include <stdlib.h>                 // NULL, free, calloc
16   	#include <string.h>                 // strdup, strcmp, strlen
17   	#include <sys/types.h>              // time_t, ssize_t
18   	#include <time.h>                   // time
19   	#include <unistd.h>                 // close
20   	
21   	#include <glib.h>                   // g_list_free_full, gpointer
22   	#include <gnutls/gnutls.h>          // gnutls_deinit, gnutls_bye
23   	#include <libxml/parser.h>          // xmlNode
24   	#include <qb/qbdefs.h>              // QB_MAX
25   	#include <qb/qblog.h>               // QB_XS
26   	
27   	#include <crm/common/actions.h>     // PCMK_DEFAULT_ACTION_TIMEOUT_MS
28   	#include <crm/common/agents.h>      // PCMK_RESOURCE_CLASS_STONITH
29   	#include <crm/common/internal.h>
30   	#include <crm/common/ipc.h>         // crm_ipc_*
31   	#include <crm/common/logging.h>     // CRM_CHECK, CRM_LOG_ASSERT
32   	#include <crm/common/mainloop.h>    // mainloop_set_trigger
33   	#include <crm/common/nvpair.h>      // hash2smartfield, xml2list
34   	#include <crm/common/options.h>     // PCMK_OPT_FENCING_WATCHDOG_TIMEOUT
35   	#include <crm/common/results.h>     // pcmk_rc_*, pcmk_rc2legacy
36   	#include <crm/common/util.h>        // crm_default_remote_port
37   	#include <crm/crm.h>                // CRM_OP_REGISTER, CRM_SYSTEM_LRMD
38   	#include <crm/fencing/internal.h>   // stonith__*
39   	#include <crm/lrmd.h>               // lrmd_t, lrmd_s, lrmd_key_value_t
40   	#include <crm/lrmd_events.h>        // lrmd_event_*
41   	#include <crm/lrmd_internal.h>      // lrmd__init_remote_key
42   	#include <crm/services.h>           // services_action_free
43   	#include <crm/services_internal.h>  // services__copy_result
44   	
45   	#define MAX_TLS_RECV_WAIT 10000
46   	
47   	static int lrmd_api_disconnect(lrmd_t * lrmd);
48   	static int lrmd_api_is_connected(lrmd_t * lrmd);
49   	
50   	/* IPC proxy functions */
51   	int lrmd_internal_proxy_send(lrmd_t * lrmd, xmlNode *msg);
52   	static void lrmd_internal_proxy_dispatch(lrmd_t *lrmd, xmlNode *msg);
53   	void lrmd_internal_set_proxy_callback(lrmd_t * lrmd, void *userdata, void (*callback)(lrmd_t *lrmd, void *userdata, xmlNode *msg));
54   	
55   	// GnuTLS client handshake timeout in seconds
56   	#define TLS_HANDSHAKE_TIMEOUT 5
57   	
58   	static void lrmd_tls_disconnect(lrmd_t * lrmd);
59   	static int global_remote_msg_id = 0;
60   	static void lrmd_tls_connection_destroy(gpointer userdata);
61   	static int add_tls_to_mainloop(lrmd_t *lrmd, bool do_api_handshake);
62   	
63   	static gnutls_datum_t remote_key = { NULL, 0 };
64   	
65   	typedef struct {
66   	    uint64_t type;
67   	    char *token;
68   	    mainloop_io_t *source;
69   	
70   	    /* IPC parameters */
71   	    crm_ipc_t *ipc;
72   	
73   	    pcmk__remote_t *remote;
74   	
75   	    /* Extra TLS parameters */
76   	    char *remote_nodename;
77   	    char *server;
78   	    int port;
79   	    pcmk__tls_t *tls;
80   	
81   	    /* while the async connection is occurring, this is the id
82   	     * of the connection timeout timer. */
83   	    int async_timer;
84   	    int sock;
85   	    /* since tls requires a round trip across the network for a
86   	     * request/reply, there are times where we just want to be able
87   	     * to send a request from the client and not wait around (or even care
88   	     * about) what the reply is. */
89   	    int expected_late_replies;
90   	    GList *pending_notify;
91   	    crm_trigger_t *process_notify;
92   	    crm_trigger_t *handshake_trigger;
93   	
94   	    lrmd_event_callback callback;
95   	
96   	    /* Internal IPC proxy msg passing for remote guests */
97   	    void (*proxy_callback)(lrmd_t *lrmd, void *userdata, xmlNode *msg);
98   	    void *proxy_callback_userdata;
99   	    char *peer_version;
100  	} lrmd_private_t;
101  	
102  	static int process_lrmd_handshake_reply(xmlNode *reply, lrmd_private_t *native);
103  	static void report_async_connection_result(lrmd_t * lrmd, int rc);
104  	
105  	static lrmd_list_t *
106  	lrmd_list_add(lrmd_list_t * head, const char *value)
107  	{
108  	    lrmd_list_t *p, *end;
109  	
110  	    p = pcmk__assert_alloc(1, sizeof(lrmd_list_t));
111  	    p->val = strdup(value);
112  	
113  	    end = head;
114  	    while (end && end->next) {
115  	        end = end->next;
116  	    }
117  	
118  	    if (end) {
119  	        end->next = p;
120  	    } else {
121  	        head = p;
122  	    }
123  	
124  	    return head;
125  	}
126  	
127  	void
128  	lrmd_list_freeall(lrmd_list_t * head)
129  	{
130  	    lrmd_list_t *p;
131  	
132  	    while (head) {
133  	        char *val = (char *)head->val;
134  	
135  	        p = head->next;
136  	        free(val);
137  	        free(head);
138  	        head = p;
139  	    }
140  	}
141  	
142  	lrmd_key_value_t *
143  	lrmd_key_value_add(lrmd_key_value_t * head, const char *key, const char *value)
144  	{
145  	    lrmd_key_value_t *p, *end;
146  	
147  	    p = pcmk__assert_alloc(1, sizeof(lrmd_key_value_t));
148  	    p->key = strdup(key);
149  	    p->value = strdup(value);
150  	
151  	    end = head;
152  	    while (end && end->next) {
153  	        end = end->next;
154  	    }
155  	
156  	    if (end) {
157  	        end->next = p;
158  	    } else {
159  	        head = p;
160  	    }
161  	
162  	    return head;
163  	}
164  	
165  	void
166  	lrmd_key_value_freeall(lrmd_key_value_t * head)
167  	{
168  	    lrmd_key_value_t *p;
169  	
170  	    while (head) {
171  	        p = head->next;
172  	        free(head->key);
173  	        free(head->value);
174  	        free(head);
175  	        head = p;
176  	    }
177  	}
178  	
179  	/*!
180  	 * \brief Create a new lrmd_event_data_t object
181  	 *
182  	 * \param[in] rsc_id       ID of resource involved in event
183  	 * \param[in] task         Action name
184  	 * \param[in] interval_ms  Action interval
185  	 *
186  	 * \return Newly allocated and initialized lrmd_event_data_t
187  	 * \note This functions asserts on memory errors, so the return value is
188  	 *       guaranteed to be non-NULL. The caller is responsible for freeing the
189  	 *       result with lrmd_free_event().
190  	 */
191  	lrmd_event_data_t *
192  	lrmd_new_event(const char *rsc_id, const char *task, guint interval_ms)
193  	{
194  	    lrmd_event_data_t *event = pcmk__assert_alloc(1, sizeof(lrmd_event_data_t));
195  	
196  	    // lrmd_event_data_t has (const char *) members that lrmd_free_event() frees
197  	    event->rsc_id = pcmk__str_copy(rsc_id);
198  	    event->op_type = pcmk__str_copy(task);
199  	    event->interval_ms = interval_ms;
200  	    return event;
201  	}
202  	
203  	lrmd_event_data_t *
204  	lrmd_copy_event(lrmd_event_data_t * event)
205  	{
206  	    lrmd_event_data_t *copy = NULL;
207  	
208  	    copy = pcmk__assert_alloc(1, sizeof(lrmd_event_data_t));
209  	
210  	    copy->type = event->type;
211  	
212  	    // lrmd_event_data_t has (const char *) members that lrmd_free_event() frees
213  	    copy->rsc_id = pcmk__str_copy(event->rsc_id);
214  	    copy->op_type = pcmk__str_copy(event->op_type);
215  	    copy->user_data = pcmk__str_copy(event->user_data);
216  	    copy->output = pcmk__str_copy(event->output);
217  	    copy->remote_nodename = pcmk__str_copy(event->remote_nodename);
218  	    copy->exit_reason = pcmk__str_copy(event->exit_reason);
219  	
220  	    copy->call_id = event->call_id;
221  	    copy->timeout = event->timeout;
222  	    copy->interval_ms = event->interval_ms;
223  	    copy->start_delay = event->start_delay;
224  	    copy->rsc_deleted = event->rsc_deleted;
225  	    copy->rc = event->rc;
226  	    copy->op_status = event->op_status;
227  	    copy->t_run = event->t_run;
228  	    copy->t_rcchange = event->t_rcchange;
229  	    copy->exec_time = event->exec_time;
230  	    copy->queue_time = event->queue_time;
231  	    copy->connection_rc = event->connection_rc;
232  	    copy->params = pcmk__str_table_dup(event->params);
233  	
234  	    return copy;
235  	}
236  	
237  	/*!
238  	 * \brief Free an executor event
239  	 *
240  	 * \param[in,out]  Executor event object to free
241  	 */
242  	void
243  	lrmd_free_event(lrmd_event_data_t *event)
244  	{
245  	    if (event == NULL) {
246  	        return;
247  	    }
248  	    // @TODO Why are these const char *?
249  	    free((void *) event->rsc_id);
250  	    free((void *) event->op_type);
251  	    free((void *) event->user_data);
252  	    free((void *) event->remote_nodename);
253  	    lrmd__reset_result(event);
254  	    g_clear_pointer(&event->params, g_hash_table_destroy);
255  	    free(event);
256  	}
257  	
258  	static void
259  	lrmd_dispatch_internal(gpointer data, gpointer user_data)
260  	{
261  	    xmlNode *msg = data;
262  	    lrmd_t *lrmd = user_data;
263  	
264  	    const char *type;
265  	    const char *proxy_session = pcmk__xe_get(msg, PCMK__XA_LRMD_IPC_SESSION);
266  	    lrmd_private_t *native = lrmd->lrmd_private;
267  	    lrmd_event_data_t event = { 0, };
268  	
269  	    if (proxy_session != NULL) {
270  	        /* this is proxy business */
271  	        lrmd_internal_proxy_dispatch(lrmd, msg);
272  	        return;
273  	    } else if (!native->callback) {
274  	        /* no callback set */
275  	        pcmk__trace("notify event received but client has not set callback");
276  	        return;
277  	    }
278  	
279  	    event.remote_nodename = native->remote_nodename;
280  	    type = pcmk__xe_get(msg, PCMK__XA_LRMD_OP);
281  	    pcmk__xe_get_int(msg, PCMK__XA_LRMD_CALLID, &event.call_id);
282  	    event.rsc_id = pcmk__xe_get(msg, PCMK__XA_LRMD_RSC_ID);
283  	
284  	    if (pcmk__str_eq(type, LRMD_OP_RSC_REG, pcmk__str_none)) {
285  	        event.type = lrmd_event_register;
286  	    } else if (pcmk__str_eq(type, LRMD_OP_RSC_UNREG, pcmk__str_none)) {
287  	        event.type = lrmd_event_unregister;
288  	    } else if (pcmk__str_eq(type, LRMD_OP_RSC_EXEC, pcmk__str_none)) {
289  	        int rc = 0;
290  	        int exec_time = 0;
291  	        int queue_time = 0;
292  	
293  	        pcmk__xe_get_int(msg, PCMK__XA_LRMD_TIMEOUT, &event.timeout);
294  	        pcmk__xe_get_guint(msg, PCMK__XA_LRMD_RSC_INTERVAL, &event.interval_ms);
295  	        pcmk__xe_get_int(msg, PCMK__XA_LRMD_RSC_START_DELAY,
296  	                         &event.start_delay);
297  	
298  	        pcmk__xe_get_int(msg, PCMK__XA_LRMD_EXEC_RC, &rc);
299  	        event.rc = (enum ocf_exitcode) rc;
300  	
301  	        pcmk__xe_get_int(msg, PCMK__XA_LRMD_EXEC_OP_STATUS, &event.op_status);
302  	        pcmk__xe_get_int(msg, PCMK__XA_LRMD_RSC_DELETED, &event.rsc_deleted);
303  	
304  	        pcmk__xe_get_time(msg, PCMK__XA_LRMD_RUN_TIME, &event.t_run);
305  	        pcmk__xe_get_time(msg, PCMK__XA_LRMD_RCCHANGE_TIME, &event.t_rcchange);
306  	
307  	        pcmk__xe_get_int(msg, PCMK__XA_LRMD_EXEC_TIME, &exec_time);
308  	        CRM_LOG_ASSERT(exec_time >= 0);
309  	        event.exec_time = QB_MAX(0, exec_time);
310  	
311  	        pcmk__xe_get_int(msg, PCMK__XA_LRMD_QUEUE_TIME, &queue_time);
312  	        event.queue_time = QB_MAX(0, queue_time);
313  	
314  	        event.op_type = pcmk__xe_get(msg, PCMK__XA_LRMD_RSC_ACTION);
315  	        event.user_data = pcmk__xe_get(msg, PCMK__XA_LRMD_RSC_USERDATA_STR);
316  	        event.type = lrmd_event_exec_complete;
317  	
318  	        /* output and exit_reason may be freed by a callback */
319  	        event.output = pcmk__xe_get_copy(msg, PCMK__XA_LRMD_RSC_OUTPUT);
320  	        lrmd__set_result(&event, event.rc, event.op_status,
321  	                         pcmk__xe_get(msg, PCMK__XA_LRMD_RSC_EXIT_REASON));
322  	
323  	        event.params = xml2list(msg);
324  	    } else if (pcmk__str_eq(type, LRMD_OP_NEW_CLIENT, pcmk__str_none)) {
325  	        event.type = lrmd_event_new_client;
326  	    } else if (pcmk__str_eq(type, LRMD_OP_POKE, pcmk__str_none)) {
327  	        event.type = lrmd_event_poke;
328  	    } else {
329  	        return;
330  	    }
331  	
332  	    pcmk__trace("op %s notify event received", type);
333  	    native->callback(&event);
334  	
335  	    g_clear_pointer(&event.params, g_hash_table_destroy);
336  	    lrmd__reset_result(&event);
337  	}
338  	
339  	// \return Always 0, to indicate that IPC mainloop source should be kept
340  	static int
341  	lrmd_ipc_dispatch(const char *buffer, ssize_t length, gpointer userdata)
342  	{
343  	    lrmd_t *lrmd = userdata;
344  	    lrmd_private_t *native = lrmd->lrmd_private;
345  	
346  	    if (native->callback != NULL) {
347  	        xmlNode *msg = pcmk__xml_parse(buffer);
348  	
349  	        lrmd_dispatch_internal(msg, lrmd);
350  	        pcmk__xml_free(msg);
351  	    }
352  	    return 0;
353  	}
354  	
355  	static bool
356  	remote_executor_connected(lrmd_t * lrmd)
357  	{
358  	    lrmd_private_t *native = lrmd->lrmd_private;
359  	
360  	    return (native->remote->tls_session != NULL);
361  	}
362  	
363  	static void
364  	handle_remote_msg(xmlNode *xml, lrmd_t *lrmd)
365  	{
366  	    lrmd_private_t *native = lrmd->lrmd_private;
367  	    const char *msg_type = NULL;
368  	
369  	    msg_type = pcmk__xe_get(xml, PCMK__XA_LRMD_REMOTE_MSG_TYPE);
370  	    if (pcmk__str_eq(msg_type, "notify", pcmk__str_casei)) {
371  	        lrmd_dispatch_internal(xml, lrmd);
372  	    } else if (pcmk__str_eq(msg_type, "reply", pcmk__str_casei)) {
373  	        const char *op = pcmk__xe_get(xml, PCMK__XA_LRMD_OP);
374  	
375  	        if (native->expected_late_replies > 0) {
376  	            native->expected_late_replies--;
377  	
378  	            /* The register op message we get as a response to lrmd_handshake_async
379  	             * is a reply, so we have to handle that here.
380  	             */
381  	            if (pcmk__str_eq(op, "register", pcmk__str_casei)) {
382  	                int rc = process_lrmd_handshake_reply(xml, native);
383  	                report_async_connection_result(lrmd, pcmk_rc2legacy(rc));
384  	            }
385  	        } else {
386  	            int reply_id = 0;
387  	
388  	            pcmk__xe_get_int(xml, PCMK__XA_LRMD_CALLID, &reply_id);
389  	            /* if this happens, we want to know about it */
390  	            pcmk__err("Got outdated Pacemaker Remote reply %d", reply_id);
391  	        }
392  	    }
393  	}
394  	
395  	/*!
396  	 * \internal
397  	 * \brief Notify trigger handler
398  	 *
399  	 * \param[in,out] userdata API connection
400  	 *
401  	 * \return Always return G_SOURCE_CONTINUE to leave this trigger handler in the
402  	 *         mainloop
403  	 */
404  	static int
405  	process_pending_notifies(gpointer userdata)
406  	{
407  	    lrmd_t *lrmd = userdata;
408  	    lrmd_private_t *native = lrmd->lrmd_private;
409  	
410  	    if (native->pending_notify == NULL) {
411  	        return G_SOURCE_CONTINUE;
412  	    }
413  	
414  	    pcmk__trace("Processing pending notifies");
415  	    g_list_foreach(native->pending_notify, lrmd_dispatch_internal, lrmd);
416  	    g_list_free_full(native->pending_notify, (GDestroyNotify) pcmk__xml_free);
417  	    native->pending_notify = NULL;
418  	    return G_SOURCE_CONTINUE;
419  	}
420  	
421  	/*!
422  	 * \internal
423  	 * \brief TLS dispatch function for file descriptor sources
424  	 *
425  	 * \param[in,out] userdata  API connection
426  	 *
427  	 * \return -1 on error to remove the source from the mainloop, or 0 otherwise
428  	 *         to leave it in the mainloop
429  	 */
430  	static int
431  	lrmd_tls_dispatch(gpointer userdata)
432  	{
433  	    lrmd_t *lrmd = userdata;
434  	    lrmd_private_t *native = lrmd->lrmd_private;
435  	    xmlNode *xml = NULL;
436  	    int rc = pcmk_rc_ok;
437  	
438  	    if (!remote_executor_connected(lrmd)) {
439  	        pcmk__trace("TLS dispatch triggered after disconnect");
440  	        return -1;
441  	    }
442  	
443  	    pcmk__trace("TLS dispatch triggered");
444  	
445  	    rc = pcmk__remote_ready(native->remote, 0);
446  	    if (rc == pcmk_rc_ok) {
447  	        rc = pcmk__read_remote_message(native->remote, -1);
448  	    }
449  	
450  	    if (rc != pcmk_rc_ok && rc != ETIME) {
451  	        pcmk__info("Lost %s executor connection while reading data",
452  	                   pcmk__s(native->remote_nodename, "local"));
453  	        lrmd_tls_disconnect(lrmd);
454  	        return -1;
455  	    }
456  	
457  	    /* If rc is ETIME, there was nothing to read but we may already have a
458  	     * full message in the buffer
459  	     */
460  	    xml = pcmk__remote_message_xml(native->remote);
461  	
462  	    if (xml == NULL) {
463  	        return 0;
464  	    }
465  	
466  	    handle_remote_msg(xml, lrmd);
467  	    pcmk__xml_free(xml);
468  	    return 0;
469  	}
470  	
471  	/* Not used with mainloop */
472  	int
473  	lrmd_poll(lrmd_t * lrmd, int timeout)
474  	{
475  	    lrmd_private_t *native = lrmd->lrmd_private;
476  	
477  	    switch (native->type) {
478  	        case pcmk__client_ipc:
479  	            return crm_ipc_ready(native->ipc);
480  	
481  	        case pcmk__client_tls:
482  	            if (native->pending_notify) {
483  	                return 1;
484  	            } else {
485  	                int rc = pcmk__remote_ready(native->remote, 0);
486  	
487  	                switch (rc) {
488  	                    case pcmk_rc_ok:
489  	                        return 1;
490  	                    case ETIME:
491  	                        return 0;
492  	                    default:
493  	                        return pcmk_rc2legacy(rc);
494  	                }
495  	            }
496  	        default:
497  	            pcmk__err("Unsupported executor connection type (bug?): %d",
498  	                      native->type);
499  	            return -EPROTONOSUPPORT;
500  	    }
501  	}
502  	
503  	/* Not used with mainloop */
504  	bool
505  	lrmd_dispatch(lrmd_t * lrmd)
506  	{
507  	    lrmd_private_t *private = NULL;
508  	
509  	    pcmk__assert(lrmd != NULL);
510  	
511  	    private = lrmd->lrmd_private;
512  	    switch (private->type) {
513  	        case pcmk__client_ipc:
514  	            while (crm_ipc_ready(private->ipc)) {
515  	                if (crm_ipc_read(private->ipc) > 0) {
516  	                    const char *msg = crm_ipc_buffer(private->ipc);
517  	
518  	                    lrmd_ipc_dispatch(msg, strlen(msg), lrmd);
519  	                    pcmk__ipc_free_client_buffer(private->ipc);
520  	                }
521  	            }
522  	            break;
523  	        case pcmk__client_tls:
524  	            lrmd_tls_dispatch(lrmd);
525  	            break;
526  	        default:
527  	            pcmk__err("Unsupported executor connection type (bug?): %d",
528  	                      private->type);
529  	    }
530  	
531  	    if (lrmd_api_is_connected(lrmd) == FALSE) {
532  	        pcmk__err("Connection closed");
533  	        return FALSE;
534  	    }
535  	
536  	    return TRUE;
537  	}
538  	
539  	static xmlNode *
540  	lrmd_create_op(const char *token, const char *op, xmlNode *data, int timeout,
541  	               enum lrmd_call_options options)
542  	{
543  	    xmlNode *op_msg = NULL;
544  	
545  	    CRM_CHECK(token != NULL, return NULL);
546  	
547  	    op_msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_COMMAND);
548  	    pcmk__xe_set(op_msg, PCMK__XA_T, PCMK__VALUE_LRMD);
549  	    pcmk__xe_set(op_msg, PCMK__XA_LRMD_OP, op);
550  	    pcmk__xe_set_int(op_msg, PCMK__XA_LRMD_TIMEOUT, timeout);
551  	    pcmk__xe_set_int(op_msg, PCMK__XA_LRMD_CALLOPT, options);
552  	
553  	    if (data != NULL) {
554  	        xmlNode *wrapper = pcmk__xe_create(op_msg, PCMK__XE_LRMD_CALLDATA);
555  	
556  	        pcmk__xml_copy(wrapper, data);
557  	    }
558  	
559  	    pcmk__trace("Created executor %s command with call options %.8lx (%d)",
560  	                op, (long) options, options);
561  	    return op_msg;
562  	}
563  	
564  	static void
565  	lrmd_ipc_connection_destroy(gpointer userdata)
566  	{
567  	    lrmd_t *lrmd = userdata;
568  	    lrmd_private_t *native = lrmd->lrmd_private;
569  	
570  	    switch (native->type) {
571  	        case pcmk__client_ipc:
572  	            pcmk__info("Disconnected from local executor");
573  	            break;
574  	        case pcmk__client_tls:
575  	            pcmk__info("Disconnected from remote executor on %s",
576  	                       native->remote_nodename);
577  	            break;
578  	        default:
579  	            pcmk__err("Unsupported executor connection type %d (bug?)",
580  	                      native->type);
581  	    }
582  	
583  	    /* Prevent these from being cleaned up in lrmd_api_disconnect() */
584  	    native->ipc = NULL;
585  	    native->source = NULL;
586  	
587  	    if (native->callback) {
588  	        lrmd_event_data_t event = { 0, };
589  	        event.type = lrmd_event_disconnect;
590  	        event.remote_nodename = native->remote_nodename;
591  	        native->callback(&event);
592  	    }
593  	}
594  	
595  	static void
596  	lrmd_tls_connection_destroy(gpointer userdata)
597  	{
598  	    lrmd_t *lrmd = userdata;
599  	    lrmd_private_t *native = lrmd->lrmd_private;
600  	
601  	    pcmk__info("TLS connection destroyed");
602  	
603  	    if (native->remote->tls_session) {
604  	        gnutls_bye(native->remote->tls_session, GNUTLS_SHUT_RDWR);
605  	        g_clear_pointer(&native->remote->tls_session, gnutls_deinit);
606  	    }
607  	
608  	    g_clear_pointer(&native->tls, pcmk__free_tls);
609  	
610  	    if (native->sock >= 0) {
611  	        close(native->sock);
612  	    }
613  	
614  	    g_clear_pointer(&native->process_notify, mainloop_destroy_trigger);
615  	
616  	    g_list_free_full(native->pending_notify, (GDestroyNotify) pcmk__xml_free);
617  	    native->pending_notify = NULL;
618  	
619  	    g_clear_pointer(&native->handshake_trigger, mainloop_destroy_trigger);
620  	
621  	    g_clear_pointer(&native->remote->buffer, free);
622  	    g_clear_pointer(&native->remote->start_state, free);
623  	    native->source = 0;
624  	    native->sock = -1;
625  	
626  	    if (native->callback) {
627  	        lrmd_event_data_t event = { 0, };
628  	        event.remote_nodename = native->remote_nodename;
629  	        event.type = lrmd_event_disconnect;
630  	        native->callback(&event);
631  	    }
632  	}
633  	
634  	// \return Standard Pacemaker return code
635  	int
636  	lrmd__remote_send_xml(pcmk__remote_t *session, xmlNode *msg, uint32_t id,
637  	                      const char *msg_type)
638  	{
639  	    pcmk__xe_set_int(msg, PCMK__XA_LRMD_REMOTE_MSG_ID, id);
640  	    pcmk__xe_set(msg, PCMK__XA_LRMD_REMOTE_MSG_TYPE, msg_type);
641  	    return pcmk__remote_send_xml(session, msg);
642  	}
643  	
644  	// \return Standard Pacemaker return code
645  	static int
646  	read_remote_reply(lrmd_t *lrmd, int total_timeout, int expected_reply_id,
647  	                  xmlNode **reply)
648  	{
649  	    lrmd_private_t *native = lrmd->lrmd_private;
650  	    time_t start = time(NULL);
651  	    const char *msg_type = NULL;
652  	    int reply_id = 0;
653  	    int remaining_timeout = 0;
654  	    int rc = pcmk_rc_ok;
655  	
656  	    /* A timeout of 0 here makes no sense.  We have to wait a period of time
657  	     * for the response to come back.  If -1 or 0, default to 10 seconds. */
658  	    if (total_timeout <= 0 || total_timeout > MAX_TLS_RECV_WAIT) {
659  	        total_timeout = MAX_TLS_RECV_WAIT;
660  	    }
661  	
662  	    for (*reply = NULL; *reply == NULL; ) {
663  	
664  	        *reply = pcmk__remote_message_xml(native->remote);
665  	        if (*reply == NULL) {
666  	            /* read some more off the tls buffer if we still have time left. */
667  	            if (remaining_timeout) {
668  	                remaining_timeout = total_timeout - ((time(NULL) - start) * 1000);
669  	            } else {
670  	                remaining_timeout = total_timeout;
671  	            }
672  	            if (remaining_timeout <= 0) {
673  	                return ETIME;
674  	            }
675  	
676  	            rc = pcmk__read_remote_message(native->remote, remaining_timeout);
677  	            if (rc != pcmk_rc_ok) {
678  	                return rc;
679  	            }
680  	
681  	            *reply = pcmk__remote_message_xml(native->remote);
682  	            if (*reply == NULL) {
683  	                return ENOMSG;
684  	            }
685  	        }
686  	
687  	        pcmk__xe_get_int(*reply, PCMK__XA_LRMD_REMOTE_MSG_ID, &reply_id);
688  	        msg_type = pcmk__xe_get(*reply, PCMK__XA_LRMD_REMOTE_MSG_TYPE);
689  	
690  	        if (!msg_type) {
691  	            pcmk__err("Empty msg type received while waiting for reply");
692  	            g_clear_pointer(reply, pcmk__xml_free);
693  	
694  	        } else if (pcmk__str_eq(msg_type, "notify", pcmk__str_casei)) {
695  	            /* got a notify while waiting for reply, trigger the notify to be processed later */
696  	            pcmk__info("queueing notify");
697  	            native->pending_notify = g_list_append(native->pending_notify, *reply);
698  	            if (native->process_notify) {
699  	                pcmk__info("notify trigger set");
700  	                mainloop_set_trigger(native->process_notify);
701  	            }
702  	            *reply = NULL;
703  	        } else if (!pcmk__str_eq(msg_type, "reply", pcmk__str_casei)) {
704  	            /* msg isn't a reply, make some noise */
705  	            pcmk__err("Expected a reply, got %s", msg_type);
706  	            g_clear_pointer(reply, pcmk__xml_free);
707  	
708  	        } else if (reply_id != expected_reply_id) {
709  	            if (native->expected_late_replies > 0) {
710  	                native->expected_late_replies--;
711  	            } else {
712  	                pcmk__err("Got outdated reply, expected id %d got id %d",
713  	                          expected_reply_id, reply_id);
714  	            }
715  	
716  	            g_clear_pointer(reply, pcmk__xml_free);
717  	        }
718  	    }
719  	
720  	    if (native->remote->buffer && native->process_notify) {
721  	        mainloop_set_trigger(native->process_notify);
722  	    }
723  	
724  	    return rc;
725  	}
726  	
727  	// \return Standard Pacemaker return code
728  	static int
729  	send_remote_message(lrmd_t *lrmd, xmlNode *msg)
730  	{
731  	    int rc = pcmk_rc_ok;
732  	    lrmd_private_t *native = lrmd->lrmd_private;
733  	
734  	    global_remote_msg_id++;
735  	    if (global_remote_msg_id <= 0) {
736  	        global_remote_msg_id = 1;
737  	    }
738  	
739  	    rc = lrmd__remote_send_xml(native->remote, msg, global_remote_msg_id,
740  	                               "request");
741  	    if (rc != pcmk_rc_ok) {
742  	        pcmk__err("Disconnecting because TLS message could not be sent to "
743  	                  "Pacemaker Remote: %s",
744  	                  pcmk_rc_str(rc));
745  	        lrmd_tls_disconnect(lrmd);
746  	    }
747  	    return rc;
748  	}
749  	
750  	static int
751  	lrmd_tls_send_recv(lrmd_t * lrmd, xmlNode * msg, int timeout, xmlNode ** reply)
752  	{
753  	    int rc = 0;
754  	    xmlNode *xml = NULL;
755  	
756  	    if (!remote_executor_connected(lrmd)) {
757  	        return -ENOTCONN;
758  	    }
759  	
760  	    rc = send_remote_message(lrmd, msg);
761  	    if (rc != pcmk_rc_ok) {
762  	        return pcmk_rc2legacy(rc);
763  	    }
764  	
765  	    rc = read_remote_reply(lrmd, timeout, global_remote_msg_id, &xml);
766  	    if (rc != pcmk_rc_ok) {
767  	        pcmk__err("Disconnecting remote after request %d reply not received: "
768  	                  "%s " QB_XS " rc=%d timeout=%dms",
769  	                  global_remote_msg_id, pcmk_rc_str(rc), rc, timeout);
770  	        lrmd_tls_disconnect(lrmd);
771  	    }
772  	
773  	    if (reply) {
774  	        *reply = xml;
775  	    } else {
776  	        pcmk__xml_free(xml);
777  	    }
778  	
779  	    return pcmk_rc2legacy(rc);
780  	}
781  	
782  	static int
783  	lrmd_send_xml(lrmd_t * lrmd, xmlNode * msg, int timeout, xmlNode ** reply)
784  	{
785  	    int rc = pcmk_ok;
786  	    lrmd_private_t *native = lrmd->lrmd_private;
787  	
788  	    switch (native->type) {
789  	        case pcmk__client_ipc:
790  	            rc = crm_ipc_send(native->ipc, msg, crm_ipc_client_response, timeout, reply);
791  	            break;
792  	        case pcmk__client_tls:
793  	            rc = lrmd_tls_send_recv(lrmd, msg, timeout, reply);
794  	            break;
795  	        default:
796  	            pcmk__err("Unsupported executor connection type (bug?): %d",
797  	                      native->type);
798  	            rc = -EPROTONOSUPPORT;
799  	    }
800  	
801  	    return rc;
802  	}
803  	
804  	static int
805  	lrmd_send_xml_no_reply(lrmd_t * lrmd, xmlNode * msg)
806  	{
807  	    int rc = pcmk_ok;
808  	    lrmd_private_t *native = lrmd->lrmd_private;
809  	
810  	    switch (native->type) {
811  	        case pcmk__client_ipc:
812  	            rc = crm_ipc_send(native->ipc, msg, crm_ipc_flags_none, 0, NULL);
813  	            break;
814  	        case pcmk__client_tls:
815  	            rc = send_remote_message(lrmd, msg);
816  	            if (rc == pcmk_rc_ok) {
817  	                /* we don't want to wait around for the reply, but
818  	                 * since the request/reply protocol needs to behave the same
819  	                 * as libqb, a reply will eventually come later anyway. */
820  	                native->expected_late_replies++;
821  	            }
822  	            rc = pcmk_rc2legacy(rc);
823  	            break;
824  	        default:
825  	            pcmk__err("Unsupported executor connection type (bug?): %d",
826  	                      native->type);
827  	            rc = -EPROTONOSUPPORT;
828  	    }
829  	
830  	    return rc;
831  	}
832  	
833  	static int
834  	lrmd_api_is_connected(lrmd_t * lrmd)
835  	{
836  	    lrmd_private_t *native = lrmd->lrmd_private;
837  	
838  	    switch (native->type) {
839  	        case pcmk__client_ipc:
840  	            return crm_ipc_connected(native->ipc);
841  	        case pcmk__client_tls:
842  	            return remote_executor_connected(lrmd);
843  	        default:
844  	            pcmk__err("Unsupported executor connection type (bug?): %d",
845  	                      native->type);
846  	            return 0;
847  	    }
848  	}
849  	
850  	static void
851  	handle_ack(const xmlNode *reply)
852  	{
853  	    int status = 0;
854  	
855  	    pcmk__log_xml_err(reply, "Bad reply");
856  	
857  	    pcmk__xe_get_int(reply, PCMK_XA_STATUS, &status);
858  	    pcmk__err("Received error response from executor: %s", crm_exit_str(status));
859  	}
860  	
861  	/*!
862  	 * \internal
863  	 * \brief Send a prepared API command to the executor
864  	 *
865  	 * \param[in,out] lrmd          Existing connection to the executor
866  	 * \param[in]     op            Name of API command to send
867  	 * \param[in]     data          Command data XML to add to the sent command
868  	 * \param[out]    output_data   If expecting a reply, it will be stored here
869  	 * \param[in]     timeout       Timeout in milliseconds (if 0, defaults to
870  	 *                              a sensible value per the type of connection,
871  	 *                              standard vs. pacemaker remote);
872  	 *                              also propagated to the command XML
873  	 * \param[in]     call_options  Call options to pass to server when sending
874  	 * \param[in]     expect_reply  If true, wait for a reply from the server;
875  	 *                              must be true for IPC (as opposed to TLS) clients
876  	 *
877  	 * \return pcmk_ok on success, -errno on error
878  	 */
879  	static int
880  	lrmd_send_command(lrmd_t *lrmd, const char *op, xmlNode *data,
881  	                  xmlNode **output_data, int timeout,
882  	                  enum lrmd_call_options options, bool expect_reply)
883  	{
884  	    int rc = pcmk_ok;
885  	    lrmd_private_t *native = lrmd->lrmd_private;
886  	    xmlNode *op_msg = NULL;
887  	    xmlNode *op_reply = NULL;
888  	
889  	    if (!lrmd_api_is_connected(lrmd)) {
890  	        return -ENOTCONN;
891  	    }
892  	
893  	    if (op == NULL) {
894  	        pcmk__err("No operation specified");
895  	        return -EINVAL;
896  	    }
897  	
898  	    CRM_LOG_ASSERT(native->token != NULL);
899  	    pcmk__trace("Sending %s op to executor", op);
900  	
901  	    op_msg = lrmd_create_op(native->token, op, data, timeout, options);
902  	
903  	    if (op_msg == NULL) {
904  	        return -EINVAL;
905  	    }
906  	
907  	    if (expect_reply) {
908  	        rc = lrmd_send_xml(lrmd, op_msg, timeout, &op_reply);
909  	    } else {
910  	        rc = lrmd_send_xml_no_reply(lrmd, op_msg);
911  	        goto done;
912  	    }
913  	
914  	    if (rc < 0) {
915  	        pcmk__err("Couldn't perform %s operation (timeout=%d): %d", op, timeout,
916  	                  pcmk_strerror(rc));
917  	        goto done;
918  	
919  	    } else if (op_reply == NULL) {
920  	        rc = -ENOMSG;
921  	        goto done;
922  	    }
923  	
924  	    /* The only reason we can receive an ACK here is because we sent a request
925  	     * that execd didn't recognize and it responded via handle_unknown_request,
926  	     * and the status code will always indicate some sort of error.
927  	     */
928  	    if (pcmk__xe_is(op_reply, PCMK__XE_ACK)) {
929  	        handle_ack(op_reply);
930  	        rc = -EPROTO;
931  	        goto done;
932  	    }
933  	
934  	    pcmk__trace("%s op reply received", op);
935  	    pcmk__log_xml_trace(op_reply, "Reply");
936  	
937  	    rc = pcmk_ok;
938  	    if (pcmk__xe_get_int(op_reply, PCMK__XA_LRMD_RC, &rc) != pcmk_rc_ok) {
939  	        rc = -ENOMSG;
940  	        goto done;
941  	    }
942  	
943  	    if (output_data) {
944  	        *output_data = op_reply;
945  	        op_reply = NULL;        /* Prevent subsequent free */
946  	    }
947  	
948  	  done:
949  	    if (lrmd_api_is_connected(lrmd) == FALSE) {
950  	        pcmk__err("Executor disconnected");
951  	    }
952  	
953  	    pcmk__xml_free(op_msg);
954  	    pcmk__xml_free(op_reply);
955  	    return rc;
956  	}
957  	
958  	static int
959  	lrmd_api_poke_connection(lrmd_t * lrmd)
960  	{
961  	    int rc;
962  	    lrmd_private_t *native = lrmd->lrmd_private;
963  	    xmlNode *data = pcmk__xe_create(NULL, PCMK__XE_LRMD_RSC);
964  	
965  	    pcmk__xe_set(data, PCMK__XA_LRMD_ORIGIN, __func__);
966  	    rc = lrmd_send_command(lrmd, LRMD_OP_POKE, data, NULL, 0, 0,
967  	                           (native->type == pcmk__client_ipc));
968  	    pcmk__xml_free(data);
969  	
970  	    return rc < 0 ? rc : pcmk_ok;
971  	}
972  	
973  	// \return Standard Pacemaker return code
974  	int
975  	lrmd__validate_remote_settings(lrmd_t *lrmd, GHashTable *hash)
976  	{
977  	    int rc = pcmk_rc_ok;
978  	    const char *value;
979  	    lrmd_private_t *native = lrmd->lrmd_private;
980  	    xmlNode *data = pcmk__xe_create(NULL, PCMK__XA_LRMD_OP);
981  	
982  	    pcmk__xe_set(data, PCMK__XA_LRMD_ORIGIN, __func__);
983  	
984  	    value = pcmk__cluster_option(hash, PCMK_OPT_FENCING_WATCHDOG_TIMEOUT);
985  	    if ((value) &&
986  	        (stonith__watchdog_fencing_enabled_for_node(native->remote_nodename))) {
987  	       pcmk__xe_set(data, PCMK__XA_LRMD_WATCHDOG, value);
988  	    }
989  	
990  	    rc = lrmd_send_command(lrmd, LRMD_OP_CHECK, data, NULL, 0, 0,
991  	                           (native->type == pcmk__client_ipc));
992  	    pcmk__xml_free(data);
993  	    return (rc < 0)? pcmk_legacy2rc(rc) : pcmk_rc_ok;
994  	}
995  	
996  	static xmlNode *
997  	lrmd_handshake_hello_msg(const char *name, bool is_proxy)
998  	{
999  	    xmlNode *hello = pcmk__xe_create(NULL, PCMK__XE_LRMD_COMMAND);
1000 	
1001 	    pcmk__xe_set(hello, PCMK__XA_T, PCMK__VALUE_LRMD);
1002 	    pcmk__xe_set(hello, PCMK__XA_LRMD_OP, CRM_OP_REGISTER);
1003 	    pcmk__xe_set(hello, PCMK__XA_LRMD_CLIENTNAME, name);
1004 	    pcmk__xe_set(hello, PCMK__XA_LRMD_PROTOCOL_VERSION, LRMD_PROTOCOL_VERSION);
1005 	
1006 	    /* advertise that we are a proxy provider */
1007 	    if (is_proxy) {
1008 	        pcmk__xe_set_bool(hello, PCMK__XA_LRMD_IS_IPC_PROVIDER, true);
1009 	    }
1010 	
1011 	    return hello;
1012 	}
1013 	
1014 	static int
1015 	process_lrmd_handshake_reply(xmlNode *reply, lrmd_private_t *native)
1016 	{
1017 	    int rc = pcmk_rc_ok;
1018 	    const char *version = pcmk__xe_get(reply, PCMK__XA_LRMD_PROTOCOL_VERSION);
1019 	    const char *msg_type = pcmk__xe_get(reply, PCMK__XA_LRMD_OP);
1020 	    const char *tmp_ticket = pcmk__xe_get(reply, PCMK__XA_LRMD_CLIENTID);
1021 	    const char *start_state = pcmk__xe_get(reply, PCMK__XA_NODE_START_STATE);
1022 	
1023 	    /* The only reason we can receive an ACK here is because execd didn't
1024 	     * understand the CRM_OP_REGISTER message we sent in lrmd_handshake{,_async},
1025 	     * and the status code will always indicate some sort of error.
1026 	     */
1027 	    if (pcmk__xe_is(reply, PCMK__XE_ACK)) {
1028 	        handle_ack(reply);
1029 	        return EPROTO;
1030 	    }
1031 	
1032 	    pcmk__xe_get_int(reply, PCMK__XA_LRMD_RC, &rc);
1033 	    rc = pcmk_legacy2rc(rc);
1034 	
1035 	    /* The remote executor may add its uptime to the XML reply, which is useful
1036 	     * in handling transient attributes when the connection to the remote node
1037 	     * unexpectedly drops.  If no parameter is given, just default to -1.
1038 	     */
1039 	    native->remote->uptime = -1;
1040 	    pcmk__xe_get_time(reply, PCMK__XA_UPTIME, &native->remote->uptime);
1041 	
1042 	    if (start_state) {
1043 	        native->remote->start_state = strdup(start_state);
1044 	    }
1045 	
1046 	    if (rc == EPROTO) {
1047 	        pcmk__err("Executor protocol version mismatch between client "
1048 	                  "(" LRMD_PROTOCOL_VERSION ") and server (%s)",
1049 	                  version);
1050 	        pcmk__log_xml_err(reply, "Protocol Error");
1051 	    } else if (!pcmk__str_eq(msg_type, CRM_OP_REGISTER, pcmk__str_casei)) {
1052 	        pcmk__err("Invalid registration message: %s", msg_type);
1053 	        pcmk__log_xml_err(reply, "Bad reply");
1054 	        rc = EPROTO;
1055 	    } else if (tmp_ticket == NULL) {
1056 	        pcmk__err("No registration token provided");
1057 	        pcmk__log_xml_err(reply, "Bad reply");
1058 	        rc = EPROTO;
1059 	    } else {
1060 	        pcmk__trace("Obtained registration token: %s", tmp_ticket);
1061 	        native->token = strdup(tmp_ticket);
1062 	        native->peer_version = strdup(version?version:"1.0"); /* Included since 1.1 */
1063 	        rc = pcmk_rc_ok;
1064 	    }
1065 	
1066 	    return rc;
1067 	}
1068 	
1069 	static int
1070 	lrmd_handshake(lrmd_t * lrmd, const char *name)
1071 	{
1072 	    int rc = pcmk_rc_ok;
1073 	    lrmd_private_t *native = lrmd->lrmd_private;
1074 	    xmlNode *reply = NULL;
1075 	    xmlNode *hello = lrmd_handshake_hello_msg(name, native->proxy_callback != NULL);
1076 	
1077 	    rc = lrmd_send_xml(lrmd, hello, -1, &reply);
1078 	
1079 	    if (rc < 0) {
1080 	        pcmk__debug("Couldn't complete registration with the executor API: %s",
1081 	                    pcmk_strerror(rc));
1082 	        rc = ECOMM;
1083 	    } else if (reply == NULL) {
1084 	        pcmk__err("Did not receive registration reply");
1085 	        rc = EPROTO;
1086 	    } else {
1087 	        rc = process_lrmd_handshake_reply(reply, native);
1088 	    }
1089 	
1090 	    pcmk__xml_free(reply);
1091 	    pcmk__xml_free(hello);
1092 	
1093 	    if (rc != pcmk_rc_ok) {
1094 	        lrmd_api_disconnect(lrmd);
1095 	    }
1096 	
1097 	    return rc;
1098 	}
1099 	
1100 	static int
1101 	lrmd_handshake_async(lrmd_t * lrmd, const char *name)
1102 	{
1103 	    int rc = pcmk_rc_ok;
1104 	    lrmd_private_t *native = lrmd->lrmd_private;
1105 	    xmlNode *hello = lrmd_handshake_hello_msg(name, native->proxy_callback != NULL);
1106 	
1107 	    rc = send_remote_message(lrmd, hello);
1108 	
1109 	    if (rc == pcmk_rc_ok) {
1110 	        native->expected_late_replies++;
1111 	    } else {
1112 	        lrmd_api_disconnect(lrmd);
1113 	    }
1114 	
1115 	    pcmk__xml_free(hello);
1116 	    return rc;
1117 	}
1118 	
1119 	static int
1120 	lrmd_ipc_connect(lrmd_t * lrmd, int *fd)
1121 	{
1122 	    int rc = pcmk_ok;
1123 	    lrmd_private_t *native = lrmd->lrmd_private;
1124 	
1125 	    struct ipc_client_callbacks lrmd_callbacks = {
1126 	        .dispatch = lrmd_ipc_dispatch,
1127 	        .destroy = lrmd_ipc_connection_destroy
1128 	    };
1129 	
1130 	    pcmk__info("Connecting to executor");
1131 	
1132 	    if (fd) {
1133 	        /* No mainloop */
1134 	        native->ipc = crm_ipc_new(CRM_SYSTEM_LRMD, 0);
1135 	        if (native->ipc != NULL) {
1136 	            rc = pcmk__connect_generic_ipc(native->ipc);
1137 	            if (rc == pcmk_rc_ok) {
1138 	                rc = pcmk__ipc_fd(native->ipc, fd);
1139 	            }
1140 	            if (rc != pcmk_rc_ok) {
1141 	                pcmk__err("Connection to executor failed: %s", pcmk_rc_str(rc));
1142 	                rc = -ENOTCONN;
1143 	            }
1144 	        }
1145 	    } else {
1146 	        native->source = mainloop_add_ipc_client(CRM_SYSTEM_LRMD, G_PRIORITY_HIGH, 0, lrmd, &lrmd_callbacks);
1147 	        native->ipc = mainloop_get_ipc_client(native->source);
1148 	    }
1149 	
1150 	    if (native->ipc == NULL) {
1151 	        pcmk__debug("Could not connect to the executor API");
1152 	        rc = -ENOTCONN;
1153 	    }
1154 	
1155 	    return rc;
1156 	}
1157 	
1158 	/*!
1159 	 * \internal
1160 	 * \brief Initialize the Pacemaker Remote authentication key
1161 	 *
1162 	 * Try loading the Pacemaker Remote authentication key from cache if available,
1163 	 * otherwise from these locations, in order of preference:
1164 	 *
1165 	 * - The value of the PCMK_authkey_location environment variable, if set
1166 	 * - The Pacemaker default key file location
1167 	 *
1168 	 * \param[out] key  Where to store key
1169 	 *
1170 	 * \return Standard Pacemaker return code
1171 	 */
1172 	int
1173 	lrmd__init_remote_key(gnutls_datum_t *key)
1174 	{
1175 	    static const char *env_location = NULL;
1176 	    static bool need_env = true;
1177 	
1178 	    int rc = pcmk_rc_ok;
1179 	
1180 	    if (need_env) {
1181 	        env_location = pcmk__env_option(PCMK__ENV_AUTHKEY_LOCATION);
1182 	        need_env = false;
1183 	    }
1184 	
1185 	    if (remote_key.data != NULL) {
1186 	        pcmk__copy_key(key, &remote_key);
1187 	        return pcmk_rc_ok;
1188 	    }
1189 	
1190 	    // Try location in environment variable, if set
1191 	    if (env_location != NULL) {
1192 	        rc = pcmk__load_key(env_location, &remote_key, true);
1193 	
1194 	        if (rc == pcmk_rc_ok) {
1195 	            pcmk__copy_key(key, &remote_key);
1196 	            return pcmk_rc_ok;
1197 	        }
1198 	
1199 	        pcmk__warn("Could not read Pacemaker Remote key from %s: %s",
1200 	                   env_location, pcmk_rc_str(rc));
1201 	        return ENOKEY;
1202 	    }
1203 	
1204 	    // Try default location, if environment wasn't explicitly set to it
1205 	    rc = pcmk__load_key(DEFAULT_REMOTE_KEY_LOCATION, &remote_key, true);
1206 	
1207 	    if (rc == pcmk_rc_ok) {
1208 	        pcmk__copy_key(key, &remote_key);
1209 	        return pcmk_rc_ok;
1210 	    }
1211 	
1212 	    pcmk__warn("Could not read Pacemaker Remote key from default location "
1213 	               DEFAULT_REMOTE_KEY_LOCATION ": %s",
1214 	               pcmk_rc_str(rc));
1215 	    return ENOKEY;
1216 	}
1217 	
1218 	static void
1219 	report_async_connection_result(lrmd_t * lrmd, int rc)
1220 	{
1221 	    lrmd_private_t *native = lrmd->lrmd_private;
1222 	
1223 	    if (native->callback) {
1224 	        lrmd_event_data_t event = { 0, };
1225 	        event.type = lrmd_event_connect;
1226 	        event.remote_nodename = native->remote_nodename;
1227 	        event.connection_rc = rc;
1228 	        native->callback(&event);
1229 	    }
1230 	}
1231 	
1232 	static void
1233 	tls_handshake_failed(lrmd_t *lrmd, int tls_rc, int rc)
1234 	{
1235 	    lrmd_private_t *native = lrmd->lrmd_private;
1236 	
1237 	    pcmk__warn("Disconnecting after TLS handshake with Pacemaker Remote server "
1238 	               "%s:%d failed: %s",
1239 	               native->server, native->port,
1240 	               ((rc == EPROTO)? gnutls_strerror(tls_rc) : pcmk_rc_str(rc)));
1241 	    report_async_connection_result(lrmd, pcmk_rc2legacy(rc));
1242 	
1243 	    g_clear_pointer(&native->remote->tls_session, gnutls_deinit);
1244 	    lrmd_tls_connection_destroy(lrmd);
1245 	}
1246 	
1247 	static void
1248 	tls_handshake_succeeded(lrmd_t *lrmd)
1249 	{
1250 	    int rc = pcmk_rc_ok;
1251 	    lrmd_private_t *native = lrmd->lrmd_private;
1252 	
1253 	    /* Now that the handshake is done, see if any client TLS certificate is
1254 	     * close to its expiration date and log if so.  If a TLS certificate is not
1255 	     * in use, this function will just return so we don't need to check for the
1256 	     * session type here.
1257 	     */
1258 	    pcmk__tls_check_cert_expiration(native->remote->tls_session);
1259 	
1260 	    pcmk__info("TLS connection to Pacemaker Remote server %s:%d succeeded",
1261 	               native->server, native->port);
1262 	    rc = add_tls_to_mainloop(lrmd, true);
1263 	
1264 	    /* If add_tls_to_mainloop failed, report that right now.  Otherwise, we have
1265 	     * to wait until we read the async reply to report anything.
1266 	     */
1267 	    if (rc != pcmk_rc_ok) {
1268 	        report_async_connection_result(lrmd, pcmk_rc2legacy(rc));
1269 	    }
1270 	}
1271 	
1272 	/*!
1273 	 * \internal
1274 	 * \brief Perform a TLS client handshake with a Pacemaker Remote server
1275 	 *
1276 	 * \param[in] lrmd  Newly established Pacemaker Remote executor connection
1277 	 *
1278 	 * \return Standard Pacemaker return code
1279 	 */
1280 	static int
1281 	tls_client_handshake(lrmd_t *lrmd)
1282 	{
1283 	    lrmd_private_t *native = lrmd->lrmd_private;
1284 	    int tls_rc = GNUTLS_E_SUCCESS;
1285 	    int rc = pcmk__tls_client_handshake(native->remote, TLS_HANDSHAKE_TIMEOUT,
1286 	                                        &tls_rc);
1287 	
1288 	    if (rc != pcmk_rc_ok) {
1289 	        tls_handshake_failed(lrmd, tls_rc, rc);
1290 	    }
1291 	
1292 	    return rc;
1293 	}
1294 	
1295 	/*!
1296 	 * \internal
1297 	 * \brief Add trigger and file descriptor mainloop sources for TLS
1298 	 *
1299 	 * \param[in,out] lrmd              API connection with established TLS session
1300 	 * \param[in]     do_api_handshake  Whether to perform executor handshake
1301 	 *
1302 	 * \return Standard Pacemaker return code
1303 	 */
1304 	static int
1305 	add_tls_to_mainloop(lrmd_t *lrmd, bool do_api_handshake)
1306 	{
1307 	    lrmd_private_t *native = lrmd->lrmd_private;
1308 	    int rc = pcmk_rc_ok;
1309 	
1310 	    char *name = pcmk__assert_asprintf("pacemaker-remote-%s:%d",
1311 	                                       native->server, native->port);
1312 	
1313 	    struct mainloop_fd_callbacks tls_fd_callbacks = {
1314 	        .dispatch = lrmd_tls_dispatch,
1315 	        .destroy = lrmd_tls_connection_destroy,
1316 	    };
1317 	
1318 	    native->process_notify = mainloop_add_trigger(G_PRIORITY_HIGH,
1319 	                                                  process_pending_notifies, lrmd);
1320 	    native->source = mainloop_add_fd(name, G_PRIORITY_HIGH, native->sock, lrmd,
1321 	                                     &tls_fd_callbacks);
1322 	
1323 	    /* Async connections lose the client name provided by the API caller, so we
1324 	     * have to use our generated name here to perform the executor handshake.
1325 	     *
1326 	     * @TODO Keep track of the caller-provided name. Perhaps we should be using
1327 	     * that name in this function instead of generating one anyway.
1328 	     */
1329 	    if (do_api_handshake) {
1330 	        rc = lrmd_handshake_async(lrmd, name);
1331 	    }
1332 	    free(name);
1333 	    return rc;
1334 	}
1335 	
1336 	struct handshake_data_s {
1337 	    lrmd_t *lrmd;
1338 	    time_t start_time;
1339 	    int timeout_sec;
1340 	};
1341 	
1342 	static gboolean
1343 	try_handshake_cb(gpointer user_data)
1344 	{
1345 	    struct handshake_data_s *hs = user_data;
1346 	    lrmd_t *lrmd = hs->lrmd;
1347 	    lrmd_private_t *native = lrmd->lrmd_private;
1348 	    pcmk__remote_t *remote = native->remote;
1349 	
1350 	    int rc = pcmk_rc_ok;
1351 	    int tls_rc = GNUTLS_E_SUCCESS;
1352 	
1353 	    if (time(NULL) >= hs->start_time + hs->timeout_sec) {
1354 	        rc = ETIME;
1355 	
1356 	        tls_handshake_failed(lrmd, GNUTLS_E_TIMEDOUT, rc);
1357 	        free(hs);
1358 	        return 0;
1359 	    }
1360 	
1361 	    rc = pcmk__tls_client_try_handshake(remote, &tls_rc);
1362 	
1363 	    if (rc == pcmk_rc_ok) {
1364 	        tls_handshake_succeeded(lrmd);
1365 	        free(hs);
1366 	        return 0;
1367 	    } else if (rc == EAGAIN) {
1368 	        mainloop_set_trigger(native->handshake_trigger);
1369 	        return 1;
1370 	    } else {
1371 	        rc = EKEYREJECTED;
1372 	        tls_handshake_failed(lrmd, tls_rc, rc);
1373 	        free(hs);
1374 	        return 0;
1375 	    }
1376 	}
1377 	
1378 	static void
1379 	lrmd_tcp_connect_cb(void *userdata, int rc, int sock)
1380 	{
1381 	    lrmd_t *lrmd = userdata;
1382 	    lrmd_private_t *native = lrmd->lrmd_private;
1383 	    int tls_rc = GNUTLS_E_SUCCESS;
1384 	
1385 	    native->async_timer = 0;
1386 	
1387 	    if (rc != pcmk_rc_ok) {
1388 	        lrmd_tls_connection_destroy(lrmd);
1389 	        pcmk__info("Could not connect to Pacemaker Remote at %s:%d: %s "
1390 	                   QB_XS " rc=%d",
1391 	                   native->server, native->port, pcmk_rc_str(rc), rc);
1392 	        report_async_connection_result(lrmd, pcmk_rc2legacy(rc));
1393 	        return;
1394 	    }
1395 	
1396 	    /* The TCP connection was successful, so establish the TLS connection. */
1397 	
1398 	    native->sock = sock;
1399 	
1400 	    if (native->tls == NULL) {
1401 	        rc = pcmk__init_tls(&native->tls, false, true);
1402 	
1403 	        if ((rc != pcmk_rc_ok) || (native->tls == NULL)) {
1404 	            lrmd_tls_connection_destroy(lrmd);
1405 	            report_async_connection_result(lrmd, pcmk_rc2legacy(rc));
1406 	            return;
1407 	        }
1408 	    }
1409 	
1410 	    if (!pcmk__x509_enabled()) {
1411 	        gnutls_datum_t psk_key = { NULL, 0 };
1412 	
1413 	        rc = lrmd__init_remote_key(&psk_key);
1414 	        if (rc != pcmk_rc_ok) {
1415 	            pcmk__info("Could not connect to Pacemaker Remote at %s:%d: %s "
1416 	                       QB_XS " rc=%d",
1417 	                       native->server, native->port, pcmk_rc_str(rc), rc);
1418 	            lrmd_tls_connection_destroy(lrmd);
1419 	            report_async_connection_result(lrmd, pcmk_rc2legacy(rc));
1420 	            return;
1421 	        }
1422 	
1423 	        pcmk__tls_client_add_psk_key(native->tls, DEFAULT_REMOTE_USERNAME,
1424 	                                     &psk_key, true);
1425 	        gnutls_free(psk_key.data);
1426 	    }
1427 	
1428 	    native->remote->tls_session = pcmk__new_tls_session(native->tls, sock);
1429 	    if (native->remote->tls_session == NULL) {
1430 	        lrmd_tls_connection_destroy(lrmd);
1431 	        report_async_connection_result(lrmd, -EPROTO);
1432 	        return;
1433 	    }
1434 	
1435 	    /* If the TLS handshake immediately succeeds or fails, we can handle that
1436 	     * now without having to deal with mainloops and retries.  Otherwise, add a
1437 	     * trigger to keep trying until we get a result (or it times out).
1438 	     */
1439 	    rc = pcmk__tls_client_try_handshake(native->remote, &tls_rc);
1440 	    if (rc == EAGAIN) {
1441 	        struct handshake_data_s *hs = NULL;
1442 	
1443 	        if (native->handshake_trigger != NULL) {
1444 	            return;
1445 	        }
1446 	
1447 	        hs = pcmk__assert_alloc(1, sizeof(struct handshake_data_s));
1448 	        hs->lrmd = lrmd;
1449 	        hs->start_time = time(NULL);
1450 	        hs->timeout_sec = TLS_HANDSHAKE_TIMEOUT;
1451 	
1452 	        native->handshake_trigger = mainloop_add_trigger(G_PRIORITY_LOW, try_handshake_cb, hs);
1453 	        mainloop_set_trigger(native->handshake_trigger);
1454 	
1455 	    } else if (rc == pcmk_rc_ok) {
1456 	        tls_handshake_succeeded(lrmd);
1457 	
1458 	    } else {
1459 	        tls_handshake_failed(lrmd, tls_rc, rc);
1460 	    }
1461 	}
1462 	
1463 	static int
1464 	lrmd_tls_connect_async(lrmd_t * lrmd, int timeout /*ms */ )
1465 	{
1466 	    int rc = pcmk_rc_ok;
1467 	    int timer_id = 0;
1468 	    lrmd_private_t *native = lrmd->lrmd_private;
1469 	
1470 	    native->sock = -1;
1471 	    rc = pcmk__connect_remote(native->server, native->port, timeout, &timer_id,
1472 	                              &(native->sock), lrmd, lrmd_tcp_connect_cb);
1473 	    if (rc != pcmk_rc_ok) {
1474 	        pcmk__warn("Pacemaker Remote connection to %s:%d failed: %s "
1475 	                   QB_XS " rc=%d",
1476 	                   native->server, native->port, pcmk_rc_str(rc), rc);
1477 	        return rc;
1478 	    }
1479 	    native->async_timer = timer_id;
1480 	    return rc;
1481 	}
1482 	
1483 	static int
1484 	lrmd_tls_connect(lrmd_t * lrmd, int *fd)
1485 	{
1486 	    int rc = pcmk_rc_ok;
1487 	    lrmd_private_t *native = lrmd->lrmd_private;
1488 	
1489 	    native->sock = -1;
1490 	    rc = pcmk__connect_remote(native->server, native->port, 0, NULL,
1491 	                              &(native->sock), NULL, NULL);
1492 	    if (rc != pcmk_rc_ok) {
1493 	        pcmk__warn("Pacemaker Remote connection to %s:%d failed: %s "
1494 	                   QB_XS " rc=%d",
1495 	                   native->server, native->port, pcmk_rc_str(rc), rc);
1496 	        lrmd_tls_connection_destroy(lrmd);
1497 	        return ENOTCONN;
1498 	    }
1499 	
1500 	    if (native->tls == NULL) {
1501 	        rc = pcmk__init_tls(&native->tls, false, true);
1502 	
1503 	        if ((rc != pcmk_rc_ok) || (native->tls == NULL)) {
1504 	            lrmd_tls_connection_destroy(lrmd);
1505 	            return rc;
1506 	        }
1507 	    }
1508 	
1509 	    if (!pcmk__x509_enabled()) {
1510 	        gnutls_datum_t psk_key = { NULL, 0 };
1511 	
1512 	        rc = lrmd__init_remote_key(&psk_key);
1513 	        if (rc != pcmk_rc_ok) {
1514 	            lrmd_tls_connection_destroy(lrmd);
1515 	            return rc;
1516 	        }
1517 	
1518 	        pcmk__tls_client_add_psk_key(native->tls, DEFAULT_REMOTE_USERNAME,
1519 	                                     &psk_key, true);
1520 	        gnutls_free(psk_key.data);
1521 	    }
1522 	
1523 	    native->remote->tls_session = pcmk__new_tls_session(native->tls, native->sock);
1524 	    if (native->remote->tls_session == NULL) {
1525 	        lrmd_tls_connection_destroy(lrmd);
1526 	        return EPROTO;
1527 	    }
1528 	
1529 	    if (tls_client_handshake(lrmd) != pcmk_rc_ok) {
1530 	        return EKEYREJECTED;
1531 	    }
1532 	
1533 	    pcmk__info("Client TLS connection established with Pacemaker Remote server "
1534 	               "%s:%d",
1535 	               native->server, native->port);
1536 	
1537 	    if (fd) {
1538 	        *fd = native->sock;
1539 	    } else {
1540 	        rc = add_tls_to_mainloop(lrmd, false);
1541 	    }
1542 	    return rc;
1543 	}
1544 	
1545 	static int
1546 	lrmd_api_connect(lrmd_t * lrmd, const char *name, int *fd)
1547 	{
1548 	    int rc = -ENOTCONN;
1549 	    lrmd_private_t *native = lrmd->lrmd_private;
1550 	
1551 	    switch (native->type) {
1552 	        case pcmk__client_ipc:
1553 	            rc = lrmd_ipc_connect(lrmd, fd);
1554 	            break;
1555 	        case pcmk__client_tls:
1556 	            rc = lrmd_tls_connect(lrmd, fd);
1557 	            rc = pcmk_rc2legacy(rc);
1558 	            break;
1559 	        default:
1560 	            pcmk__err("Unsupported executor connection type (bug?): %d",
1561 	                      native->type);
1562 	            rc = -EPROTONOSUPPORT;
1563 	    }
1564 	
1565 	    if (rc == pcmk_ok) {
1566 	        rc = lrmd_handshake(lrmd, name);
1567 	        rc = pcmk_rc2legacy(rc);
1568 	    }
1569 	
1570 	    return rc;
1571 	}
1572 	
1573 	static int
1574 	lrmd_api_connect_async(lrmd_t * lrmd, const char *name, int timeout)
1575 	{
1576 	    int rc = pcmk_ok;
1577 	    lrmd_private_t *native = lrmd->lrmd_private;
1578 	
1579 	    CRM_CHECK(native && native->callback, return -EINVAL);
1580 	
1581 	    switch (native->type) {
1582 	        case pcmk__client_ipc:
1583 	            /* fake async connection with ipc.  it should be fast
1584 	             * enough that we gain very little from async */
1585 	            rc = lrmd_api_connect(lrmd, name, NULL);
1586 	            if (!rc) {
1587 	                report_async_connection_result(lrmd, rc);
1588 	            }
1589 	            break;
1590 	        case pcmk__client_tls:
1591 	            rc = lrmd_tls_connect_async(lrmd, timeout);
1592 	            rc = pcmk_rc2legacy(rc);
1593 	            break;
1594 	        default:
1595 	            pcmk__err("Unsupported executor connection type (bug?): %d",
1596 	                      native->type);
1597 	            rc = -EPROTONOSUPPORT;
1598 	    }
1599 	
1600 	    return rc;
1601 	}
1602 	
1603 	static void
1604 	lrmd_ipc_disconnect(lrmd_t * lrmd)
1605 	{
1606 	    lrmd_private_t *native = lrmd->lrmd_private;
1607 	
1608 	    if (native->source != NULL) {
1609 	        /* Attached to mainloop */
1610 	        g_clear_pointer(&native->source, mainloop_del_ipc_client);
1611 	        native->ipc = NULL;
1612 	
1613 	    } else if (native->ipc) {
1614 	        /* Not attached to mainloop */
1615 	        crm_ipc_t *ipc = native->ipc;
1616 	
1617 	        native->ipc = NULL;
1618 	        crm_ipc_close(ipc);
1619 	        crm_ipc_destroy(ipc);
1620 	    }
1621 	}
1622 	
1623 	static void
1624 	lrmd_tls_disconnect(lrmd_t * lrmd)
1625 	{
1626 	    lrmd_private_t *native = lrmd->lrmd_private;
1627 	
1628 	    if (native->remote->tls_session) {
1629 	        gnutls_bye(native->remote->tls_session, GNUTLS_SHUT_RDWR);
1630 	        g_clear_pointer(&native->remote->tls_session, gnutls_deinit);
1631 	    }
1632 	
1633 	    if (native->async_timer) {
1634 	        g_source_remove(native->async_timer);
1635 	        native->async_timer = 0;
1636 	    }
1637 	
1638 	    if (native->source != NULL) {
1639 	        /* Attached to mainloop */
1640 	        g_clear_pointer(&native->source, mainloop_del_ipc_client);
1641 	
1642 	    } else if (native->sock >= 0) {
1643 	        close(native->sock);
1644 	        native->sock = -1;
1645 	    }
1646 	
1647 	    g_list_free_full(native->pending_notify, (GDestroyNotify) pcmk__xml_free);
1648 	    native->pending_notify = NULL;
1649 	}
1650 	
1651 	static int
1652 	lrmd_api_disconnect(lrmd_t * lrmd)
1653 	{
1654 	    lrmd_private_t *native = lrmd->lrmd_private;
1655 	    int rc = pcmk_ok;
1656 	
1657 	    switch (native->type) {
1658 	        case pcmk__client_ipc:
1659 	            pcmk__debug("Disconnecting from local executor");
1660 	            lrmd_ipc_disconnect(lrmd);
1661 	            break;
1662 	        case pcmk__client_tls:
1663 	            pcmk__debug("Disconnecting from remote executor on %s",
1664 	                        native->remote_nodename);
1665 	            lrmd_tls_disconnect(lrmd);
1666 	            break;
1667 	        default:
1668 	            pcmk__err("Unsupported executor connection type (bug?): %d",
1669 	                      native->type);
1670 	            rc = -EPROTONOSUPPORT;
1671 	    }
1672 	
1673 	    g_clear_pointer(&native->token, free);
1674 	    g_clear_pointer(&native->peer_version, free);
1675 	    return rc;
1676 	}
1677 	
1678 	static int
1679 	lrmd_api_register_rsc(lrmd_t * lrmd,
1680 	                      const char *rsc_id,
1681 	                      const char *class,
1682 	                      const char *provider, const char *type, enum lrmd_call_options options)
1683 	{
1684 	    int rc = pcmk_ok;
1685 	    xmlNode *data = NULL;
1686 	
1687 	    if (!class || !type || !rsc_id) {
1688 	        return -EINVAL;
1689 	    }
1690 	    if (pcmk__is_set(pcmk_get_ra_caps(class), pcmk_ra_cap_provider)
1691 	        && (provider == NULL)) {
1692 	        return -EINVAL;
1693 	    }
1694 	
1695 	    data = pcmk__xe_create(NULL, PCMK__XE_LRMD_RSC);
1696 	
1697 	    pcmk__xe_set(data, PCMK__XA_LRMD_ORIGIN, __func__);
1698 	    pcmk__xe_set(data, PCMK__XA_LRMD_RSC_ID, rsc_id);
1699 	    pcmk__xe_set(data, PCMK__XA_LRMD_CLASS, class);
1700 	    pcmk__xe_set(data, PCMK__XA_LRMD_PROVIDER, provider);
1701 	    pcmk__xe_set(data, PCMK__XA_LRMD_TYPE, type);
1702 	    rc = lrmd_send_command(lrmd, LRMD_OP_RSC_REG, data, NULL, 0, options, true);
1703 	    pcmk__xml_free(data);
1704 	
1705 	    return rc;
1706 	}
1707 	
1708 	static int
1709 	lrmd_api_unregister_rsc(lrmd_t * lrmd, const char *rsc_id, enum lrmd_call_options options)
1710 	{
1711 	    int rc = pcmk_ok;
1712 	    xmlNode *data = pcmk__xe_create(NULL, PCMK__XE_LRMD_RSC);
1713 	
1714 	    pcmk__xe_set(data, PCMK__XA_LRMD_ORIGIN, __func__);
1715 	    pcmk__xe_set(data, PCMK__XA_LRMD_RSC_ID, rsc_id);
1716 	    rc = lrmd_send_command(lrmd, LRMD_OP_RSC_UNREG, data, NULL, 0, options, true);
1717 	    pcmk__xml_free(data);
1718 	
1719 	    return rc;
1720 	}
1721 	
1722 	lrmd_rsc_info_t *
1723 	lrmd_new_rsc_info(const char *rsc_id, const char *standard,
1724 	                  const char *provider, const char *type)
1725 	{
1726 	    lrmd_rsc_info_t *rsc_info = pcmk__assert_alloc(1, sizeof(lrmd_rsc_info_t));
1727 	
1728 	    rsc_info->id = pcmk__str_copy(rsc_id);
1729 	    rsc_info->standard = pcmk__str_copy(standard);
1730 	    rsc_info->provider = pcmk__str_copy(provider);
1731 	    rsc_info->type = pcmk__str_copy(type);
1732 	    return rsc_info;
1733 	}
1734 	
1735 	lrmd_rsc_info_t *
1736 	lrmd_copy_rsc_info(lrmd_rsc_info_t * rsc_info)
1737 	{
1738 	    return lrmd_new_rsc_info(rsc_info->id, rsc_info->standard,
1739 	                             rsc_info->provider, rsc_info->type);
1740 	}
1741 	
1742 	void
1743 	lrmd_free_rsc_info(lrmd_rsc_info_t * rsc_info)
1744 	{
1745 	    if (!rsc_info) {
1746 	        return;
1747 	    }
1748 	    free(rsc_info->id);
1749 	    free(rsc_info->type);
1750 	    free(rsc_info->standard);
1751 	    free(rsc_info->provider);
1752 	    free(rsc_info);
1753 	}
1754 	
1755 	static lrmd_rsc_info_t *
1756 	lrmd_api_get_rsc_info(lrmd_t * lrmd, const char *rsc_id, enum lrmd_call_options options)
1757 	{
1758 	    lrmd_rsc_info_t *rsc_info = NULL;
1759 	    xmlNode *data = pcmk__xe_create(NULL, PCMK__XE_LRMD_RSC);
1760 	    xmlNode *output = NULL;
1761 	    const char *class = NULL;
1762 	    const char *provider = NULL;
1763 	    const char *type = NULL;
1764 	
1765 	    pcmk__xe_set(data, PCMK__XA_LRMD_ORIGIN, __func__);
1766 	    pcmk__xe_set(data, PCMK__XA_LRMD_RSC_ID, rsc_id);
1767 	    lrmd_send_command(lrmd, LRMD_OP_RSC_INFO, data, &output, 0, options, true);
1768 	    pcmk__xml_free(data);
1769 	
1770 	    if (!output) {
1771 	        return NULL;
1772 	    }
1773 	
1774 	    class = pcmk__xe_get(output, PCMK__XA_LRMD_CLASS);
1775 	    provider = pcmk__xe_get(output, PCMK__XA_LRMD_PROVIDER);
1776 	    type = pcmk__xe_get(output, PCMK__XA_LRMD_TYPE);
1777 	
1778 	    if (!class || !type) {
1779 	        pcmk__xml_free(output);
1780 	        return NULL;
1781 	    } else if (pcmk__is_set(pcmk_get_ra_caps(class), pcmk_ra_cap_provider)
1782 	               && (provider == NULL)) {
1783 	        pcmk__xml_free(output);
1784 	        return NULL;
1785 	    }
1786 	
1787 	    rsc_info = lrmd_new_rsc_info(rsc_id, class, provider, type);
1788 	    pcmk__xml_free(output);
1789 	    return rsc_info;
1790 	}
1791 	
1792 	void
1793 	lrmd_free_op_info(lrmd_op_info_t *op_info)
1794 	{
1795 	    if (op_info) {
1796 	        free(op_info->rsc_id);
1797 	        free(op_info->action);
1798 	        free(op_info->interval_ms_s);
1799 	        free(op_info->timeout_ms_s);
1800 	        free(op_info);
1801 	    }
1802 	}
1803 	
1804 	static int
1805 	lrmd_api_get_recurring_ops(lrmd_t *lrmd, const char *rsc_id, int timeout_ms,
1806 	                           enum lrmd_call_options options, GList **output)
1807 	{
1808 	    xmlNode *data = NULL;
1809 	    xmlNode *output_xml = NULL;
1810 	    int rc = pcmk_ok;
1811 	
1812 	    if (output == NULL) {
1813 	        return -EINVAL;
1814 	    }
1815 	    *output = NULL;
1816 	
1817 	    // Send request
1818 	    if (rsc_id) {
1819 	        data = pcmk__xe_create(NULL, PCMK__XE_LRMD_RSC);
1820 	        pcmk__xe_set(data, PCMK__XA_LRMD_ORIGIN, __func__);
1821 	        pcmk__xe_set(data, PCMK__XA_LRMD_RSC_ID, rsc_id);
1822 	    }
1823 	    rc = lrmd_send_command(lrmd, LRMD_OP_GET_RECURRING, data, &output_xml,
1824 	                           timeout_ms, options, true);
1825 	    if (data) {
1826 	        pcmk__xml_free(data);
1827 	    }
1828 	
1829 	    // Process reply
1830 	    if ((rc != pcmk_ok) || (output_xml == NULL)) {
1831 	        return rc;
1832 	    }
1833 	    for (const xmlNode *rsc_xml = pcmk__xe_first_child(output_xml,
1834 	                                                       PCMK__XE_LRMD_RSC, NULL,
1835 	                                                       NULL);
1836 	         (rsc_xml != NULL) && (rc == pcmk_ok);
1837 	         rsc_xml = pcmk__xe_next(rsc_xml, PCMK__XE_LRMD_RSC)) {
1838 	
1839 	        rsc_id = pcmk__xe_get(rsc_xml, PCMK__XA_LRMD_RSC_ID);
1840 	        if (rsc_id == NULL) {
1841 	            pcmk__err("Could not parse recurring operation information from "
1842 	                      "executor");
1843 	            continue;
1844 	        }
1845 	        for (const xmlNode *op_xml = pcmk__xe_first_child(rsc_xml,
1846 	                                                          PCMK__XE_LRMD_RSC_OP,
1847 	                                                          NULL, NULL);
1848 	             op_xml != NULL;
1849 	             op_xml = pcmk__xe_next(op_xml, PCMK__XE_LRMD_RSC_OP)) {
1850 	
1851 	            lrmd_op_info_t *op_info = calloc(1, sizeof(lrmd_op_info_t));
1852 	
1853 	            if (op_info == NULL) {
1854 	                rc = -ENOMEM;
1855 	                break;
1856 	            }
1857 	            op_info->rsc_id = strdup(rsc_id);
1858 	            op_info->action = pcmk__xe_get_copy(op_xml,
1859 	                                                PCMK__XA_LRMD_RSC_ACTION);
1860 	            op_info->interval_ms_s =
1861 	                pcmk__xe_get_copy(op_xml, PCMK__XA_LRMD_RSC_INTERVAL);
1862 	            op_info->timeout_ms_s = pcmk__xe_get_copy(op_xml,
1863 	                                                      PCMK__XA_LRMD_TIMEOUT);
1864 	            *output = g_list_prepend(*output, op_info);
1865 	        }
1866 	    }
1867 	    pcmk__xml_free(output_xml);
1868 	    return rc;
1869 	}
1870 	
1871 	
1872 	static void
1873 	lrmd_api_set_callback(lrmd_t * lrmd, lrmd_event_callback callback)
1874 	{
1875 	    lrmd_private_t *native = lrmd->lrmd_private;
1876 	
1877 	    native->callback = callback;
1878 	}
1879 	
1880 	void
1881 	lrmd_internal_set_proxy_callback(lrmd_t * lrmd, void *userdata, void (*callback)(lrmd_t *lrmd, void *userdata, xmlNode *msg))
1882 	{
1883 	    lrmd_private_t *native = lrmd->lrmd_private;
1884 	
1885 	    native->proxy_callback = callback;
1886 	    native->proxy_callback_userdata = userdata;
1887 	}
1888 	
1889 	void
1890 	lrmd_internal_proxy_dispatch(lrmd_t *lrmd, xmlNode *msg)
1891 	{
1892 	    lrmd_private_t *native = lrmd->lrmd_private;
1893 	
1894 	    if (native->proxy_callback) {
1895 	        pcmk__log_xml_trace(msg, "PROXY_INBOUND");
1896 	        native->proxy_callback(lrmd, native->proxy_callback_userdata, msg);
1897 	    }
1898 	}
1899 	
1900 	int
1901 	lrmd_internal_proxy_send(lrmd_t * lrmd, xmlNode *msg)
1902 	{
1903 	    if (lrmd == NULL) {
1904 	        return -ENOTCONN;
1905 	    }
1906 	    pcmk__xe_set(msg, PCMK__XA_LRMD_OP, CRM_OP_IPC_FWD);
1907 	
1908 	    pcmk__log_xml_trace(msg, "PROXY_OUTBOUND");
1909 	    return lrmd_send_xml_no_reply(lrmd, msg);
1910 	}
1911 	
1912 	static int
1913 	stonith_get_metadata(const char *type, char **output)
1914 	{
1915 	    int rc = pcmk_ok;
1916 	    stonith_t *stonith_api = stonith__api_new();
1917 	
1918 	    if (stonith_api == NULL) {
1919 	        pcmk__err("Could not get fence agent meta-data: API memory allocation "
1920 	                  "failed");
1921 	        return -ENOMEM;
1922 	    }
1923 	
1924 	    rc = stonith_api->cmds->metadata(stonith_api, st_opt_sync_call, type, NULL,
1925 	                                     output, 0);
1926 	    if ((rc == pcmk_ok) && (*output == NULL)) {
1927 	        rc = -EIO;
1928 	    }
1929 	    stonith_api->cmds->free(stonith_api);
1930 	    return rc;
1931 	}
1932 	
1933 	static int
1934 	lrmd_api_get_metadata(lrmd_t *lrmd, const char *standard, const char *provider,
1935 	                      const char *type, char **output,
1936 	                      enum lrmd_call_options options)
1937 	{
1938 	    return lrmd->cmds->get_metadata_params(lrmd, standard, provider, type,
1939 	                                           output, options, NULL);
1940 	}
1941 	
1942 	static int
1943 	lrmd_api_get_metadata_params(lrmd_t *lrmd, const char *standard,
1944 	                             const char *provider, const char *type,
1945 	                             char **output, enum lrmd_call_options options,
1946 	                             lrmd_key_value_t *params)
1947 	{
1948 	    svc_action_t *action = NULL;
1949 	    GHashTable *params_table = NULL;
1950 	
1951 	    if (!standard || !type) {
1952 	        lrmd_key_value_freeall(params);
1953 	        return -EINVAL;
1954 	    }
1955 	
1956 	    if (pcmk__str_eq(standard, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
1957 	        lrmd_key_value_freeall(params);
1958 	
1959 	        // stonith-class resources don't support a provider
1960 	        return stonith_get_metadata(type, output);
1961 	    }
1962 	
1963 	    params_table = pcmk__strkey_table(free, free);
1964 	    for (const lrmd_key_value_t *param = params; param; param = param->next) {
1965 	        pcmk__insert_dup(params_table, param->key, param->value);
1966 	    }
1967 	    action = services__create_resource_action(type, standard, provider, type,
1968 	                                              PCMK_ACTION_META_DATA, 0,
1969 	                                              PCMK_DEFAULT_ACTION_TIMEOUT_MS,
1970 	                                              params_table, 0);
1971 	    lrmd_key_value_freeall(params);
1972 	
1973 	    if (action == NULL) {
1974 	        return -ENOMEM;
1975 	    }
1976 	    if (action->rc != PCMK_OCF_UNKNOWN) {
1977 	        services_action_free(action);
1978 	        return -EINVAL;
1979 	    }
1980 	
1981 	    if (!services_action_sync(action)) {
1982 	        pcmk__err("Failed to retrieve meta-data for %s:%s:%s", standard,
1983 	                  provider, type);
1984 	        services_action_free(action);
1985 	        return -EIO;
1986 	    }
1987 	
1988 	    if (!action->stdout_data) {
1989 	        pcmk__err("Failed to receive meta-data for %s:%s:%s", standard,
1990 	                  provider, type);
1991 	        services_action_free(action);
1992 	        return -EIO;
1993 	    }
1994 	
1995 	    *output = strdup(action->stdout_data);
1996 	    services_action_free(action);
1997 	
1998 	    return pcmk_ok;
1999 	}
2000 	
2001 	static int
2002 	lrmd_api_exec(lrmd_t *lrmd, const char *rsc_id, const char *action,
2003 	              const char *userdata, guint interval_ms,
2004 	              int timeout,      /* ms */
2005 	              int start_delay,  /* ms */
2006 	              enum lrmd_call_options options, lrmd_key_value_t * params)
2007 	{
2008 	    int rc = pcmk_ok;
2009 	    xmlNode *data = pcmk__xe_create(NULL, PCMK__XE_LRMD_RSC);
2010 	    xmlNode *args = pcmk__xe_create(data, PCMK__XE_ATTRIBUTES);
2011 	    lrmd_key_value_t *tmp = NULL;
2012 	
2013 	    pcmk__xe_set(data, PCMK__XA_LRMD_ORIGIN, __func__);
2014 	    pcmk__xe_set(data, PCMK__XA_LRMD_RSC_ID, rsc_id);
2015 	    pcmk__xe_set(data, PCMK__XA_LRMD_RSC_ACTION, action);
2016 	    pcmk__xe_set(data, PCMK__XA_LRMD_RSC_USERDATA_STR, userdata);
2017 	    pcmk__xe_set_guint(data, PCMK__XA_LRMD_RSC_INTERVAL, interval_ms);
2018 	    pcmk__xe_set_int(data, PCMK__XA_LRMD_TIMEOUT, timeout);
2019 	    pcmk__xe_set_int(data, PCMK__XA_LRMD_RSC_START_DELAY, start_delay);
2020 	
2021 	    for (tmp = params; tmp; tmp = tmp->next) {
2022 	        hash2smartfield((gpointer) tmp->key, (gpointer) tmp->value, args);
2023 	    }
2024 	
2025 	    rc = lrmd_send_command(lrmd, LRMD_OP_RSC_EXEC, data, NULL, timeout, options, true);
2026 	    pcmk__xml_free(data);
2027 	
2028 	    lrmd_key_value_freeall(params);
2029 	    return rc;
2030 	}
2031 	
2032 	/* timeout is in ms */
2033 	static int
2034 	lrmd_api_exec_alert(lrmd_t *lrmd, const char *alert_id, const char *alert_path,
2035 	                    int timeout, lrmd_key_value_t *params)
2036 	{
2037 	    int rc = pcmk_ok;
2038 	    xmlNode *data = pcmk__xe_create(NULL, PCMK__XE_LRMD_ALERT);
2039 	    xmlNode *args = pcmk__xe_create(data, PCMK__XE_ATTRIBUTES);
2040 	    lrmd_key_value_t *tmp = NULL;
2041 	
2042 	    pcmk__xe_set(data, PCMK__XA_LRMD_ORIGIN, __func__);
2043 	    pcmk__xe_set(data, PCMK__XA_LRMD_ALERT_ID, alert_id);
2044 	    pcmk__xe_set(data, PCMK__XA_LRMD_ALERT_PATH, alert_path);
2045 	    pcmk__xe_set_int(data, PCMK__XA_LRMD_TIMEOUT, timeout);
2046 	
2047 	    for (tmp = params; tmp; tmp = tmp->next) {
2048 	        hash2smartfield((gpointer) tmp->key, (gpointer) tmp->value, args);
2049 	    }
2050 	
2051 	    rc = lrmd_send_command(lrmd, LRMD_OP_ALERT_EXEC, data, NULL, timeout,
2052 	                           lrmd_opt_notify_orig_only, true);
2053 	    pcmk__xml_free(data);
2054 	
2055 	    lrmd_key_value_freeall(params);
2056 	    return rc;
2057 	}
2058 	
2059 	static int
2060 	lrmd_api_cancel(lrmd_t *lrmd, const char *rsc_id, const char *action,
2061 	                guint interval_ms)
2062 	{
2063 	    int rc = pcmk_ok;
2064 	    xmlNode *data = pcmk__xe_create(NULL, PCMK__XE_LRMD_RSC);
2065 	
2066 	    pcmk__xe_set(data, PCMK__XA_LRMD_ORIGIN, __func__);
2067 	    pcmk__xe_set(data, PCMK__XA_LRMD_RSC_ACTION, action);
2068 	    pcmk__xe_set(data, PCMK__XA_LRMD_RSC_ID, rsc_id);
2069 	    pcmk__xe_set_guint(data, PCMK__XA_LRMD_RSC_INTERVAL, interval_ms);
2070 	    rc = lrmd_send_command(lrmd, LRMD_OP_RSC_CANCEL, data, NULL, 0, 0, true);
2071 	    pcmk__xml_free(data);
2072 	    return rc;
2073 	}
2074 	
2075 	static int
2076 	list_stonith_agents(lrmd_list_t ** resources)
2077 	{
2078 	    int rc = 0;
2079 	    stonith_t *stonith_api = stonith__api_new();
2080 	    stonith_key_value_t *stonith_resources = NULL;
2081 	    stonith_key_value_t *dIter = NULL;
2082 	
2083 	    if (stonith_api == NULL) {
2084 	        pcmk__err("Could not list fence agents: API memory allocation failed");
2085 	        return -ENOMEM;
2086 	    }
2087 	    stonith_api->cmds->list_agents(stonith_api, st_opt_sync_call, NULL,
2088 	                                   &stonith_resources, 0);
2089 	    stonith_api->cmds->free(stonith_api);
2090 	
2091 	    for (dIter = stonith_resources; dIter; dIter = dIter->next) {
2092 	        rc++;
2093 	        if (resources) {
2094 	            *resources = lrmd_list_add(*resources, dIter->value);
2095 	        }
2096 	    }
2097 	
2098 	    stonith__key_value_freeall(stonith_resources, true, false);
2099 	    return rc;
2100 	}
2101 	
2102 	static int
2103 	lrmd_api_list_agents(lrmd_t * lrmd, lrmd_list_t ** resources, const char *class,
2104 	                     const char *provider)
2105 	{
2106 	    int rc = 0;
2107 	    int stonith_count = 0; // Initially, whether to include stonith devices
2108 	
2109 	    if (pcmk__str_eq(class, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_casei)) {
2110 	        stonith_count = 1;
2111 	
2112 	    } else {
2113 	        GList *gIter = NULL;
2114 	        GList *agents = resources_list_agents(class, provider);
2115 	
2116 	        for (gIter = agents; gIter != NULL; gIter = gIter->next) {
2117 	            *resources = lrmd_list_add(*resources, (const char *)gIter->data);
2118 	            rc++;
2119 	        }
2120 	        g_list_free_full(agents, free);
2121 	
2122 	        if (!class) {
2123 	            stonith_count = 1;
2124 	        }
2125 	    }
2126 	
2127 	    if (stonith_count) {
2128 	        // Now, if stonith devices are included, how many there are
2129 	        stonith_count = list_stonith_agents(resources);
2130 	        if (stonith_count > 0) {
2131 	            rc += stonith_count;
2132 	        }
2133 	    }
2134 	    if (rc == 0) {
2135 	        pcmk__notice("No agents found for class %s", class);
2136 	        rc = -EPROTONOSUPPORT;
2137 	    }
2138 	    return rc;
2139 	}
2140 	
2141 	static bool
2142 	does_provider_have_agent(const char *agent, const char *provider, const char *class)
2143 	{
2144 	    bool found = false;
2145 	    GList *agents = NULL;
2146 	    GList *gIter2 = NULL;
2147 	
2148 	    agents = resources_list_agents(class, provider);
2149 	    for (gIter2 = agents; gIter2 != NULL; gIter2 = gIter2->next) {
2150 	        if (pcmk__str_eq(agent, gIter2->data, pcmk__str_casei)) {
2151 	            found = true;
2152 	        }
2153 	    }
2154 	    g_list_free_full(agents, free);
2155 	    return found;
2156 	}
2157 	
2158 	static int
2159 	lrmd_api_list_ocf_providers(lrmd_t * lrmd, const char *agent, lrmd_list_t ** providers)
2160 	{
2161 	    int rc = pcmk_ok;
2162 	    char *provider = NULL;
2163 	    GList *ocf_providers = NULL;
2164 	    GList *gIter = NULL;
2165 	
2166 	    ocf_providers = resources_list_providers(PCMK_RESOURCE_CLASS_OCF);
2167 	
2168 	    for (gIter = ocf_providers; gIter != NULL; gIter = gIter->next) {
2169 	        provider = gIter->data;
2170 	        if (!agent || does_provider_have_agent(agent, provider,
2171 	                                               PCMK_RESOURCE_CLASS_OCF)) {
2172 	            *providers = lrmd_list_add(*providers, (const char *)gIter->data);
2173 	            rc++;
2174 	        }
2175 	    }
2176 	
2177 	    g_list_free_full(ocf_providers, free);
2178 	    return rc;
2179 	}
2180 	
2181 	static int
2182 	lrmd_api_list_standards(lrmd_t * lrmd, lrmd_list_t ** supported)
2183 	{
2184 	    int rc = 0;
2185 	    GList *standards = NULL;
2186 	    GList *gIter = NULL;
2187 	
2188 	    standards = resources_list_standards();
2189 	
2190 	    for (gIter = standards; gIter != NULL; gIter = gIter->next) {
2191 	        *supported = lrmd_list_add(*supported, (const char *)gIter->data);
2192 	        rc++;
2193 	    }
2194 	
2195 	    if (list_stonith_agents(NULL) > 0) {
2196 	        *supported = lrmd_list_add(*supported, PCMK_RESOURCE_CLASS_STONITH);
2197 	        rc++;
2198 	    }
2199 	
2200 	    g_list_free_full(standards, free);
2201 	    return rc;
2202 	}
2203 	
2204 	/*!
2205 	 * \internal
2206 	 * \brief Create an executor API object
2207 	 *
2208 	 * \param[out] api       Will be set to newly created API object (it is the
2209 	 *                       caller's responsibility to free this value with
2210 	 *                       lrmd_api_delete() if this function succeeds)
2211 	 * \param[in]  nodename  If the object will be used for a remote connection,
2212 	 *                       the node name to use in cluster for remote executor
2213 	 * \param[in]  server    If the object will be used for a remote connection,
2214 	 *                       the resolvable host name to connect to
2215 	 * \param[in]  port      If the object will be used for a remote connection,
2216 	 *                       port number on \p server to connect to
2217 	 *
2218 	 * \return Standard Pacemaker return code
2219 	 * \note If the caller leaves one of \p nodename or \p server NULL, the other's
2220 	 *       value will be used for both. If the caller leaves both NULL, an API
2221 	 *       object will be created for a local executor connection.
2222 	 */
2223 	int
2224 	lrmd__new(lrmd_t **api, const char *nodename, const char *server, int port)
2225 	{
2226 	    lrmd_private_t *pvt = NULL;
2227 	
2228 	    if (api == NULL) {
2229 	        return EINVAL;
2230 	    }
2231 	    *api = NULL;
2232 	
2233 	    // Allocate all memory needed
2234 	
2235 	    *api = calloc(1, sizeof(lrmd_t));
2236 	    if (*api == NULL) {
2237 	        return ENOMEM;
2238 	    }
2239 	
2240 	    pvt = calloc(1, sizeof(lrmd_private_t));
2241 	    if (pvt == NULL) {
2242 	        lrmd_api_delete(*api);
2243 	        *api = NULL;
2244 	        return ENOMEM;
2245 	    }
2246 	    (*api)->lrmd_private = pvt;
2247 	
2248 	    // @TODO Do we need to do this for local connections?
2249 	    pvt->remote = calloc(1, sizeof(pcmk__remote_t));
2250 	
2251 	    (*api)->cmds = calloc(1, sizeof(lrmd_api_operations_t));
2252 	
2253 	    if ((pvt->remote == NULL) || ((*api)->cmds == NULL)) {
2254 	        lrmd_api_delete(*api);
2255 	        *api = NULL;
2256 	        return ENOMEM;
2257 	    }
2258 	
2259 	    // Set methods
2260 	    (*api)->cmds->connect = lrmd_api_connect;
2261 	    (*api)->cmds->connect_async = lrmd_api_connect_async;
2262 	    (*api)->cmds->is_connected = lrmd_api_is_connected;
2263 	    (*api)->cmds->poke_connection = lrmd_api_poke_connection;
2264 	    (*api)->cmds->disconnect = lrmd_api_disconnect;
2265 	    (*api)->cmds->register_rsc = lrmd_api_register_rsc;
2266 	    (*api)->cmds->unregister_rsc = lrmd_api_unregister_rsc;
2267 	    (*api)->cmds->get_rsc_info = lrmd_api_get_rsc_info;
2268 	    (*api)->cmds->get_recurring_ops = lrmd_api_get_recurring_ops;
2269 	    (*api)->cmds->set_callback = lrmd_api_set_callback;
2270 	    (*api)->cmds->get_metadata = lrmd_api_get_metadata;
2271 	    (*api)->cmds->exec = lrmd_api_exec;
2272 	    (*api)->cmds->cancel = lrmd_api_cancel;
2273 	    (*api)->cmds->list_agents = lrmd_api_list_agents;
2274 	    (*api)->cmds->list_ocf_providers = lrmd_api_list_ocf_providers;
2275 	    (*api)->cmds->list_standards = lrmd_api_list_standards;
2276 	    (*api)->cmds->exec_alert = lrmd_api_exec_alert;
2277 	    (*api)->cmds->get_metadata_params = lrmd_api_get_metadata_params;
2278 	
2279 	    if ((nodename == NULL) && (server == NULL)) {
2280 	        pvt->type = pcmk__client_ipc;
2281 	    } else {
2282 	        if (nodename == NULL) {
2283 	            nodename = server;
2284 	        } else if (server == NULL) {
2285 	            server = nodename;
2286 	        }
2287 	        pvt->type = pcmk__client_tls;
2288 	        pvt->remote_nodename = strdup(nodename);
2289 	        pvt->server = strdup(server);
2290 	        if ((pvt->remote_nodename == NULL) || (pvt->server == NULL)) {
2291 	            lrmd_api_delete(*api);
2292 	            *api = NULL;
2293 	            return ENOMEM;
2294 	        }
2295 	        pvt->port = port;
2296 	        if (pvt->port == 0) {
2297 	            pvt->port = crm_default_remote_port();
2298 	        }
2299 	    }
2300 	    return pcmk_rc_ok;
2301 	}
2302 	
2303 	lrmd_t *
2304 	lrmd_api_new(void)
2305 	{
2306 	    lrmd_t *api = NULL;
2307 	
2308 	    pcmk__assert(lrmd__new(&api, NULL, NULL, 0) == pcmk_rc_ok);
2309 	    return api;
2310 	}
2311 	
2312 	lrmd_t *
2313 	lrmd_remote_api_new(const char *nodename, const char *server, int port)
2314 	{
2315 	    lrmd_t *api = NULL;
2316 	
2317 	    pcmk__assert(lrmd__new(&api, nodename, server, port) == pcmk_rc_ok);
2318 	    return api;
2319 	}
2320 	
2321 	void
2322 	lrmd_api_delete(lrmd_t * lrmd)
2323 	{
2324 	    if (lrmd == NULL) {
2325 	        return;
2326 	    }
2327 	    if (lrmd->cmds != NULL) { // Never NULL, but make static analysis happy
2328 	        if (lrmd->cmds->disconnect != NULL) { // Also never really NULL
2329 	            lrmd->cmds->disconnect(lrmd); // No-op if already disconnected
2330 	        }
2331 	        free(lrmd->cmds);
2332 	    }
2333 	    if (lrmd->lrmd_private != NULL) {
2334 	        lrmd_private_t *native = lrmd->lrmd_private;
2335 	
2336 	        free(native->server);
2337 	        free(native->remote_nodename);
2338 	        free(native->remote);
2339 	        free(native->token);
2340 	        free(native->peer_version);
2341 	        free(lrmd->lrmd_private);
2342 	    }
2343 	    free(lrmd);
2344 	}
2345 	
2346 	struct metadata_cb {
2347 	     void (*callback)(int pid, const pcmk__action_result_t *result,
2348 	                      void *user_data);
2349 	     void *user_data;
2350 	};
2351 	
2352 	/*!
2353 	 * \internal
2354 	 * \brief Process asynchronous metadata completion
2355 	 *
2356 	 * \param[in,out] action  Metadata action that completed
2357 	 */
2358 	static void
2359 	metadata_complete(svc_action_t *action)
2360 	{
2361 	    struct metadata_cb *metadata_cb = (struct metadata_cb *) action->cb_data;
2362 	    pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;
2363 	
2364 	    services__copy_result(action, &result);
2365 	    pcmk__set_result_output(&result, action->stdout_data, action->stderr_data);
2366 	
2367 	    metadata_cb->callback(0, &result, metadata_cb->user_data);
2368 	    result.action_stdout = NULL; // Prevent free, because action owns it
2369 	    result.action_stderr = NULL; // Prevent free, because action owns it
2370 	    pcmk__reset_result(&result);
2371 	    free(metadata_cb);
2372 	}
2373 	
2374 	/*!
2375 	 * \internal
2376 	 * \brief Retrieve agent metadata asynchronously
2377 	 *
2378 	 * \param[in]     rsc        Resource agent specification
2379 	 * \param[in]     callback   Function to call with result (this will always be
2380 	 *                           called, whether by this function directly or later
2381 	 *                           via the main loop, and on success the metadata will
2382 	 *                           be in its result argument's action_stdout)
2383 	 * \param[in,out] user_data  User data to pass to callback
2384 	 *
2385 	 * \return Standard Pacemaker return code
2386 	 * \note This function is not a lrmd_api_operations_t method because it does not
2387 	 *       need an lrmd_t object and does not go through the executor, but
2388 	 *       executes the agent directly.
2389 	 */
2390 	int
2391 	lrmd__metadata_async(const lrmd_rsc_info_t *rsc,
2392 	                     void (*callback)(int pid,
2393 	                                      const pcmk__action_result_t *result,
2394 	                                      void *user_data),
2395 	                     void *user_data)
2396 	{
2397 	    svc_action_t *action = NULL;
2398 	    struct metadata_cb *metadata_cb = NULL;
2399 	    pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;
2400 	
2401 	    CRM_CHECK(callback != NULL, return EINVAL);
2402 	
2403 	    if ((rsc == NULL) || (rsc->standard == NULL) || (rsc->type == NULL)) {
2404 	        pcmk__set_result(&result, PCMK_OCF_NOT_CONFIGURED,
2405 	                         PCMK_EXEC_ERROR_FATAL,
2406 	                         "Invalid resource specification");
2407 	        callback(0, &result, user_data);
2408 	        pcmk__reset_result(&result);
2409 	        return EINVAL;
2410 	    }
2411 	
2412 	    if (strcmp(rsc->standard, PCMK_RESOURCE_CLASS_STONITH) == 0) {
2413 	        return stonith__metadata_async(rsc->type,
2414 	                                       pcmk__timeout_ms2s(PCMK_DEFAULT_ACTION_TIMEOUT_MS),
2415 	                                       callback, user_data);
2416 	    }
2417 	
2418 	    action = services__create_resource_action(pcmk__s(rsc->id, rsc->type),
2419 	                                              rsc->standard, rsc->provider,
2420 	                                              rsc->type,
2421 	                                              PCMK_ACTION_META_DATA, 0,
2422 	                                              PCMK_DEFAULT_ACTION_TIMEOUT_MS,
2423 	                                              NULL, 0);
2424 	    if (action == NULL) {
2425 	        pcmk__set_result(&result, PCMK_OCF_UNKNOWN_ERROR, PCMK_EXEC_ERROR,
2426 	                         "Out of memory");
2427 	        callback(0, &result, user_data);
2428 	        pcmk__reset_result(&result);
2429 	        return ENOMEM;
2430 	    }
2431 	    if (action->rc != PCMK_OCF_UNKNOWN) {
2432 	        services__copy_result(action, &result);
2433 	        callback(0, &result, user_data);
2434 	        pcmk__reset_result(&result);
2435 	        services_action_free(action);
2436 	        return EINVAL;
2437 	    }
2438 	
2439 	    action->cb_data = calloc(1, sizeof(struct metadata_cb));
2440 	    if (action->cb_data == NULL) {
2441 	        services_action_free(action);
2442 	        pcmk__set_result(&result, PCMK_OCF_UNKNOWN_ERROR, PCMK_EXEC_ERROR,
2443 	                         "Out of memory");
2444 	        callback(0, &result, user_data);
2445 	        pcmk__reset_result(&result);
2446 	        return ENOMEM;
2447 	    }
2448 	
2449 	    metadata_cb = (struct metadata_cb *) action->cb_data;
2450 	    metadata_cb->callback = callback;
2451 	    metadata_cb->user_data = user_data;
2452 	    if (!services_action_async(action, metadata_complete)) {
2453 	        services_action_free(action);
2454 	        return pcmk_rc_error; // @TODO Derive from action->rc and ->status
2455 	    }
2456 	
2457 	    // The services library has taken responsibility for action
2458 	    return pcmk_rc_ok;
2459 	}
2460 	
2461 	/*!
2462 	 * \internal
2463 	 * \brief Set the result of an executor event
2464 	 *
2465 	 * \param[in,out] event        Executor event to set
2466 	 * \param[in]     rc           OCF exit status of event
2467 	 * \param[in]     op_status    Executor status of event
2468 	 * \param[in]     exit_reason  Human-friendly description of event
2469 	 */
2470 	void
2471 	lrmd__set_result(lrmd_event_data_t *event, enum ocf_exitcode rc, int op_status,
2472 	                 const char *exit_reason)
2473 	{
2474 	    if (event == NULL) {
2475 	        return;
2476 	    }
2477 	
2478 	    event->rc = rc;
2479 	    event->op_status = op_status;
2480 	
2481 	    // lrmd_event_data_t has (const char *) members that lrmd_free_event() frees
2482 	    pcmk__str_update((char **) &event->exit_reason, exit_reason);
2483 	}
2484 	
2485 	/*!
2486 	 * \internal
2487 	 * \brief Clear an executor event's exit reason, output, and error output
2488 	 *
2489 	 * \param[in,out] event  Executor event to reset
2490 	 */
2491 	void
2492 	lrmd__reset_result(lrmd_event_data_t *event)
2493 	{
(1) Event path: Condition "event == NULL", taking false branch.
2494 	    if (event == NULL) {
2495 	        return;
2496 	    }
2497 	
(2) Event path: Condition "_p", taking true branch.
2498 	    g_clear_pointer(&event->exit_reason, free);
CID (unavailable; MK=644eff7dd29b6b532d943c1ff490efbe) (#2 of 2): Inconsistent C union access (INCONSISTENT_UNION_ACCESS):
(3) Event assign_union_field: The union field "in" of "_pp" is written.
(4) Event inconsistent_union_field_access: In "_pp.out", the union field used: "out" is inconsistent with the field most recently stored: "in".
2499 	    g_clear_pointer(&event->output, free);
2500 	}
2501 	
2502 	/*!
2503 	 * \internal
2504 	 * \brief Get the uptime of a remote resource connection
2505 	 *
2506 	 * When the cluster connects to a remote resource, part of that resource's
2507 	 * handshake includes the uptime of the remote resource's connection.  This
2508 	 * uptime is stored in the lrmd_t object.
2509 	 *
2510 	 * \return The connection's uptime, or -1 if unknown
2511 	 */
2512 	time_t
2513 	lrmd__uptime(lrmd_t *lrmd)
2514 	{
2515 	    lrmd_private_t *native = lrmd->lrmd_private;
2516 	
2517 	    if (native->remote == NULL) {
2518 	        return -1;
2519 	    } else {
2520 	        return native->remote->uptime;
2521 	    }
2522 	}
2523 	
2524 	const char *
2525 	lrmd__node_start_state(lrmd_t *lrmd)
2526 	{
2527 	    lrmd_private_t *native = lrmd->lrmd_private;
2528 	
2529 	    if (native->remote == NULL) {
2530 	        return NULL;
2531 	    } else {
2532 	        return native->remote->start_state;
2533 	    }
2534 	}
2535