pacemaker  2.0.4-2deceaa
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ipc.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-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 
12 #if defined(US_AUTH_PEERCRED_UCRED) || defined(US_AUTH_PEERCRED_SOCKPEERCRED)
13 # ifdef US_AUTH_PEERCRED_UCRED
14 # ifndef _GNU_SOURCE
15 # define _GNU_SOURCE
16 # endif
17 # endif
18 # include <sys/socket.h>
19 #elif defined(US_AUTH_GETPEERUCRED)
20 # include <ucred.h>
21 #endif
22 
23 #include <sys/param.h>
24 
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <grp.h>
30 
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <bzlib.h>
34 
35 #include <crm/crm.h> /* indirectly: pcmk_err_generic */
36 #include <crm/msg_xml.h>
37 #include <crm/common/ipc.h>
39 
40 #include <crm/common/ipc_internal.h> /* PCMK__SPECIAL_PID* */
41 
42 #define PCMK_IPC_VERSION 1
43 
44 /* Evict clients whose event queue grows this large (by default) */
45 #define PCMK_IPC_DEFAULT_QUEUE_MAX 500
46 
47 struct crm_ipc_response_header {
48  struct qb_ipc_response_header qb;
49  uint32_t size_uncompressed;
50  uint32_t size_compressed;
51  uint32_t flags;
52  uint8_t version; /* Protect against version changes for anyone that might bother to statically link us */
53 };
54 
55 static int hdr_offset = 0;
56 static unsigned int ipc_buffer_max = 0;
57 static unsigned int pick_ipc_buffer(unsigned int max);
58 
59 static inline void
60 crm_ipc_init(void)
61 {
62  if (hdr_offset == 0) {
63  hdr_offset = sizeof(struct crm_ipc_response_header);
64  }
65  if (ipc_buffer_max == 0) {
66  ipc_buffer_max = pick_ipc_buffer(0);
67  }
68 }
69 
70 unsigned int
72 {
73  return pick_ipc_buffer(0);
74 }
75 
76 static char *
77 generateReference(const char *custom1, const char *custom2)
78 {
79  static uint ref_counter = 0;
80 
81  return crm_strdup_printf("%s-%s-%lld-%u",
82  (custom1? custom1 : "_empty_"),
83  (custom2? custom2 : "_empty_"),
84  (long long) time(NULL), ref_counter++);
85 }
86 
87 xmlNode *
88 create_request_adv(const char *task, xmlNode * msg_data,
89  const char *host_to, const char *sys_to,
90  const char *sys_from, const char *uuid_from, const char *origin)
91 {
92  char *true_from = NULL;
93  xmlNode *request = NULL;
94  char *reference = generateReference(task, sys_from);
95 
96  if (uuid_from != NULL) {
97  true_from = generate_hash_key(sys_from, uuid_from);
98  } else if (sys_from != NULL) {
99  true_from = strdup(sys_from);
100  } else {
101  crm_err("No sys from specified");
102  }
103 
104  // host_from will get set for us if necessary by the controller when routed
105  request = create_xml_node(NULL, __FUNCTION__);
106  crm_xml_add(request, F_CRM_ORIGIN, origin);
107  crm_xml_add(request, F_TYPE, T_CRM);
110  crm_xml_add(request, F_CRM_REFERENCE, reference);
111  crm_xml_add(request, F_CRM_TASK, task);
112  crm_xml_add(request, F_CRM_SYS_TO, sys_to);
113  crm_xml_add(request, F_CRM_SYS_FROM, true_from);
114 
115  /* HOSTTO will be ignored if it is to the DC anyway. */
116  if (host_to != NULL && strlen(host_to) > 0) {
117  crm_xml_add(request, F_CRM_HOST_TO, host_to);
118  }
119 
120  if (msg_data != NULL) {
121  add_message_xml(request, F_CRM_DATA, msg_data);
122  }
123  free(reference);
124  free(true_from);
125 
126  return request;
127 }
128 
129 /*
130  * This method adds a copy of xml_response_data
131  */
132 xmlNode *
133 create_reply_adv(xmlNode * original_request, xmlNode * xml_response_data, const char *origin)
134 {
135  xmlNode *reply = NULL;
136 
137  const char *host_from = crm_element_value(original_request, F_CRM_HOST_FROM);
138  const char *sys_from = crm_element_value(original_request, F_CRM_SYS_FROM);
139  const char *sys_to = crm_element_value(original_request, F_CRM_SYS_TO);
140  const char *type = crm_element_value(original_request, F_CRM_MSG_TYPE);
141  const char *operation = crm_element_value(original_request, F_CRM_TASK);
142  const char *crm_msg_reference = crm_element_value(original_request, F_CRM_REFERENCE);
143 
144  if (type == NULL) {
145  crm_err("Cannot create new_message, no message type in original message");
146  CRM_ASSERT(type != NULL);
147  return NULL;
148 #if 0
149  } else if (strcasecmp(XML_ATTR_REQUEST, type) != 0) {
150  crm_err("Cannot create new_message, original message was not a request");
151  return NULL;
152 #endif
153  }
154  reply = create_xml_node(NULL, __FUNCTION__);
155  if (reply == NULL) {
156  crm_err("Cannot create new_message, malloc failed");
157  return NULL;
158  }
159 
160  crm_xml_add(reply, F_CRM_ORIGIN, origin);
161  crm_xml_add(reply, F_TYPE, T_CRM);
164  crm_xml_add(reply, F_CRM_REFERENCE, crm_msg_reference);
165  crm_xml_add(reply, F_CRM_TASK, operation);
166 
167  /* since this is a reply, we reverse the from and to */
168  crm_xml_add(reply, F_CRM_SYS_TO, sys_from);
169  crm_xml_add(reply, F_CRM_SYS_FROM, sys_to);
170 
171  /* HOSTTO will be ignored if it is to the DC anyway. */
172  if (host_from != NULL && strlen(host_from) > 0) {
173  crm_xml_add(reply, F_CRM_HOST_TO, host_from);
174  }
175 
176  if (xml_response_data != NULL) {
177  add_message_xml(reply, F_CRM_DATA, xml_response_data);
178  }
179 
180  return reply;
181 }
182 
183 /* Libqb based IPC */
184 
185 /* Server... */
186 
187 static GHashTable *client_connections = NULL;
188 
195 guint
197 {
198  return client_connections? g_hash_table_size(client_connections) : 0;
199 }
200 
210 void
211 pcmk__foreach_ipc_client(GHFunc func, gpointer user_data)
212 {
213  if ((func != NULL) && (client_connections != NULL)) {
214  g_hash_table_foreach(client_connections, func, user_data);
215  }
216 }
217 
227 void
228 pcmk__foreach_ipc_client_remove(GHRFunc func, gpointer user_data)
229 {
230  if ((func != NULL) && (client_connections != NULL)) {
231  g_hash_table_foreach_remove(client_connections, func, user_data);
232  }
233 }
234 
236 pcmk__find_client(qb_ipcs_connection_t *c)
237 {
238  if (client_connections) {
239  return g_hash_table_lookup(client_connections, c);
240  }
241 
242  crm_trace("No client found for %p", c);
243  return NULL;
244 }
245 
247 pcmk__find_client_by_id(const char *id)
248 {
249  gpointer key;
250  pcmk__client_t *client;
251  GHashTableIter iter;
252 
253  if (client_connections && id) {
254  g_hash_table_iter_init(&iter, client_connections);
255  while (g_hash_table_iter_next(&iter, &key, (gpointer *) & client)) {
256  if (strcmp(client->id, id) == 0) {
257  return client;
258  }
259  }
260  }
261 
262  crm_trace("No client found with id=%s", id);
263  return NULL;
264 }
265 
266 const char *
268 {
269  if (c == NULL) {
270  return "null";
271  } else if (c->name == NULL && c->id == NULL) {
272  return "unknown";
273  } else if (c->name == NULL) {
274  return c->id;
275  } else {
276  return c->name;
277  }
278 }
279 
280 const char *
282 {
283  switch (client_type) {
284  case PCMK__CLIENT_IPC:
285  return "IPC";
286  case PCMK__CLIENT_TCP:
287  return "TCP";
288 #ifdef HAVE_GNUTLS_GNUTLS_H
289  case PCMK__CLIENT_TLS:
290  return "TLS";
291 #endif
292  default:
293  return "unknown";
294  }
295 }
296 
297 void
299 {
300  if (client_connections != NULL) {
301  int active = g_hash_table_size(client_connections);
302 
303  if (active) {
304  crm_err("Exiting with %d active IPC client%s",
305  active, pcmk__plural_s(active));
306  }
307  g_hash_table_destroy(client_connections); client_connections = NULL;
308  }
309 }
310 
311 void
312 pcmk__drop_all_clients(qb_ipcs_service_t *service)
313 {
314  qb_ipcs_connection_t *c = NULL;
315 
316  if (service == NULL) {
317  return;
318  }
319 
320  c = qb_ipcs_connection_first_get(service);
321 
322  while (c != NULL) {
323  qb_ipcs_connection_t *last = c;
324 
325  c = qb_ipcs_connection_next_get(service, last);
326 
327  /* There really shouldn't be anyone connected at this point */
328  crm_notice("Disconnecting client %p, pid=%d...",
329  last, pcmk__client_pid(last));
330  qb_ipcs_disconnect(last);
331  qb_ipcs_connection_unref(last);
332  }
333 }
334 
345 static pcmk__client_t *
346 client_from_connection(qb_ipcs_connection_t *c, void *key, uid_t uid_client)
347 {
348  pcmk__client_t *client = calloc(1, sizeof(pcmk__client_t));
349 
350  if (client == NULL) {
351  crm_perror(LOG_ERR, "Allocating client");
352  return NULL;
353  }
354 
355  if (c) {
356 #if ENABLE_ACL
357  client->user = pcmk__uid2username(uid_client);
358  if (client->user == NULL) {
359  client->user = strdup("#unprivileged");
360  CRM_CHECK(client->user != NULL, free(client); return NULL);
361  crm_err("Unable to enforce ACLs for user ID %d, assuming unprivileged",
362  uid_client);
363  }
364 #endif
365  client->ipcs = c;
366  client->kind = PCMK__CLIENT_IPC;
367  client->pid = pcmk__client_pid(c);
368  if (key == NULL) {
369  key = c;
370  }
371  }
372 
373  client->id = crm_generate_uuid();
374  if (client->id == NULL) {
375  crm_err("Could not generate UUID for client");
376  free(client->user);
377  free(client);
378  return NULL;
379  }
380  if (key == NULL) {
381  key = client->id;
382  }
383  if (client_connections == NULL) {
384  crm_trace("Creating IPC client table");
385  client_connections = g_hash_table_new(g_direct_hash, g_direct_equal);
386  }
387  g_hash_table_insert(client_connections, key, client);
388  return client;
389 }
390 
400 {
401  pcmk__client_t *client = client_from_connection(NULL, key, 0);
402 
403  CRM_ASSERT(client != NULL);
404  return client;
405 }
406 
408 pcmk__new_client(qb_ipcs_connection_t *c, uid_t uid_client, gid_t gid_client)
409 {
410  gid_t uid_cluster = 0;
411  gid_t gid_cluster = 0;
412 
413  pcmk__client_t *client = NULL;
414 
415  CRM_CHECK(c != NULL, return NULL);
416 
417  if (pcmk_daemon_user(&uid_cluster, &gid_cluster) < 0) {
418  static bool need_log = TRUE;
419 
420  if (need_log) {
421  crm_warn("Could not find user and group IDs for user %s",
423  need_log = FALSE;
424  }
425  }
426 
427  if (uid_client != 0) {
428  crm_trace("Giving group %u access to new IPC connection", gid_cluster);
429  /* Passing -1 to chown(2) means don't change */
430  qb_ipcs_connection_auth_set(c, -1, gid_cluster, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
431  }
432 
433  /* TODO: Do our own auth checking, return NULL if unauthorized */
434  client = client_from_connection(c, NULL, uid_client);
435  if (client == NULL) {
436  return NULL;
437  }
438 
439  if ((uid_client == 0) || (uid_client == uid_cluster)) {
440  /* Remember when a connection came from root or hacluster */
442  }
443 
444  crm_debug("New IPC client %s for PID %u with uid %d and gid %d",
445  client->id, client->pid, uid_client, gid_client);
446  return client;
447 }
448 
449 static struct iovec *
450 pcmk__new_ipc_event(void)
451 {
452  struct iovec *iov = calloc(2, sizeof(struct iovec));
453 
454  CRM_ASSERT(iov != NULL);
455  return iov;
456 }
457 
463 void
464 pcmk_free_ipc_event(struct iovec *event)
465 {
466  if (event != NULL) {
467  free(event[0].iov_base);
468  free(event[1].iov_base);
469  free(event);
470  }
471 }
472 
473 static void
474 free_event(gpointer data)
475 {
476  pcmk_free_ipc_event((struct iovec *) data);
477 }
478 
479 static void
480 add_event(pcmk__client_t *c, struct iovec *iov)
481 {
482  if (c->event_queue == NULL) {
483  c->event_queue = g_queue_new();
484  }
485  g_queue_push_tail(c->event_queue, iov);
486 }
487 
488 void
490 {
491  if (c == NULL) {
492  return;
493  }
494 
495  if (client_connections) {
496  if (c->ipcs) {
497  crm_trace("Destroying %p/%p (%d remaining)",
498  c, c->ipcs, g_hash_table_size(client_connections) - 1);
499  g_hash_table_remove(client_connections, c->ipcs);
500 
501  } else {
502  crm_trace("Destroying remote connection %p (%d remaining)",
503  c, g_hash_table_size(client_connections) - 1);
504  g_hash_table_remove(client_connections, c->id);
505  }
506  }
507 
508  if (c->event_timer) {
509  g_source_remove(c->event_timer);
510  }
511 
512  if (c->event_queue) {
513  crm_debug("Destroying %d events", g_queue_get_length(c->event_queue));
514  g_queue_free_full(c->event_queue, free_event);
515  }
516 
517  free(c->id);
518  free(c->name);
519  free(c->user);
520  if (c->remote) {
521  if (c->remote->auth_timeout) {
522  g_source_remove(c->remote->auth_timeout);
523  }
524  free(c->remote->buffer);
525  free(c->remote);
526  }
527  free(c);
528 }
529 
539 bool
540 pcmk__set_client_queue_max(pcmk__client_t *client, const char *qmax)
541 {
542  if (is_set(client->flags, pcmk__client_privileged)) {
543  long long qmax_int;
544 
545  errno = 0;
546  qmax_int = crm_parse_ll(qmax, NULL);
547  if ((errno == 0) && (qmax_int > 0)) {
548  client->queue_max = (unsigned int) qmax_int;
549  return TRUE;
550  }
551  }
552  return FALSE;
553 }
554 
555 int
556 pcmk__client_pid(qb_ipcs_connection_t *c)
557 {
558  struct qb_ipcs_connection_stats stats;
559 
560  stats.client_pid = 0;
561  qb_ipcs_connection_stats_get(c, &stats, 0);
562  return stats.client_pid;
563 }
564 
576 xmlNode *
577 pcmk__client_data2xml(pcmk__client_t *c, void *data, uint32_t *id,
578  uint32_t *flags)
579 {
580  xmlNode *xml = NULL;
581  char *uncompressed = NULL;
582  char *text = ((char *)data) + sizeof(struct crm_ipc_response_header);
583  struct crm_ipc_response_header *header = data;
584 
585  if (id) {
586  *id = ((struct qb_ipc_response_header *)data)->id;
587  }
588  if (flags) {
589  *flags = header->flags;
590  }
591 
592  if (is_set(header->flags, crm_ipc_proxied)) {
593  /* Mark this client as being the endpoint of a proxy connection.
594  * Proxy connections responses are sent on the event channel, to avoid
595  * blocking the controller serving as proxy.
596  */
598  }
599 
600  if(header->version > PCMK_IPC_VERSION) {
601  crm_err("Filtering incompatible v%d IPC message, we only support versions <= %d",
602  header->version, PCMK_IPC_VERSION);
603  return NULL;
604  }
605 
606  if (header->size_compressed) {
607  int rc = 0;
608  unsigned int size_u = 1 + header->size_uncompressed;
609  uncompressed = calloc(1, size_u);
610 
611  crm_trace("Decompressing message data %u bytes into %u bytes",
612  header->size_compressed, size_u);
613 
614  rc = BZ2_bzBuffToBuffDecompress(uncompressed, &size_u, text, header->size_compressed, 1, 0);
615  text = uncompressed;
616 
617  if (rc != BZ_OK) {
618  crm_err("Decompression failed: %s " CRM_XS " bzerror=%d",
619  bz2_strerror(rc), rc);
620  free(uncompressed);
621  return NULL;
622  }
623  }
624 
625  CRM_ASSERT(text[header->size_uncompressed - 1] == 0);
626 
627  xml = string2xml(text);
628  crm_log_xml_trace(xml, "[IPC received]");
629 
630  free(uncompressed);
631  return xml;
632 }
633 
634 static int crm_ipcs_flush_events(pcmk__client_t *c);
635 
636 static gboolean
637 crm_ipcs_flush_events_cb(gpointer data)
638 {
639  pcmk__client_t *c = data;
640 
641  c->event_timer = 0;
642  crm_ipcs_flush_events(c);
643  return FALSE;
644 }
645 
653 static inline void
654 delay_next_flush(pcmk__client_t *c, unsigned int queue_len)
655 {
656  /* Delay a maximum of 1.5 seconds */
657  guint delay = (queue_len < 5)? (1000 + 100 * queue_len) : 1500;
658 
659  c->event_timer = g_timeout_add(delay, crm_ipcs_flush_events_cb, c);
660 }
661 
670 static int
671 crm_ipcs_flush_events(pcmk__client_t *c)
672 {
673  int rc = pcmk_rc_ok;
674  ssize_t qb_rc = 0;
675  unsigned int sent = 0;
676  unsigned int queue_len = 0;
677 
678  if (c == NULL) {
679  return rc;
680 
681  } else if (c->event_timer) {
682  /* There is already a timer, wait until it goes off */
683  crm_trace("Timer active for %p - %d", c->ipcs, c->event_timer);
684  return rc;
685  }
686 
687  if (c->event_queue) {
688  queue_len = g_queue_get_length(c->event_queue);
689  }
690  while (sent < 100) {
691  struct crm_ipc_response_header *header = NULL;
692  struct iovec *event = NULL;
693 
694  if (c->event_queue) {
695  // We don't pop unless send is successful
696  event = g_queue_peek_head(c->event_queue);
697  }
698  if (event == NULL) { // Queue is empty
699  break;
700  }
701 
702  qb_rc = qb_ipcs_event_sendv(c->ipcs, event, 2);
703  if (qb_rc < 0) {
704  rc = (int) -qb_rc;
705  break;
706  }
707  event = g_queue_pop_head(c->event_queue);
708 
709  sent++;
710  header = event[0].iov_base;
711  if (header->size_compressed) {
712  crm_trace("Event %d to %p[%d] (%lld compressed bytes) sent",
713  header->qb.id, c->ipcs, c->pid, (long long) qb_rc);
714  } else {
715  crm_trace("Event %d to %p[%d] (%lld bytes) sent: %.120s",
716  header->qb.id, c->ipcs, c->pid, (long long) qb_rc,
717  (char *) (event[1].iov_base));
718  }
719  pcmk_free_ipc_event(event);
720  }
721 
722  queue_len -= sent;
723  if (sent > 0 || queue_len) {
724  crm_trace("Sent %d events (%d remaining) for %p[%d]: %s (%lld)",
725  sent, queue_len, c->ipcs, c->pid,
726  pcmk_rc_str(rc), (long long) qb_rc);
727  }
728 
729  if (queue_len) {
730 
731  /* Allow clients to briefly fall behind on processing incoming messages,
732  * but drop completely unresponsive clients so the connection doesn't
733  * consume resources indefinitely.
734  */
735  if (queue_len > QB_MAX(c->queue_max, PCMK_IPC_DEFAULT_QUEUE_MAX)) {
736  if ((c->queue_backlog <= 1) || (queue_len < c->queue_backlog)) {
737  /* Don't evict for a new or shrinking backlog */
738  crm_warn("Client with process ID %u has a backlog of %u messages "
739  CRM_XS " %p", c->pid, queue_len, c->ipcs);
740  } else {
741  crm_err("Evicting client with process ID %u due to backlog of %u messages "
742  CRM_XS " %p", c->pid, queue_len, c->ipcs);
743  c->queue_backlog = 0;
744  qb_ipcs_disconnect(c->ipcs);
745  return rc;
746  }
747  }
748 
749  c->queue_backlog = queue_len;
750  delay_next_flush(c, queue_len);
751 
752  } else {
753  /* Event queue is empty, there is no backlog */
754  c->queue_backlog = 0;
755  }
756 
757  return rc;
758 }
759 
772 int
773 pcmk__ipc_prepare_iov(uint32_t request, xmlNode *message,
774  uint32_t max_send_size, struct iovec **result,
775  ssize_t *bytes)
776 {
777  static unsigned int biggest = 0;
778  struct iovec *iov;
779  unsigned int total = 0;
780  char *compressed = NULL;
781  char *buffer = NULL;
782  struct crm_ipc_response_header *header = NULL;
783 
784  if ((message == NULL) || (result == NULL)) {
785  return EINVAL;
786  }
787 
788  header = calloc(1, sizeof(struct crm_ipc_response_header));
789  if (header == NULL) {
790  return ENOMEM; /* errno mightn't be set by allocator */
791  }
792 
793  buffer = dump_xml_unformatted(message);
794  crm_ipc_init();
795 
796  if (max_send_size == 0) {
797  max_send_size = ipc_buffer_max;
798  }
799  CRM_LOG_ASSERT(max_send_size != 0);
800 
801  *result = NULL;
802  iov = pcmk__new_ipc_event();
803  iov[0].iov_len = hdr_offset;
804  iov[0].iov_base = header;
805 
806  header->version = PCMK_IPC_VERSION;
807  header->size_uncompressed = 1 + strlen(buffer);
808  total = iov[0].iov_len + header->size_uncompressed;
809 
810  if (total < max_send_size) {
811  iov[1].iov_base = buffer;
812  iov[1].iov_len = header->size_uncompressed;
813 
814  } else {
815  unsigned int new_size = 0;
816 
817  if (pcmk__compress(buffer, (unsigned int) header->size_uncompressed,
818  (unsigned int) max_send_size, &compressed,
819  &new_size) == pcmk_rc_ok) {
820 
821  header->flags |= crm_ipc_compressed;
822  header->size_compressed = new_size;
823 
824  iov[1].iov_len = header->size_compressed;
825  iov[1].iov_base = compressed;
826 
827  free(buffer);
828 
829  biggest = QB_MAX(header->size_compressed, biggest);
830 
831  } else {
832  crm_log_xml_trace(message, "EMSGSIZE");
833  biggest = QB_MAX(header->size_uncompressed, biggest);
834 
835  crm_err("Could not compress %u-byte message into less than IPC "
836  "limit of %u bytes; set PCMK_ipc_buffer to higher value "
837  "(%u bytes suggested)",
838  header->size_uncompressed, max_send_size, 4 * biggest);
839 
840  free(compressed);
841  free(buffer);
842  pcmk_free_ipc_event(iov);
843  return EMSGSIZE;
844  }
845  }
846 
847  header->qb.size = iov[0].iov_len + iov[1].iov_len;
848  header->qb.id = (int32_t)request; /* Replying to a specific request */
849 
850  *result = iov;
851  CRM_ASSERT(header->qb.size > 0);
852  if (bytes != NULL) {
853  *bytes = header->qb.size;
854  }
855  return pcmk_rc_ok;
856 }
857 
858 int
859 pcmk__ipc_send_iov(pcmk__client_t *c, struct iovec *iov, uint32_t flags)
860 {
861  int rc = pcmk_rc_ok;
862  static uint32_t id = 1;
863  struct crm_ipc_response_header *header = iov[0].iov_base;
864 
865  if (c->flags & pcmk__client_proxied) {
866  /* _ALL_ replies to proxied connections need to be sent as events */
867  if (is_not_set(flags, crm_ipc_server_event)) {
868  flags |= crm_ipc_server_event;
869  /* this flag lets us know this was originally meant to be a response.
870  * even though we're sending it over the event channel. */
872  }
873  }
874 
875  header->flags |= flags;
876  if (flags & crm_ipc_server_event) {
877  header->qb.id = id++; /* We don't really use it, but doesn't hurt to set one */
878 
879  if (flags & crm_ipc_server_free) {
880  crm_trace("Sending the original to %p[%d]", c->ipcs, c->pid);
881  add_event(c, iov);
882 
883  } else {
884  struct iovec *iov_copy = pcmk__new_ipc_event();
885 
886  crm_trace("Sending a copy to %p[%d]", c->ipcs, c->pid);
887  iov_copy[0].iov_len = iov[0].iov_len;
888  iov_copy[0].iov_base = malloc(iov[0].iov_len);
889  memcpy(iov_copy[0].iov_base, iov[0].iov_base, iov[0].iov_len);
890 
891  iov_copy[1].iov_len = iov[1].iov_len;
892  iov_copy[1].iov_base = malloc(iov[1].iov_len);
893  memcpy(iov_copy[1].iov_base, iov[1].iov_base, iov[1].iov_len);
894 
895  add_event(c, iov_copy);
896  }
897 
898  } else {
899  ssize_t qb_rc;
900 
901  CRM_LOG_ASSERT(header->qb.id != 0); /* Replying to a specific request */
902 
903  qb_rc = qb_ipcs_response_sendv(c->ipcs, iov, 2);
904  if (qb_rc < header->qb.size) {
905  if (qb_rc < 0) {
906  rc = (int) -qb_rc;
907  }
908  crm_notice("Response %d to pid %d failed: %s "
909  CRM_XS " bytes=%u rc=%lld ipcs=%p",
910  header->qb.id, c->pid, pcmk_rc_str(rc),
911  header->qb.size, (long long) qb_rc, c->ipcs);
912 
913  } else {
914  crm_trace("Response %d sent, %lld bytes to %p[%d]",
915  header->qb.id, (long long) qb_rc, c->ipcs, c->pid);
916  }
917 
918  if (flags & crm_ipc_server_free) {
919  pcmk_free_ipc_event(iov);
920  }
921  }
922 
923  if (flags & crm_ipc_server_event) {
924  rc = crm_ipcs_flush_events(c);
925  } else {
926  crm_ipcs_flush_events(c);
927  }
928 
929  if ((rc == EPIPE) || (rc == ENOTCONN)) {
930  crm_trace("Client %p disconnected", c->ipcs);
931  }
932  return rc;
933 }
934 
935 int
936 pcmk__ipc_send_xml(pcmk__client_t *c, uint32_t request, xmlNode *message,
937  uint32_t flags)
938 {
939  struct iovec *iov = NULL;
940  int rc = pcmk_rc_ok;
941 
942  if (c == NULL) {
943  return EINVAL;
944  }
945  crm_ipc_init();
946  rc = pcmk__ipc_prepare_iov(request, message, ipc_buffer_max, &iov, NULL);
947  if (rc == pcmk_rc_ok) {
948  rc = pcmk__ipc_send_iov(c, iov, flags | crm_ipc_server_free);
949  } else {
950  pcmk_free_ipc_event(iov);
951  crm_notice("IPC message to pid %d failed: %s " CRM_XS " rc=%d",
952  c->pid, pcmk_rc_str(rc), rc);
953  }
954  return rc;
955 }
956 
957 void
958 pcmk__ipc_send_ack_as(const char *function, int line, pcmk__client_t *c,
959  uint32_t request, uint32_t flags, const char *tag)
960 {
961  if (flags & crm_ipc_client_response) {
962  xmlNode *ack = create_xml_node(NULL, tag);
963 
964  crm_trace("Ack'ing IPC message from %s", pcmk__client_name(c));
965  c->request_id = 0;
966  crm_xml_add(ack, "function", function);
967  crm_xml_add_int(ack, "line", line);
968  pcmk__ipc_send_xml(c, request, ack, flags);
969  free_xml(ack);
970  }
971 }
972 
985 void pcmk__serve_based_ipc(qb_ipcs_service_t **ipcs_ro,
986  qb_ipcs_service_t **ipcs_rw,
987  qb_ipcs_service_t **ipcs_shm,
988  struct qb_ipcs_service_handlers *ro_cb,
989  struct qb_ipcs_service_handlers *rw_cb)
990 {
992  QB_IPC_NATIVE, ro_cb);
993 
995  QB_IPC_NATIVE, rw_cb);
996 
998  QB_IPC_SHM, rw_cb);
999 
1000  if (*ipcs_ro == NULL || *ipcs_rw == NULL || *ipcs_shm == NULL) {
1001  crm_err("Failed to create the CIB manager: exiting and inhibiting respawn");
1002  crm_warn("Verify pacemaker and pacemaker_remote are not both enabled");
1004  }
1005 }
1006 
1018 void
1019 pcmk__stop_based_ipc(qb_ipcs_service_t *ipcs_ro,
1020  qb_ipcs_service_t *ipcs_rw,
1021  qb_ipcs_service_t *ipcs_shm)
1022 {
1023  qb_ipcs_destroy(ipcs_ro);
1024  qb_ipcs_destroy(ipcs_rw);
1025  qb_ipcs_destroy(ipcs_shm);
1026 }
1027 
1036 qb_ipcs_service_t *
1037 pcmk__serve_controld_ipc(struct qb_ipcs_service_handlers *cb)
1038 {
1039  return mainloop_add_ipc_server(CRM_SYSTEM_CRMD, QB_IPC_NATIVE, cb);
1040 }
1041 
1050 void
1051 pcmk__serve_attrd_ipc(qb_ipcs_service_t **ipcs,
1052  struct qb_ipcs_service_handlers *cb)
1053 {
1054  *ipcs = mainloop_add_ipc_server(T_ATTRD, QB_IPC_NATIVE, cb);
1055 
1056  if (*ipcs == NULL) {
1057  crm_err("Failed to create pacemaker-attrd server: exiting and inhibiting respawn");
1058  crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
1060  }
1061 }
1062 
1071 void
1072 pcmk__serve_fenced_ipc(qb_ipcs_service_t **ipcs,
1073  struct qb_ipcs_service_handlers *cb)
1074 {
1075  *ipcs = mainloop_add_ipc_server_with_prio("stonith-ng", QB_IPC_NATIVE, cb,
1076  QB_LOOP_HIGH);
1077 
1078  if (*ipcs == NULL) {
1079  crm_err("Failed to create fencer: exiting and inhibiting respawn.");
1080  crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
1082  }
1083 }
1084 
1085 /* Client... */
1086 
1087 #define MIN_MSG_SIZE 12336 /* sizeof(struct qb_ipc_connection_response) */
1088 #define MAX_MSG_SIZE 128*1024 /* 128k default */
1089 
1090 struct crm_ipc_s {
1091  struct pollfd pfd;
1092 
1093  /* the max size we can send/receive over ipc */
1094  unsigned int max_buf_size;
1095  /* Size of the allocated 'buffer' */
1096  unsigned int buf_size;
1097  int msg_size;
1098  int need_reply;
1099  char *buffer;
1100  char *name;
1101 
1102  qb_ipcc_connection_t *ipc;
1103 
1104 };
1105 
1106 static unsigned int
1107 pick_ipc_buffer(unsigned int max)
1108 {
1109  static unsigned int global_max = 0;
1110 
1111  if (global_max == 0) {
1112  const char *env = getenv("PCMK_ipc_buffer");
1113 
1114  if (env) {
1115  int env_max = crm_parse_int(env, "0");
1116 
1117  global_max = (env_max > 0)? QB_MAX(MIN_MSG_SIZE, env_max) : MAX_MSG_SIZE;
1118 
1119  } else {
1120  global_max = MAX_MSG_SIZE;
1121  }
1122  }
1123 
1124  return QB_MAX(max, global_max);
1125 }
1126 
1127 crm_ipc_t *
1128 crm_ipc_new(const char *name, size_t max_size)
1129 {
1130  crm_ipc_t *client = NULL;
1131 
1132  client = calloc(1, sizeof(crm_ipc_t));
1133 
1134  client->name = strdup(name);
1135  client->buf_size = pick_ipc_buffer(max_size);
1136  client->buffer = malloc(client->buf_size);
1137 
1138  /* Clients initiating connection pick the max buf size */
1139  client->max_buf_size = client->buf_size;
1140 
1141  client->pfd.fd = -1;
1142  client->pfd.events = POLLIN;
1143  client->pfd.revents = 0;
1144 
1145  return client;
1146 }
1147 
1157 bool
1159 {
1160  uid_t cl_uid = 0;
1161  gid_t cl_gid = 0;
1162  pid_t found_pid = 0; uid_t found_uid = 0; gid_t found_gid = 0;
1163  int rv;
1164 
1165  client->need_reply = FALSE;
1166  client->ipc = qb_ipcc_connect(client->name, client->buf_size);
1167 
1168  if (client->ipc == NULL) {
1169  crm_debug("Could not establish %s connection: %s (%d)", client->name, pcmk_strerror(errno), errno);
1170  return FALSE;
1171  }
1172 
1173  client->pfd.fd = crm_ipc_get_fd(client);
1174  if (client->pfd.fd < 0) {
1175  rv = errno;
1176  /* message already omitted */
1177  crm_ipc_close(client);
1178  errno = rv;
1179  return FALSE;
1180  }
1181 
1182  rv = pcmk_daemon_user(&cl_uid, &cl_gid);
1183  if (rv < 0) {
1184  /* message already omitted */
1185  crm_ipc_close(client);
1186  errno = -rv;
1187  return FALSE;
1188  }
1189 
1190  if (!(rv = crm_ipc_is_authentic_process(client->pfd.fd, cl_uid, cl_gid,
1191  &found_pid, &found_uid,
1192  &found_gid))) {
1193  crm_err("Daemon (IPC %s) is not authentic:"
1194  " process %lld (uid: %lld, gid: %lld)",
1195  client->name, (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
1196  (long long) found_uid, (long long) found_gid);
1197  crm_ipc_close(client);
1198  errno = ECONNABORTED;
1199  return FALSE;
1200 
1201  } else if (rv < 0) {
1202  errno = -rv;
1203  crm_perror(LOG_ERR, "Could not verify authenticity of daemon (IPC %s)",
1204  client->name);
1205  crm_ipc_close(client);
1206  errno = -rv;
1207  return FALSE;
1208  }
1209 
1210  qb_ipcc_context_set(client->ipc, client);
1211 
1212 #ifdef HAVE_IPCS_GET_BUFFER_SIZE
1213  client->max_buf_size = qb_ipcc_get_buffer_size(client->ipc);
1214  if (client->max_buf_size > client->buf_size) {
1215  free(client->buffer);
1216  client->buffer = calloc(1, client->max_buf_size);
1217  client->buf_size = client->max_buf_size;
1218  }
1219 #endif
1220 
1221  return TRUE;
1222 }
1223 
1224 void
1226 {
1227  if (client) {
1228  crm_trace("Disconnecting %s IPC connection %p (%p)", client->name, client, client->ipc);
1229 
1230  if (client->ipc) {
1231  qb_ipcc_connection_t *ipc = client->ipc;
1232 
1233  client->ipc = NULL;
1234  qb_ipcc_disconnect(ipc);
1235  }
1236  }
1237 }
1238 
1239 void
1241 {
1242  if (client) {
1243  if (client->ipc && qb_ipcc_is_connected(client->ipc)) {
1244  crm_notice("Destroying an active IPC connection to %s", client->name);
1245  /* The next line is basically unsafe
1246  *
1247  * If this connection was attached to mainloop and mainloop is active,
1248  * the 'disconnected' callback will end up back here and we'll end
1249  * up free'ing the memory twice - something that can still happen
1250  * even without this if we destroy a connection and it closes before
1251  * we call exit
1252  */
1253  /* crm_ipc_close(client); */
1254  }
1255  crm_trace("Destroying IPC connection to %s: %p", client->name, client);
1256  free(client->buffer);
1257  free(client->name);
1258  free(client);
1259  }
1260 }
1261 
1262 int
1264 {
1265  int fd = 0;
1266 
1267  if (client && client->ipc && (qb_ipcc_fd_get(client->ipc, &fd) == 0)) {
1268  return fd;
1269  }
1270  errno = EINVAL;
1271  crm_perror(LOG_ERR, "Could not obtain file IPC descriptor for %s",
1272  (client? client->name : "unspecified client"));
1273  return -errno;
1274 }
1275 
1276 bool
1278 {
1279  bool rc = FALSE;
1280 
1281  if (client == NULL) {
1282  crm_trace("No client");
1283  return FALSE;
1284 
1285  } else if (client->ipc == NULL) {
1286  crm_trace("No connection");
1287  return FALSE;
1288 
1289  } else if (client->pfd.fd < 0) {
1290  crm_trace("Bad descriptor");
1291  return FALSE;
1292  }
1293 
1294  rc = qb_ipcc_is_connected(client->ipc);
1295  if (rc == FALSE) {
1296  client->pfd.fd = -EINVAL;
1297  }
1298  return rc;
1299 }
1300 
1308 int
1310 {
1311  int rc;
1312 
1313  CRM_ASSERT(client != NULL);
1314 
1315  if (crm_ipc_connected(client) == FALSE) {
1316  return -ENOTCONN;
1317  }
1318 
1319  client->pfd.revents = 0;
1320  rc = poll(&(client->pfd), 1, 0);
1321  return (rc < 0)? -errno : rc;
1322 }
1323 
1324 // \return Standard Pacemaker return code
1325 static int
1326 crm_ipc_decompress(crm_ipc_t * client)
1327 {
1328  struct crm_ipc_response_header *header = (struct crm_ipc_response_header *)(void*)client->buffer;
1329 
1330  if (header->size_compressed) {
1331  int rc = 0;
1332  unsigned int size_u = 1 + header->size_uncompressed;
1333  /* never let buf size fall below our max size required for ipc reads. */
1334  unsigned int new_buf_size = QB_MAX((hdr_offset + size_u), client->max_buf_size);
1335  char *uncompressed = calloc(1, new_buf_size);
1336 
1337  crm_trace("Decompressing message data %u bytes into %u bytes",
1338  header->size_compressed, size_u);
1339 
1340  rc = BZ2_bzBuffToBuffDecompress(uncompressed + hdr_offset, &size_u,
1341  client->buffer + hdr_offset, header->size_compressed, 1, 0);
1342 
1343  if (rc != BZ_OK) {
1344  crm_err("Decompression failed: %s " CRM_XS " bzerror=%d",
1345  bz2_strerror(rc), rc);
1346  free(uncompressed);
1347  return EILSEQ;
1348  }
1349 
1350  /*
1351  * This assert no longer holds true. For an identical msg, some clients may
1352  * require compression, and others may not. If that same msg (event) is sent
1353  * to multiple clients, it could result in some clients receiving a compressed
1354  * msg even though compression was not explicitly required for them.
1355  *
1356  * CRM_ASSERT((header->size_uncompressed + hdr_offset) >= ipc_buffer_max);
1357  */
1358  CRM_ASSERT(size_u == header->size_uncompressed);
1359 
1360  memcpy(uncompressed, client->buffer, hdr_offset); /* Preserve the header */
1361  header = (struct crm_ipc_response_header *)(void*)uncompressed;
1362 
1363  free(client->buffer);
1364  client->buf_size = new_buf_size;
1365  client->buffer = uncompressed;
1366  }
1367 
1368  CRM_ASSERT(client->buffer[hdr_offset + header->size_uncompressed - 1] == 0);
1369  return pcmk_rc_ok;
1370 }
1371 
1372 long
1374 {
1375  struct crm_ipc_response_header *header = NULL;
1376 
1377  CRM_ASSERT(client != NULL);
1378  CRM_ASSERT(client->ipc != NULL);
1379  CRM_ASSERT(client->buffer != NULL);
1380 
1381  crm_ipc_init();
1382 
1383  client->buffer[0] = 0;
1384  client->msg_size = qb_ipcc_event_recv(client->ipc, client->buffer,
1385  client->buf_size, 0);
1386  if (client->msg_size >= 0) {
1387  int rc = crm_ipc_decompress(client);
1388 
1389  if (rc != pcmk_rc_ok) {
1390  return pcmk_rc2legacy(rc);
1391  }
1392 
1393  header = (struct crm_ipc_response_header *)(void*)client->buffer;
1394  if(header->version > PCMK_IPC_VERSION) {
1395  crm_err("Filtering incompatible v%d IPC message, we only support versions <= %d",
1396  header->version, PCMK_IPC_VERSION);
1397  return -EBADMSG;
1398  }
1399 
1400  crm_trace("Received %s event %d, size=%u, rc=%d, text: %.100s",
1401  client->name, header->qb.id, header->qb.size, client->msg_size,
1402  client->buffer + hdr_offset);
1403 
1404  } else {
1405  crm_trace("No message from %s received: %s", client->name, pcmk_strerror(client->msg_size));
1406  }
1407 
1408  if (crm_ipc_connected(client) == FALSE || client->msg_size == -ENOTCONN) {
1409  crm_err("Connection to %s failed", client->name);
1410  }
1411 
1412  if (header) {
1413  /* Data excluding the header */
1414  return header->size_uncompressed;
1415  }
1416  return -ENOMSG;
1417 }
1418 
1419 const char *
1421 {
1422  CRM_ASSERT(client != NULL);
1423  return client->buffer + sizeof(struct crm_ipc_response_header);
1424 }
1425 
1426 uint32_t
1428 {
1429  struct crm_ipc_response_header *header = NULL;
1430 
1431  CRM_ASSERT(client != NULL);
1432  if (client->buffer == NULL) {
1433  return 0;
1434  }
1435 
1436  header = (struct crm_ipc_response_header *)(void*)client->buffer;
1437  return header->flags;
1438 }
1439 
1440 const char *
1442 {
1443  CRM_ASSERT(client != NULL);
1444  return client->name;
1445 }
1446 
1447 // \return Standard Pacemaker return code
1448 static int
1449 internal_ipc_get_reply(crm_ipc_t *client, int request_id, int ms_timeout,
1450  ssize_t *bytes)
1451 {
1452  time_t timeout = time(NULL) + 1 + (ms_timeout / 1000);
1453  int rc = pcmk_rc_ok;
1454 
1455  crm_ipc_init();
1456 
1457  /* get the reply */
1458  crm_trace("client %s waiting on reply to msg id %d", client->name, request_id);
1459  do {
1460 
1461  *bytes = qb_ipcc_recv(client->ipc, client->buffer, client->buf_size, 1000);
1462  if (*bytes > 0) {
1463  struct crm_ipc_response_header *hdr = NULL;
1464 
1465  rc = crm_ipc_decompress(client);
1466  if (rc != pcmk_rc_ok) {
1467  return rc;
1468  }
1469 
1470  hdr = (struct crm_ipc_response_header *)(void*)client->buffer;
1471  if (hdr->qb.id == request_id) {
1472  /* Got it */
1473  break;
1474  } else if (hdr->qb.id < request_id) {
1475  xmlNode *bad = string2xml(crm_ipc_buffer(client));
1476 
1477  crm_err("Discarding old reply %d (need %d)", hdr->qb.id, request_id);
1478  crm_log_xml_notice(bad, "OldIpcReply");
1479 
1480  } else {
1481  xmlNode *bad = string2xml(crm_ipc_buffer(client));
1482 
1483  crm_err("Discarding newer reply %d (need %d)", hdr->qb.id, request_id);
1484  crm_log_xml_notice(bad, "ImpossibleReply");
1485  CRM_ASSERT(hdr->qb.id <= request_id);
1486  }
1487  } else if (crm_ipc_connected(client) == FALSE) {
1488  crm_err("Server disconnected client %s while waiting for msg id %d", client->name,
1489  request_id);
1490  break;
1491  }
1492 
1493  } while (time(NULL) < timeout);
1494 
1495  if (*bytes < 0) {
1496  rc = (int) -*bytes; // System errno
1497  }
1498  return rc;
1499 }
1500 
1514 int
1515 crm_ipc_send(crm_ipc_t * client, xmlNode * message, enum crm_ipc_flags flags, int32_t ms_timeout,
1516  xmlNode ** reply)
1517 {
1518  int rc = 0;
1519  ssize_t qb_rc = 0;
1520  ssize_t bytes = 0;
1521  struct iovec *iov;
1522  static uint32_t id = 0;
1523  static int factor = 8;
1524  struct crm_ipc_response_header *header;
1525 
1526  crm_ipc_init();
1527 
1528  if (client == NULL) {
1529  crm_notice("Can't send IPC request without connection (bug?): %.100s",
1530  message);
1531  return -ENOTCONN;
1532 
1533  } else if (crm_ipc_connected(client) == FALSE) {
1534  /* Don't even bother */
1535  crm_notice("Can't send IPC request to %s: Connection closed",
1536  client->name);
1537  return -ENOTCONN;
1538  }
1539 
1540  if (ms_timeout == 0) {
1541  ms_timeout = 5000;
1542  }
1543 
1544  if (client->need_reply) {
1545  qb_rc = qb_ipcc_recv(client->ipc, client->buffer, client->buf_size, ms_timeout);
1546  if (qb_rc < 0) {
1547  crm_warn("Sending IPC to %s disabled until pending reply received",
1548  client->name);
1549  return -EALREADY;
1550 
1551  } else {
1552  crm_notice("Sending IPC to %s re-enabled after pending reply received",
1553  client->name);
1554  client->need_reply = FALSE;
1555  }
1556  }
1557 
1558  id++;
1559  CRM_LOG_ASSERT(id != 0); /* Crude wrap-around detection */
1560  rc = pcmk__ipc_prepare_iov(id, message, client->max_buf_size, &iov, &bytes);
1561  if (rc != pcmk_rc_ok) {
1562  crm_warn("Couldn't prepare IPC request to %s: %s " CRM_XS " rc=%d",
1563  client->name, pcmk_rc_str(rc), rc);
1564  return pcmk_rc2legacy(rc);
1565  }
1566 
1567  header = iov[0].iov_base;
1568  header->flags |= flags;
1569 
1570  if(is_set(flags, crm_ipc_proxied)) {
1571  /* Don't look for a synchronous response */
1573  }
1574 
1575  if(header->size_compressed) {
1576  if(factor < 10 && (client->max_buf_size / 10) < (bytes / factor)) {
1577  crm_notice("Compressed message exceeds %d0%% of configured IPC "
1578  "limit (%u bytes); consider setting PCMK_ipc_buffer to "
1579  "%u or higher",
1580  factor, client->max_buf_size, 2 * client->max_buf_size);
1581  factor++;
1582  }
1583  }
1584 
1585  crm_trace("Sending %s IPC request %d of %u bytes using %dms timeout",
1586  client->name, header->qb.id, header->qb.size, ms_timeout);
1587 
1588  if (ms_timeout > 0 || is_not_set(flags, crm_ipc_client_response)) {
1589 
1590  time_t timeout = time(NULL) + 1 + (ms_timeout / 1000);
1591 
1592  do {
1593  /* @TODO Is this check really needed? Won't qb_ipcc_sendv() return
1594  * an error if it's not connected?
1595  */
1596  if (!crm_ipc_connected(client)) {
1597  goto send_cleanup;
1598  }
1599 
1600  qb_rc = qb_ipcc_sendv(client->ipc, iov, 2);
1601  } while ((qb_rc == -EAGAIN) && (time(NULL) < timeout));
1602 
1603  rc = (int) qb_rc; // Negative of system errno, or bytes sent
1604  if (qb_rc <= 0) {
1605  goto send_cleanup;
1606 
1607  } else if (is_not_set(flags, crm_ipc_client_response)) {
1608  crm_trace("Not waiting for reply to %s IPC request %d",
1609  client->name, header->qb.id);
1610  goto send_cleanup;
1611  }
1612 
1613  rc = internal_ipc_get_reply(client, header->qb.id, ms_timeout, &bytes);
1614  if (rc != pcmk_rc_ok) {
1615  /* We didn't get the reply in time, so disable future sends for now.
1616  * The only alternative would be to close the connection since we
1617  * don't know how to detect and discard out-of-sequence replies.
1618  *
1619  * @TODO Implement out-of-sequence detection
1620  */
1621  client->need_reply = TRUE;
1622  }
1623  rc = (int) bytes; // Negative system errno, or size of reply received
1624 
1625  } else {
1626  // No timeout, and client response needed
1627  do {
1628  qb_rc = qb_ipcc_sendv_recv(client->ipc, iov, 2, client->buffer,
1629  client->buf_size, -1);
1630  } while ((qb_rc == -EAGAIN) && crm_ipc_connected(client));
1631  rc = (int) qb_rc; // Negative system errno, or size of reply received
1632  }
1633 
1634  if (rc > 0) {
1635  struct crm_ipc_response_header *hdr = (struct crm_ipc_response_header *)(void*)client->buffer;
1636 
1637  crm_trace("Received %d-byte reply %d to %s IPC %d: %.100s",
1638  rc, hdr->qb.id, client->name, header->qb.id,
1639  crm_ipc_buffer(client));
1640 
1641  if (reply) {
1642  *reply = string2xml(crm_ipc_buffer(client));
1643  }
1644 
1645  } else {
1646  crm_trace("No reply to %s IPC %d: rc=%d",
1647  client->name, header->qb.id, rc);
1648  }
1649 
1650  send_cleanup:
1651  if (crm_ipc_connected(client) == FALSE) {
1652  crm_notice("Couldn't send %s IPC request %d: Connection closed "
1653  CRM_XS " rc=%d", client->name, header->qb.id, rc);
1654 
1655  } else if (rc == -ETIMEDOUT) {
1656  crm_warn("%s IPC request %d failed: %s after %dms " CRM_XS " rc=%d",
1657  client->name, header->qb.id, pcmk_strerror(rc), ms_timeout,
1658  rc);
1659  crm_write_blackbox(0, NULL);
1660 
1661  } else if (rc <= 0) {
1662  crm_warn("%s IPC request %d failed: %s " CRM_XS " rc=%d",
1663  client->name, header->qb.id,
1664  ((rc == 0)? "No bytes sent" : pcmk_strerror(rc)), rc);
1665  }
1666 
1667  pcmk_free_ipc_event(iov);
1668  return rc;
1669 }
1670 
1671 int
1672 crm_ipc_is_authentic_process(int sock, uid_t refuid, gid_t refgid,
1673  pid_t *gotpid, uid_t *gotuid, gid_t *gotgid) {
1674  int ret = 0;
1675  pid_t found_pid = 0; uid_t found_uid = 0; gid_t found_gid = 0;
1676 #if defined(US_AUTH_PEERCRED_UCRED)
1677  struct ucred ucred;
1678  socklen_t ucred_len = sizeof(ucred);
1679 
1680  if (!getsockopt(sock, SOL_SOCKET, SO_PEERCRED,
1681  &ucred, &ucred_len)
1682  && ucred_len == sizeof(ucred)) {
1683  found_pid = ucred.pid; found_uid = ucred.uid; found_gid = ucred.gid;
1684 
1685 #elif defined(US_AUTH_PEERCRED_SOCKPEERCRED)
1686  struct sockpeercred sockpeercred;
1687  socklen_t sockpeercred_len = sizeof(sockpeercred);
1688 
1689  if (!getsockopt(sock, SOL_SOCKET, SO_PEERCRED,
1690  &sockpeercred, &sockpeercred_len)
1691  && sockpeercred_len == sizeof(sockpeercred_len)) {
1692  found_pid = sockpeercred.pid;
1693  found_uid = sockpeercred.uid; found_gid = sockpeercred.gid;
1694 
1695 #elif defined(US_AUTH_GETPEEREID)
1696  if (!getpeereid(sock, &found_uid, &found_gid)) {
1697  found_pid = PCMK__SPECIAL_PID; /* cannot obtain PID (FreeBSD) */
1698 
1699 #elif defined(US_AUTH_GETPEERUCRED)
1700  ucred_t *ucred;
1701  if (!getpeerucred(sock, &ucred)) {
1702  errno = 0;
1703  found_pid = ucred_getpid(ucred);
1704  found_uid = ucred_geteuid(ucred); found_gid = ucred_getegid(ucred);
1705  ret = -errno;
1706  ucred_free(ucred);
1707  if (ret) {
1708  return (ret < 0) ? ret : -pcmk_err_generic;
1709  }
1710 
1711 #else
1712 # error "No way to authenticate a Unix socket peer"
1713  errno = 0;
1714  if (0) {
1715 #endif
1716  if (gotpid != NULL) {
1717  *gotpid = found_pid;
1718  }
1719  if (gotuid != NULL) {
1720  *gotuid = found_uid;
1721  }
1722  if (gotgid != NULL) {
1723  *gotgid = found_gid;
1724  }
1725  ret = (found_uid == 0 || found_uid == refuid || found_gid == refgid);
1726  } else {
1727  ret = (errno > 0) ? -errno : -pcmk_err_generic;
1728  }
1729 
1730  return ret;
1731 }
1732 
1733 int
1735  gid_t refgid, pid_t *gotpid)
1736 {
1737  static char last_asked_name[PATH_MAX / 2] = ""; /* log spam prevention */
1738  int fd;
1739  int rc = pcmk_rc_ipc_unresponsive;
1740  int auth_rc = 0;
1741  int32_t qb_rc;
1742  pid_t found_pid = 0; uid_t found_uid = 0; gid_t found_gid = 0;
1743  qb_ipcc_connection_t *c;
1744 
1745  c = qb_ipcc_connect(name, 0);
1746  if (c == NULL) {
1747  crm_info("Could not connect to %s IPC: %s", name, strerror(errno));
1749  goto bail;
1750  }
1751 
1752  qb_rc = qb_ipcc_fd_get(c, &fd);
1753  if (qb_rc != 0) {
1754  rc = (int) -qb_rc; // System errno
1755  crm_err("Could not get fd from %s IPC: %s " CRM_XS " rc=%d",
1756  name, pcmk_rc_str(rc), rc);
1757  goto bail;
1758  }
1759 
1760  auth_rc = crm_ipc_is_authentic_process(fd, refuid, refgid, &found_pid,
1761  &found_uid, &found_gid);
1762  if (auth_rc < 0) {
1763  rc = pcmk_legacy2rc(auth_rc);
1764  crm_err("Could not get peer credentials from %s IPC: %s "
1765  CRM_XS " rc=%d", name, pcmk_rc_str(rc), rc);
1766  goto bail;
1767  }
1768 
1769  if (gotpid != NULL) {
1770  *gotpid = found_pid;
1771  }
1772 
1773  if (auth_rc == 0) {
1774  crm_err("Daemon (IPC %s) effectively blocked with unauthorized"
1775  " process %lld (uid: %lld, gid: %lld)",
1776  name, (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
1777  (long long) found_uid, (long long) found_gid);
1779  goto bail;
1780  }
1781 
1782  rc = pcmk_rc_ok;
1783  if ((found_uid != refuid || found_gid != refgid)
1784  && strncmp(last_asked_name, name, sizeof(last_asked_name))) {
1785  if ((found_uid == 0) && (refuid != 0)) {
1786  crm_warn("Daemon (IPC %s) runs as root, whereas the expected"
1787  " credentials are %lld:%lld, hazard of violating"
1788  " the least privilege principle",
1789  name, (long long) refuid, (long long) refgid);
1790  } else {
1791  crm_notice("Daemon (IPC %s) runs as %lld:%lld, whereas the"
1792  " expected credentials are %lld:%lld, which may"
1793  " mean a different set of privileges than expected",
1794  name, (long long) found_uid, (long long) found_gid,
1795  (long long) refuid, (long long) refgid);
1796  }
1797  memccpy(last_asked_name, name, '\0', sizeof(last_asked_name));
1798  }
1799 
1800 bail:
1801  if (c != NULL) {
1802  qb_ipcc_disconnect(c);
1803  }
1804  return rc;
1805 }
1806 
1807 
1808 /* Utils */
1809 
1810 xmlNode *
1811 create_hello_message(const char *uuid,
1812  const char *client_name, const char *major_version, const char *minor_version)
1813 {
1814  xmlNode *hello_node = NULL;
1815  xmlNode *hello = NULL;
1816 
1817  if (pcmk__str_empty(uuid) || pcmk__str_empty(client_name)
1818  || pcmk__str_empty(major_version) || pcmk__str_empty(minor_version)) {
1819  crm_err("Could not create IPC hello message from %s (UUID %s): "
1820  "missing information",
1821  client_name? client_name : "unknown client",
1822  uuid? uuid : "unknown");
1823  return NULL;
1824  }
1825 
1826  hello_node = create_xml_node(NULL, XML_TAG_OPTIONS);
1827  if (hello_node == NULL) {
1828  crm_err("Could not create IPC hello message from %s (UUID %s): "
1829  "Message data creation failed", client_name, uuid);
1830  return NULL;
1831  }
1832 
1833  crm_xml_add(hello_node, "major_version", major_version);
1834  crm_xml_add(hello_node, "minor_version", minor_version);
1835  crm_xml_add(hello_node, "client_name", client_name);
1836  crm_xml_add(hello_node, "client_uuid", uuid);
1837 
1838  hello = create_request(CRM_OP_HELLO, hello_node, NULL, NULL, client_name, uuid);
1839  if (hello == NULL) {
1840  crm_err("Could not create IPC hello message from %s (UUID %s): "
1841  "Request creation failed", client_name, uuid);
1842  return NULL;
1843  }
1844  free_xml(hello_node);
1845 
1846  crm_trace("Created hello message from %s (UUID %s)", client_name, uuid);
1847  return hello;
1848 }
#define F_CRM_TASK
Definition: msg_xml.h:52
#define T_ATTRD
Definition: msg_xml.h:46
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:233
#define PCMK__SERVER_BASED_RW
Definition: crm_internal.h:109
xmlNode * pcmk__client_data2xml(pcmk__client_t *c, void *data, uint32_t *id, uint32_t *flags)
Definition: ipc.c:577
#define F_CRM_REFERENCE
Definition: msg_xml.h:58
int pcmk__client_pid(qb_ipcs_connection_t *c)
Definition: ipc.c:556
void crm_write_blackbox(int nsig, struct qb_log_callsite *callsite)
Definition: logging.c:394
bool crm_ipc_connect(crm_ipc_t *client)
Establish an IPC connection to a Pacemaker component.
Definition: ipc.c:1158
A dumping ground.
#define F_TYPE
Definition: msg_xml.h:30
#define crm_notice(fmt, args...)
Definition: logging.h:365
const char * pcmk_strerror(int rc)
Definition: results.c:55
const char * bz2_strerror(int rc)
Definition: results.c:718
char * crm_generate_uuid(void)
Definition: utils.c:495
void pcmk__client_cleanup(void)
Definition: ipc.c:298
int pcmk_rc2legacy(int rc)
Definition: results.c:430
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
Definition: results.c:751
pcmk__client_t * pcmk__find_client(qb_ipcs_connection_t *c)
Definition: ipc.c:236
#define F_CRM_HOST_TO
Definition: msg_xml.h:53
#define XML_TAG_OPTIONS
Definition: msg_xml.h:112
void pcmk__ipc_send_ack_as(const char *function, int line, pcmk__client_t *c, uint32_t request, uint32_t flags, const char *tag)
Definition: ipc.c:958
const char * pcmk__client_type_str(enum pcmk__client_type client_type)
Definition: ipc.c:281
int crm_ipc_get_fd(crm_ipc_t *client)
Definition: ipc.c:1263
qb_ipcs_service_t * mainloop_add_ipc_server_with_prio(const char *name, enum qb_ipc_type type, struct qb_ipcs_service_handlers *callbacks, enum qb_loop_priority prio)
Start server-side API end-point, hooked into the internal event loop.
Definition: mainloop.c:650
#define F_CRM_MSG_TYPE
Definition: msg_xml.h:54
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: nvpair.c:424
#define CRM_FEATURE_SET
Definition: crm.h:54
#define F_CRM_HOST_FROM
Definition: msg_xml.h:57
#define T_CRM
Definition: msg_xml.h:42
void pcmk__foreach_ipc_client(GHFunc func, gpointer user_data)
Definition: ipc.c:211
xmlNode * create_reply_adv(xmlNode *request, xmlNode *xml_response_data, const char *origin)
Definition: ipc.c:133
#define PCMK__SPECIAL_PID_AS_0(p)
Definition: ipc_internal.h:34
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:316
#define pcmk_err_generic
Definition: results.h:70
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:126
#define PCMK_IPC_VERSION
Definition: ipc.c:42
#define PCMK__SPECIAL_PID
Definition: ipc_internal.h:25
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:219
long crm_ipc_read(crm_ipc_t *client)
Definition: ipc.c:1373
#define clear_bit(word, bit)
Definition: crm_internal.h:69
int pcmk_daemon_user(uid_t *uid, gid_t *gid)
Get user and group IDs of pacemaker daemon user.
Definition: utils.c:171
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:413
void pcmk__foreach_ipc_client_remove(GHRFunc func, gpointer user_data)
Definition: ipc.c:228
char * strerror(int errnum)
xmlNode * create_hello_message(const char *uuid, const char *client_name, const char *major_version, const char *minor_version)
Definition: ipc.c:1811
uint32_t crm_ipc_buffer_flags(crm_ipc_t *client)
Definition: ipc.c:1427
GQueue * event_queue
Definition: ipcs_internal.h:81
xmlNode * string2xml(const char *input)
Definition: xml.c:2180
const char * crm_ipc_buffer(crm_ipc_t *client)
Definition: ipc.c:1420
#define MAX_MSG_SIZE
Definition: ipc.c:1088
#define XML_ATTR_REQUEST
Definition: msg_xml.h:115
#define crm_warn(fmt, args...)
Definition: logging.h:364
#define set_bit(word, bit)
Definition: crm_internal.h:68
int rc
Definition: pcmk_fence.c:34
#define crm_debug(fmt, args...)
Definition: logging.h:368
#define F_CRM_SYS_TO
Definition: msg_xml.h:55
struct crm_ipc_s crm_ipc_t
Definition: ipc.h:58
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:522
guint pcmk__ipc_client_count(void)
Definition: ipc.c:196
#define crm_trace(fmt, args...)
Definition: logging.h:369
void pcmk__drop_all_clients(qb_ipcs_service_t *s)
Definition: ipc.c:312
int pcmk__compress(const char *data, unsigned int length, unsigned int max, char **result, unsigned int *result_len)
Definition: strings.c:541
void pcmk__serve_attrd_ipc(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition: ipc.c:1051
pcmk__client_t * pcmk__find_client_by_id(const char *id)
Definition: ipc.c:247
#define pcmk__plural_s(i)
Definition: internal.h:198
qb_ipcs_service_t * pcmk__serve_controld_ipc(struct qb_ipcs_service_handlers *cb)
Definition: ipc.c:1037
int pcmk__ipc_prepare_iov(uint32_t request, xmlNode *message, uint32_t max_send_size, struct iovec **result, ssize_t *bytes)
Definition: ipc.c:773
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1976
#define CRM_DAEMON_USER
Definition: config.h:32
int pcmk__ipc_send_iov(pcmk__client_t *c, struct iovec *iov, uint32_t flags)
Definition: ipc.c:859
unsigned int crm_ipc_default_buffer_size(void)
Definition: ipc.c:71
void crm_ipc_destroy(crm_ipc_t *client)
Definition: ipc.c:1240
int pcmk_legacy2rc(int legacy_rc)
Definition: results.c:443
gboolean add_message_xml(xmlNode *msg, const char *field, xmlNode *xml)
Definition: xml.c:2627
void free_xml(xmlNode *child)
Definition: xml.c:2136
void pcmk_free_ipc_event(struct iovec *event)
Free an I/O vector created by pcmk__ipc_prepare_iov()
Definition: ipc.c:464
#define PCMK__SERVER_BASED_RO
Definition: crm_internal.h:108
int pcmk__ipc_send_xml(pcmk__client_t *c, uint32_t request, xmlNode *message, uint32_t flags)
Definition: ipc.c:936
#define CRM_SYSTEM_CRMD
Definition: crm.h:102
bool crm_ipc_connected(crm_ipc_t *client)
Definition: ipc.c:1277
#define F_CRM_DATA
Definition: msg_xml.h:51
#define CRM_XS
Definition: logging.h:54
bool pcmk__set_client_queue_max(pcmk__client_t *client, const char *qmax)
Definition: ipc.c:540
int crm_ipc_ready(crm_ipc_t *client)
Check whether an IPC connection is ready to be read.
Definition: ipc.c:1309
#define PCMK_IPC_DEFAULT_QUEUE_MAX
Definition: ipc.c:45
void pcmk__free_client(pcmk__client_t *c)
Definition: ipc.c:489
const char * pcmk__client_name(pcmk__client_t *c)
Definition: ipc.c:267
long long crm_parse_ll(const char *text, const char *default_text)
Parse a long long integer value from a string.
Definition: strings.c:100
const char * crm_ipc_name(crm_ipc_t *client)
Definition: ipc.c:1441
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:314
#define CRM_OP_HELLO
Definition: crm.h:135
#define crm_err(fmt, args...)
Definition: logging.h:363
#define CRM_ASSERT(expr)
Definition: results.h:42
int crm_ipc_send(crm_ipc_t *client, xmlNode *message, enum crm_ipc_flags flags, int32_t ms_timeout, xmlNode **reply)
Send an IPC XML message.
Definition: ipc.c:1515
xmlNode * create_request_adv(const char *task, xmlNode *xml_data, const char *host_to, const char *sys_to, const char *sys_from, const char *uuid_from, const char *origin)
Definition: ipc.c:88
#define F_CRM_SYS_FROM
Definition: msg_xml.h:56
int delay
Definition: pcmk_fence.c:33
#define crm_log_xml_notice(xml, text)
Definition: logging.h:374
crm_ipc_t * crm_ipc_new(const char *name, size_t max_size)
Definition: ipc.c:1128
char * dump_xml_unformatted(xmlNode *msg)
Definition: xml.c:3321
#define XML_ATTR_RESPONSE
Definition: msg_xml.h:116
char data[0]
Definition: internal.h:90
pcmk__client_t * pcmk__new_client(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
Definition: ipc.c:408
Wrappers for and extensions to libqb IPC.
char * generate_hash_key(const char *crm_msg_reference, const char *sys)
Definition: utils.c:120
#define F_CRM_ORIGIN
Definition: msg_xml.h:60
#define crm_log_xml_trace(xml, text)
Definition: logging.h:377
uint32_t flags
Definition: ipcs_internal.h:77
#define PCMK__SERVER_BASED_SHM
Definition: crm_internal.h:110
unsigned int queue_max
Definition: ipcs_internal.h:93
struct pcmk__remote_s * remote
Definition: ipcs_internal.h:90
enum pcmk__client_type kind
Definition: ipcs_internal.h:86
char * pcmk__uid2username(uid_t uid)
qb_ipcs_service_t * mainloop_add_ipc_server(const char *name, enum qb_ipc_type type, struct qb_ipcs_service_handlers *callbacks)
Definition: mainloop.c:643
void pcmk__serve_fenced_ipc(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition: ipc.c:1072
char * name
Definition: pcmk_fence.c:30
void pcmk__serve_based_ipc(qb_ipcs_service_t **ipcs_ro, qb_ipcs_service_t **ipcs_rw, qb_ipcs_service_t **ipcs_shm, struct qb_ipcs_service_handlers *ro_cb, struct qb_ipcs_service_handlers *rw_cb)
Definition: ipc.c:985
crm_ipc_flags
Definition: ipc.h:39
void crm_ipc_close(crm_ipc_t *client)
Definition: ipc.c:1225
int pcmk__ipc_is_authentic_process_active(const char *name, uid_t refuid, gid_t refgid, pid_t *gotpid)
Definition: ipc.c:1734
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
unsigned int timeout
Definition: pcmk_fence.c:31
#define create_request(task, xml_data, host_to, sys_to, sys_from, uuid_from)
Definition: ipc.h:32
unsigned int queue_backlog
Definition: ipcs_internal.h:92
#define crm_info(fmt, args...)
Definition: logging.h:366
qb_ipcs_connection_t * ipcs
Definition: ipcs_internal.h:88
pcmk__client_t * pcmk__new_unauth_client(void *key)
Allocate a new pcmk__client_t object and generate its ID.
Definition: ipc.c:399
#define F_CRM_VERSION
Definition: msg_xml.h:59
uint32_t version
Definition: remote.c:147
pcmk__client_type
Definition: ipcs_internal.h:29
uint64_t flags
Definition: remote.c:149
#define MIN_MSG_SIZE
Definition: ipc.c:1087
void pcmk__stop_based_ipc(qb_ipcs_service_t *ipcs_ro, qb_ipcs_service_t *ipcs_rw, qb_ipcs_service_t *ipcs_shm)
Definition: ipc.c:1019
enum crm_ais_msg_types type
Definition: internal.h:83
int crm_ipc_is_authentic_process(int sock, uid_t refuid, gid_t refgid, pid_t *gotpid, uid_t *gotuid, gid_t *gotgid)
Check the authenticity of the IPC socket peer process.
Definition: ipc.c:1672