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
|
(1) Event path: |
Condition "native->source != NULL", taking true branch. |
1608 if (native->source != NULL) {
1609 /* Attached to mainloop */
|
CID (unavailable; MK=f6c3cab271227c54a16bc4fec8c621c9) (#1 of 1): Inconsistent C union access (INCONSISTENT_UNION_ACCESS): |
|
(2) Event assign_union_field: |
The union field "in" of "_pp" is written. |
|
(3) Event inconsistent_union_field_access: |
In "_pp.out", the union field used: "out" is inconsistent with the field most recently stored: "in". |
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 {
2494 if (event == NULL) {
2495 return;
2496 }
2497
2498 g_clear_pointer(&event->exit_reason, free);
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