pacemaker  2.1.0-7c3f660
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dbus.c
Go to the documentation of this file.
1 /*
2  * Copyright 2014-2020 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 #include <crm/crm.h>
12 #include <crm/services.h>
13 #include <dbus/dbus.h>
14 #include <pcmk-dbus.h>
15 
16 /*
17  * DBus message dispatch
18  */
19 
20 // List of DBus connections (DBusConnection*) with messages available
21 static GList *conn_dispatches = NULL;
22 
37 static void
38 update_dispatch_status(DBusConnection *connection,
39  DBusDispatchStatus new_status, void *data)
40 {
41  if (new_status == DBUS_DISPATCH_DATA_REMAINS) {
42  crm_trace("DBus connection has messages available for dispatch");
43  conn_dispatches = g_list_prepend(conn_dispatches, connection);
44  } else {
45  crm_trace("DBus connection has no messages available for dispatch "
46  "(status %d)", new_status);
47  }
48 }
49 
54 static void
55 dispatch_messages(void)
56 {
57  for (GList *gIter = conn_dispatches; gIter != NULL; gIter = gIter->next) {
58  DBusConnection *connection = gIter->data;
59 
60  while (dbus_connection_get_dispatch_status(connection)
61  == DBUS_DISPATCH_DATA_REMAINS) {
62  crm_trace("Dispatching available messages on DBus connection");
63  dbus_connection_dispatch(connection);
64  }
65  }
66  g_list_free(conn_dispatches);
67  conn_dispatches = NULL;
68 }
69 
70 
71 /*
72  * DBus file descriptor watches
73  *
74  * The DBus library allows the caller to register functions for the library to
75  * use for file descriptor notifications via a main loop.
76  */
77 
78 /* Copied from dbus-watch.c */
79 static const char*
80 dbus_watch_flags_to_string(int flags)
81 {
82  const char *watch_type;
83 
84  if ((flags & DBUS_WATCH_READABLE) && (flags & DBUS_WATCH_WRITABLE)) {
85  watch_type = "read/write";
86  } else if (flags & DBUS_WATCH_READABLE) {
87  watch_type = "read";
88  } else if (flags & DBUS_WATCH_WRITABLE) {
89  watch_type = "write";
90  } else {
91  watch_type = "neither read nor write";
92  }
93  return watch_type;
94 }
95 
107 static int
108 dispatch_fd_data(gpointer userdata)
109 {
110  bool oom = FALSE;
111  DBusWatch *watch = userdata;
112  int flags = dbus_watch_get_flags(watch);
113  bool enabled = dbus_watch_get_enabled (watch);
114 
115  crm_trace("Dispatching DBus watch for file descriptor %d "
116  "with flags 0x%x (%s)",
117  dbus_watch_get_unix_fd(watch), flags,
118  dbus_watch_flags_to_string(flags));
119 
120  if (enabled && (flags & (DBUS_WATCH_READABLE|DBUS_WATCH_WRITABLE))) {
121  oom = !dbus_watch_handle(watch, flags);
122 
123  } else if (enabled) {
124  oom = !dbus_watch_handle(watch, DBUS_WATCH_ERROR);
125  }
126 
127  if (flags != dbus_watch_get_flags(watch)) {
128  flags = dbus_watch_get_flags(watch);
129  crm_trace("Dispatched DBus file descriptor watch: now 0x%x (%s)",
130  flags, dbus_watch_flags_to_string(flags));
131  }
132 
133  if (oom) {
134  crm_crit("Could not dispatch DBus file descriptor data: Out of memory");
135  } else {
136  dispatch_messages();
137  }
138  return 0;
139 }
140 
141 static void
142 watch_fd_closed(gpointer userdata)
143 {
144  crm_trace("DBus watch for file descriptor %d is now closed",
145  dbus_watch_get_unix_fd((DBusWatch *) userdata));
146 }
147 
148 static struct mainloop_fd_callbacks pcmk_dbus_cb = {
149  .dispatch = dispatch_fd_data,
150  .destroy = watch_fd_closed,
151 };
152 
153 static dbus_bool_t
154 add_dbus_watch(DBusWatch *watch, void *data)
155 {
156  int fd = dbus_watch_get_unix_fd(watch);
157 
158  mainloop_io_t *client = mainloop_add_fd("dbus", G_PRIORITY_DEFAULT, fd,
159  watch, &pcmk_dbus_cb);
160 
161  crm_trace("Added DBus watch for file descriptor %d", fd);
162  dbus_watch_set_data(watch, client, NULL);
163  return TRUE;
164 }
165 
166 static void
167 toggle_dbus_watch(DBusWatch *watch, void *data)
168 {
169  // @TODO Should this do something more?
170  crm_debug("DBus watch for file descriptor %d is now %s",
171  dbus_watch_get_unix_fd(watch),
172  (dbus_watch_get_enabled(watch)? "enabled" : "disabled"));
173 }
174 
175 static void
176 remove_dbus_watch(DBusWatch *watch, void *data)
177 {
178  crm_trace("Removed DBus watch for file descriptor %d",
179  dbus_watch_get_unix_fd(watch));
180  mainloop_del_fd((mainloop_io_t *) dbus_watch_get_data(watch));
181 }
182 
183 static void
184 register_watch_functions(DBusConnection *connection)
185 {
186  dbus_connection_set_watch_functions(connection, add_dbus_watch,
187  remove_dbus_watch,
188  toggle_dbus_watch, NULL, NULL);
189 }
190 
191 /*
192  * DBus main loop timeouts
193  *
194  * The DBus library allows the caller to register functions for the library to
195  * use for managing timers via a main loop.
196  */
197 
198 static gboolean
199 timer_popped(gpointer data)
200 {
201  crm_debug("%dms DBus timer expired",
202  dbus_timeout_get_interval((DBusTimeout *) data));
203  dbus_timeout_handle(data);
204  return FALSE;
205 }
206 
207 static dbus_bool_t
208 add_dbus_timer(DBusTimeout *timeout, void *data)
209 {
210  int interval_ms = dbus_timeout_get_interval(timeout);
211  guint id = g_timeout_add(interval_ms, timer_popped, timeout);
212 
213  if (id) {
214  dbus_timeout_set_data(timeout, GUINT_TO_POINTER(id), NULL);
215  }
216  crm_trace("Added %dms DBus timer", interval_ms);
217  return TRUE;
218 }
219 
220 static void
221 remove_dbus_timer(DBusTimeout *timeout, void *data)
222 {
223  void *vid = dbus_timeout_get_data(timeout);
224  guint id = GPOINTER_TO_UINT(vid);
225 
226  crm_trace("Removing %dms DBus timer", dbus_timeout_get_interval(timeout));
227  if (id) {
228  g_source_remove(id);
229  dbus_timeout_set_data(timeout, 0, NULL);
230  }
231 }
232 
233 static void
234 toggle_dbus_timer(DBusTimeout *timeout, void *data)
235 {
236  bool enabled = dbus_timeout_get_enabled(timeout);
237 
238  crm_trace("Toggling %dms DBus timer %s",
239  dbus_timeout_get_interval(timeout), (enabled? "off": "on"));
240  if (enabled) {
241  add_dbus_timer(timeout, data);
242  } else {
243  remove_dbus_timer(timeout, data);
244  }
245 }
246 
247 static void
248 register_timer_functions(DBusConnection *connection)
249 {
250  dbus_connection_set_timeout_functions(connection, add_dbus_timer,
251  remove_dbus_timer,
252  toggle_dbus_timer, NULL, NULL);
253 }
254 
255 /*
256  * General DBus utilities
257  */
258 
259 DBusConnection *
261 {
262  DBusError err;
263  DBusConnection *connection;
264 
265  dbus_error_init(&err);
266  connection = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
267  if (dbus_error_is_set(&err)) {
268  crm_err("Could not connect to DBus: %s", err.message);
269  dbus_error_free(&err);
270  return NULL;
271  }
272  if (connection == NULL) {
273  return NULL;
274  }
275 
276  /* Tell libdbus not to exit the process when a disconnect happens. This
277  * defaults to FALSE but is toggled on by the dbus_bus_get() call above.
278  */
279  dbus_connection_set_exit_on_disconnect(connection, FALSE);
280 
281  // Set custom handlers for various situations
282  register_timer_functions(connection);
283  register_watch_functions(connection);
284  dbus_connection_set_dispatch_status_function(connection,
285  update_dispatch_status,
286  NULL, NULL);
287 
288  // Call the dispatch function to check for any messages waiting already
289  update_dispatch_status(connection,
290  dbus_connection_get_dispatch_status(connection),
291  NULL);
292  return connection;
293 }
294 
295 void
296 pcmk_dbus_disconnect(DBusConnection *connection)
297 {
298  /* Per the DBus documentation, connections created with
299  * dbus_connection_open() are owned by libdbus and should never be closed.
300  *
301  * @TODO Should we call dbus_connection_unref() here?
302  */
303  return;
304 }
305 
306 // Custom DBus error names to use
307 #define ERR_NO_REQUEST "org.clusterlabs.pacemaker.NoRequest"
308 #define ERR_NO_REPLY "org.clusterlabs.pacemaker.NoReply"
309 #define ERR_INVALID_REPLY "org.clusterlabs.pacemaker.InvalidReply"
310 #define ERR_INVALID_REPLY_METHOD "org.clusterlabs.pacemaker.InvalidReply.Method"
311 #define ERR_INVALID_REPLY_SIGNAL "org.clusterlabs.pacemaker.InvalidReply.Signal"
312 #define ERR_INVALID_REPLY_TYPE "org.clusterlabs.pacemaker.InvalidReply.Type"
313 #define ERR_SEND_FAILED "org.clusterlabs.pacemaker.SendFailed"
314 
330 bool
331 pcmk_dbus_find_error(DBusPendingCall *pending, DBusMessage *reply,
332  DBusError *ret)
333 {
334  DBusError error;
335 
336  dbus_error_init(&error);
337 
338  if (pending == NULL) {
339  dbus_set_error_const(&error, ERR_NO_REQUEST, "No request sent");
340 
341  } else if (reply == NULL) {
342  dbus_set_error_const(&error, ERR_NO_REPLY, "No reply");
343 
344  } else {
345  DBusMessageIter args;
346  int dtype = dbus_message_get_type(reply);
347 
348  switch (dtype) {
349  case DBUS_MESSAGE_TYPE_METHOD_RETURN:
350  {
351  char *sig = NULL;
352 
353  dbus_message_iter_init(reply, &args);
354  crm_trace("Received DBus reply with argument type '%s'",
355  (sig = dbus_message_iter_get_signature(&args)));
356  if (sig != NULL) {
357  dbus_free(sig);
358  }
359  }
360  break;
361  case DBUS_MESSAGE_TYPE_INVALID:
362  dbus_set_error_const(&error, ERR_INVALID_REPLY,
363  "Invalid reply");
364  break;
365  case DBUS_MESSAGE_TYPE_METHOD_CALL:
366  dbus_set_error_const(&error, ERR_INVALID_REPLY_METHOD,
367  "Invalid reply (method call)");
368  break;
369  case DBUS_MESSAGE_TYPE_SIGNAL:
370  dbus_set_error_const(&error, ERR_INVALID_REPLY_SIGNAL,
371  "Invalid reply (signal)");
372  break;
373  case DBUS_MESSAGE_TYPE_ERROR:
374  dbus_set_error_from_message(&error, reply);
375  break;
376  default:
377  dbus_set_error(&error, ERR_INVALID_REPLY_TYPE,
378  "Unknown reply type %d", dtype);
379  }
380  }
381 
382  if (dbus_error_is_set(&error)) {
383  crm_trace("DBus reply indicated error '%s' (%s)",
384  error.name, error.message);
385  if (ret) {
386  dbus_error_init(ret);
387  dbus_move_error(&error, ret);
388  } else {
389  dbus_error_free(&error);
390  }
391  return TRUE;
392  }
393 
394  return FALSE;
395 }
396 
412 DBusMessage *
413 pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection,
414  DBusError *error, int timeout)
415 {
416  const char *method = NULL;
417  DBusMessage *reply = NULL;
418  DBusPendingCall* pending = NULL;
419 
420  CRM_ASSERT(dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_METHOD_CALL);
421  method = dbus_message_get_member (msg);
422 
423  /* Ensure caller can reliably check whether error is set */
424  if (error) {
425  dbus_error_init(error);
426  }
427 
428  if (timeout <= 0) {
429  /* DBUS_TIMEOUT_USE_DEFAULT (-1) tells DBus to use a sane default */
430  timeout = DBUS_TIMEOUT_USE_DEFAULT;
431  }
432 
433  // send message and get a handle for a reply
434  if (!dbus_connection_send_with_reply(connection, msg, &pending, timeout)) {
435  if (error) {
436  dbus_set_error(error, ERR_SEND_FAILED,
437  "Could not queue DBus '%s' request", method);
438  }
439  return NULL;
440  }
441 
442  dbus_connection_flush(connection);
443 
444  if (pending) {
445  /* block until we receive a reply */
446  dbus_pending_call_block(pending);
447 
448  /* get the reply message */
449  reply = dbus_pending_call_steal_reply(pending);
450  }
451 
452  (void) pcmk_dbus_find_error(pending, reply, error);
453 
454  if (pending) {
455  /* free the pending message handle */
456  dbus_pending_call_unref(pending);
457  }
458 
459  return reply;
460 }
461 
476 DBusPendingCall *
477 pcmk_dbus_send(DBusMessage *msg, DBusConnection *connection,
478  void (*done)(DBusPendingCall *pending, void *user_data),
479  void *user_data, int timeout)
480 {
481  const char *method = NULL;
482  DBusPendingCall* pending = NULL;
483 
484  CRM_ASSERT(done);
485  CRM_ASSERT(dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL);
486  method = dbus_message_get_member(msg);
487 
488  if (timeout <= 0) {
489  /* DBUS_TIMEOUT_USE_DEFAULT (-1) tells DBus to use a sane default */
490  timeout = DBUS_TIMEOUT_USE_DEFAULT;
491  }
492 
493  // send message and get a handle for a reply
494  if (!dbus_connection_send_with_reply(connection, msg, &pending, timeout)) {
495  crm_err("Could not send DBus %s message: failed", method);
496  return NULL;
497 
498  } else if (pending == NULL) {
499  crm_err("Could not send DBus %s message: connection may be closed",
500  method);
501  return NULL;
502  }
503 
504  if (dbus_pending_call_get_completed(pending)) {
505  crm_info("DBus %s message completed too soon", method);
506  /* Calling done() directly in this case instead of setting notify below
507  * breaks things
508  */
509  }
510  if (!dbus_pending_call_set_notify(pending, done, user_data, NULL)) {
511  return NULL;
512  }
513  return pending;
514 }
515 
516 bool
517 pcmk_dbus_type_check(DBusMessage *msg, DBusMessageIter *field, int expected,
518  const char *function, int line)
519 {
520  int dtype = 0;
521  DBusMessageIter lfield;
522 
523  if (field == NULL) {
524  if (dbus_message_iter_init(msg, &lfield)) {
525  field = &lfield;
526  }
527  }
528 
529  if (field == NULL) {
530  do_crm_log_alias(LOG_INFO, __FILE__, function, line,
531  "DBus reply has empty parameter list (expected '%c')",
532  expected);
533  return FALSE;
534  }
535 
536  dtype = dbus_message_iter_get_arg_type(field);
537 
538  if (dtype != expected) {
539  DBusMessageIter args;
540  char *sig;
541 
542  dbus_message_iter_init(msg, &args);
543  sig = dbus_message_iter_get_signature(&args);
544  do_crm_log_alias(LOG_INFO, __FILE__, function, line,
545  "DBus reply has unexpected type "
546  "(expected '%c' not '%c' in '%s')",
547  expected, dtype, sig);
548  dbus_free(sig);
549  return FALSE;
550  }
551 
552  return TRUE;
553 }
554 
555 
556 /*
557  * Property queries
558  */
559 
560 /* DBus APIs often provide queryable properties that use this standard
561  * interface. See:
562  * https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties
563  */
564 #define BUS_PROPERTY_IFACE "org.freedesktop.DBus.Properties"
565 
566 // Callback prototype for when a DBus property query result is received
567 typedef void (*property_callback_func)(const char *name, // Property name
568  const char *value, // Property value
569  void *userdata); // Caller-provided data
570 
571 // Data needed by DBus property queries
572 struct property_query {
573  char *name; // Property name being queried
574  char *target; // Name of DBus bus that query should be sent to
575  char *object; // DBus object path for object with the property
576  void *userdata; // Caller-provided data to supply to callback
577  property_callback_func callback; // Function to call when result is received
578 };
579 
580 static void
581 free_property_query(struct property_query *data)
582 {
583  free(data->target);
584  free(data->object);
585  free(data->name);
586  free(data);
587 }
588 
589 static char *
590 handle_query_result(DBusMessage *reply, struct property_query *data)
591 {
592  DBusError error;
593  char *output = NULL;
594  DBusMessageIter args;
595  DBusMessageIter variant_iter;
596  DBusBasicValue value;
597 
598  // First, check if the reply contains an error
599  if (pcmk_dbus_find_error((void*)&error, reply, &error)) {
600  crm_err("DBus query for %s property '%s' failed: %s",
601  data->object, data->name, error.message);
602  dbus_error_free(&error);
603  goto cleanup;
604  }
605 
606  // The lone output argument should be a DBus variant type
607  dbus_message_iter_init(reply, &args);
608  if (!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_VARIANT,
609  __func__, __LINE__)) {
610  crm_err("DBus query for %s property '%s' failed: Unexpected reply type",
611  data->object, data->name);
612  goto cleanup;
613  }
614 
615  // The variant should be a string
616  dbus_message_iter_recurse(&args, &variant_iter);
617  if (!pcmk_dbus_type_check(reply, &variant_iter, DBUS_TYPE_STRING,
618  __func__, __LINE__)) {
619  crm_err("DBus query for %s property '%s' failed: "
620  "Unexpected variant type", data->object, data->name);
621  goto cleanup;
622  }
623  dbus_message_iter_get_basic(&variant_iter, &value);
624 
625  // There should be no more arguments (in variant or reply)
626  dbus_message_iter_next(&variant_iter);
627  if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_INVALID) {
628  crm_err("DBus query for %s property '%s' failed: "
629  "Too many arguments in reply",
630  data->object, data->name);
631  goto cleanup;
632  }
633  dbus_message_iter_next(&args);
634  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_INVALID) {
635  crm_err("DBus query for %s property '%s' failed: "
636  "Too many arguments in reply", data->object, data->name);
637  goto cleanup;
638  }
639 
640  crm_trace("DBus query result for %s: %s='%s'",
641  data->object, data->name, (value.str? value.str : ""));
642 
643  if (data->callback) { // Query was asynchronous
644  data->callback(data->name, (value.str? value.str : ""), data->userdata);
645 
646  } else { // Query was synchronous
647  output = strdup(value.str? value.str : "");
648  }
649 
650  cleanup:
651  free_property_query(data);
652  return output;
653 }
654 
655 static void
656 async_query_result_cb(DBusPendingCall *pending, void *user_data)
657 {
658  DBusMessage *reply = NULL;
659  char *value = NULL;
660 
661  if (pending) {
662  reply = dbus_pending_call_steal_reply(pending);
663  }
664 
665  value = handle_query_result(reply, user_data);
666  free(value);
667 
668  if (reply) {
669  dbus_message_unref(reply);
670  }
671 }
672 
693 char *
694 pcmk_dbus_get_property(DBusConnection *connection, const char *target,
695  const char *obj, const gchar * iface, const char *name,
696  property_callback_func callback, void *userdata,
697  DBusPendingCall **pending, int timeout)
698 {
699  DBusMessage *msg;
700  char *output = NULL;
701  struct property_query *query_data = NULL;
702 
703  CRM_CHECK((connection != NULL) && (target != NULL) && (obj != NULL)
704  && (iface != NULL) && (name != NULL), return NULL);
705 
706  crm_trace("Querying DBus %s for %s property '%s'",
707  target, obj, name);
708 
709  // Create a new message to use to invoke method
710  msg = dbus_message_new_method_call(target, obj, BUS_PROPERTY_IFACE, "Get");
711  if (msg == NULL) {
712  crm_err("DBus query for %s property '%s' failed: "
713  "Unable to create message", obj, name);
714  return NULL;
715  }
716 
717  // Add the interface name and property name as message arguments
718  if (!dbus_message_append_args(msg,
719  DBUS_TYPE_STRING, &iface,
720  DBUS_TYPE_STRING, &name,
721  DBUS_TYPE_INVALID)) {
722  crm_err("DBus query for %s property '%s' failed: "
723  "Could not append arguments", obj, name);
724  dbus_message_unref(msg);
725  return NULL;
726  }
727 
728  query_data = malloc(sizeof(struct property_query));
729  if (query_data == NULL) {
730  crm_crit("DBus query for %s property '%s' failed: Out of memory",
731  obj, name);
732  dbus_message_unref(msg);
733  return NULL;
734  }
735 
736  query_data->target = strdup(target);
737  query_data->object = strdup(obj);
738  query_data->callback = callback;
739  query_data->userdata = userdata;
740  query_data->name = strdup(name);
741  CRM_CHECK((query_data->target != NULL)
742  && (query_data->object != NULL)
743  && (query_data->name != NULL),
744  free_property_query(query_data);
745  dbus_message_unref(msg);
746  return NULL);
747 
748  if (query_data->callback) { // Asynchronous
749  DBusPendingCall *local_pending;
750 
751  local_pending = pcmk_dbus_send(msg, connection, async_query_result_cb,
752  query_data, timeout);
753  if (local_pending == NULL) {
754  // async_query_result_cb() was not called in this case
755  free_property_query(query_data);
756  query_data = NULL;
757  }
758 
759  if (pending) {
760  *pending = local_pending;
761  }
762 
763  } else { // Synchronous
764  DBusMessage *reply = pcmk_dbus_send_recv(msg, connection, NULL,
765  timeout);
766 
767  output = handle_query_result(reply, query_data);
768 
769  if (reply) {
770  dbus_message_unref(reply);
771  }
772  }
773 
774  dbus_message_unref(msg);
775 
776  return output;
777 }
Services API.
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:218
A dumping ground.
#define ERR_INVALID_REPLY_SIGNAL
Definition: dbus.c:311
#define crm_crit(fmt, args...)
Definition: logging.h:349
char data[0]
Definition: cpg.c:55
mainloop_io_t * mainloop_add_fd(const char *name, int priority, int fd, void *userdata, struct mainloop_fd_callbacks *callbacks)
Definition: mainloop.c:975
#define BUS_PROPERTY_IFACE
Definition: dbus.c:564
#define ERR_INVALID_REPLY_TYPE
Definition: dbus.c:312
void pcmk_dbus_disconnect(DBusConnection *connection)
Definition: dbus.c:296
#define DBUS_TIMEOUT_USE_DEFAULT
Definition: pcmk-dbus.h:16
struct mainloop_io_s mainloop_io_t
Definition: mainloop.h:32
void(* property_callback_func)(const char *name, const char *value, void *userdata)
Definition: dbus.c:567
int(* dispatch)(gpointer userdata)
Dispatch function for mainloop file descriptor with data ready.
Definition: mainloop.h:137
#define do_crm_log_alias(level, file, function, line, fmt, args...)
Log a message as if it came from a different code location.
Definition: logging.h:273
bool pcmk_dbus_find_error(DBusPendingCall *pending, DBusMessage *reply, DBusError *ret)
Definition: dbus.c:331
#define ERR_NO_REPLY
Definition: dbus.c:308
#define ERR_SEND_FAILED
Definition: dbus.c:313
#define crm_debug(fmt, args...)
Definition: logging.h:355
#define crm_trace(fmt, args...)
Definition: logging.h:356
DBusPendingCall * pcmk_dbus_send(DBusMessage *msg, DBusConnection *connection, void(*done)(DBusPendingCall *pending, void *user_data), void *user_data, int timeout)
Definition: dbus.c:477
DBusConnection * pcmk_dbus_connect(void)
Definition: dbus.c:260
const char * target
Definition: pcmk_fence.c:29
#define ERR_INVALID_REPLY_METHOD
Definition: dbus.c:310
#define crm_err(fmt, args...)
Definition: logging.h:350
#define CRM_ASSERT(expr)
Definition: results.h:42
bool pcmk_dbus_type_check(DBusMessage *msg, DBusMessageIter *field, int expected, const char *function, int line)
Definition: dbus.c:517
void mainloop_del_fd(mainloop_io_t *client)
Definition: mainloop.c:1019
#define ERR_INVALID_REPLY
Definition: dbus.c:309
char * pcmk_dbus_get_property(DBusConnection *connection, const char *target, const char *obj, const gchar *iface, const char *name, property_callback_func callback, void *userdata, DBusPendingCall **pending, int timeout)
Definition: dbus.c:694
char * name
Definition: pcmk_fence.c:31
unsigned int timeout
Definition: pcmk_fence.c:32
DBusMessage * pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, DBusError *error, int timeout)
Definition: dbus.c:413
#define crm_info(fmt, args...)
Definition: logging.h:353
uint64_t flags
Definition: remote.c:149
#define ERR_NO_REQUEST
Definition: dbus.c:307