This source file includes following definitions.
- pcmk_new_ipc_api
- free_daemon_specific_data
- pcmk__call_ipc_callback
- ipc_post_disconnect
- pcmk_free_ipc_api
- pcmk_ipc_name
- pcmk_ipc_is_connected
- call_api_dispatch
- dispatch_ipc_data
- dispatch_ipc_source_data
- pcmk_poll_ipc
- pcmk_dispatch_ipc
- connect_with_main_loop
- connect_without_main_loop
- pcmk__connect_ipc_retry_conrefused
- pcmk__connect_ipc
- pcmk_connect_ipc
- pcmk_disconnect_ipc
- pcmk_register_ipc_callback
- pcmk__send_ipc_request
- create_purge_node_request
- pcmk_ipc_purge_node
- crm_ipc_new
- pcmk__connect_generic_ipc
- crm_ipc_close
- crm_ipc_destroy
- pcmk__ipc_fd
- crm_ipc_get_fd
- crm_ipc_connected
- crm_ipc_ready
- crm_ipc_read
- pcmk__ipc_free_client_buffer
- crm_ipc_buffer
- crm_ipc_buffer_flags
- crm_ipc_name
- internal_ipc_get_reply
- discard_old_replies
- crm_ipc_send
- is_ipc_provider_expected
- crm_ipc_is_authentic_process
- pcmk__ipc_is_authentic_process_active
- crm_ipc_connect
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #if defined(HAVE_UCRED) || defined(HAVE_SOCKPEERCRED)
13 #include <sys/socket.h>
14 #elif defined(HAVE_GETPEERUCRED)
15 #include <ucred.h>
16 #endif
17
18 #include <stdio.h>
19 #include <sys/types.h>
20 #include <errno.h>
21 #include <bzlib.h>
22
23 #include <crm/crm.h>
24 #include <crm/common/xml.h>
25 #include <crm/common/ipc.h>
26 #include <crm/common/ipc_internal.h>
27 #include "crmcommon_private.h"
28
29 static int is_ipc_provider_expected(qb_ipcc_connection_t *qb_ipc, int sock,
30 uid_t refuid, gid_t refgid, pid_t *gotpid,
31 uid_t *gotuid, gid_t *gotgid);
32
33
34
35
36
37
38
39
40
41
42
43
44
45 int
46 pcmk_new_ipc_api(pcmk_ipc_api_t **api, enum pcmk_ipc_server server)
47 {
48 if (api == NULL) {
49 return EINVAL;
50 }
51
52 *api = calloc(1, sizeof(pcmk_ipc_api_t));
53 if (*api == NULL) {
54 return errno;
55 }
56
57 (*api)->server = server;
58 if (pcmk_ipc_name(*api, false) == NULL) {
59 pcmk_free_ipc_api(*api);
60 *api = NULL;
61 return EOPNOTSUPP;
62 }
63
64
65 switch (server) {
66 case pcmk_ipc_attrd:
67 (*api)->cmds = pcmk__attrd_api_methods();
68 break;
69
70 case pcmk_ipc_based:
71 break;
72
73 case pcmk_ipc_controld:
74 (*api)->cmds = pcmk__controld_api_methods();
75 break;
76
77 case pcmk_ipc_execd:
78 break;
79
80 case pcmk_ipc_fenced:
81 break;
82
83 case pcmk_ipc_pacemakerd:
84 (*api)->cmds = pcmk__pacemakerd_api_methods();
85 break;
86
87 case pcmk_ipc_schedulerd:
88 (*api)->cmds = pcmk__schedulerd_api_methods();
89 break;
90
91 default:
92 pcmk_free_ipc_api(*api);
93 *api = NULL;
94 return EINVAL;
95 }
96 if ((*api)->cmds == NULL) {
97 pcmk_free_ipc_api(*api);
98 *api = NULL;
99 return ENOMEM;
100 }
101
102 (*api)->ipc = crm_ipc_new(pcmk_ipc_name(*api, false), 0);
103 if ((*api)->ipc == NULL) {
104 pcmk_free_ipc_api(*api);
105 *api = NULL;
106 return ENOMEM;
107 }
108
109
110 if ((*api)->cmds->new_data != NULL) {
111 if ((*api)->cmds->new_data(*api) != pcmk_rc_ok) {
112 pcmk_free_ipc_api(*api);
113 *api = NULL;
114 return ENOMEM;
115 }
116 }
117 crm_trace("Created %s API IPC object", pcmk_ipc_name(*api, true));
118 return pcmk_rc_ok;
119 }
120
121 static void
122 free_daemon_specific_data(pcmk_ipc_api_t *api)
123 {
124 if ((api != NULL) && (api->cmds != NULL)) {
125 if ((api->cmds->free_data != NULL) && (api->api_data != NULL)) {
126 api->cmds->free_data(api->api_data);
127 api->api_data = NULL;
128 }
129 free(api->cmds);
130 api->cmds = NULL;
131 }
132 }
133
134
135
136
137
138
139
140
141
142
143 void
144 pcmk__call_ipc_callback(pcmk_ipc_api_t *api, enum pcmk_ipc_event event_type,
145 crm_exit_t status, void *event_data)
146 {
147 if ((api != NULL) && (api->cb != NULL)) {
148 api->cb(api, event_type, status, event_data, api->user_data);
149 }
150 }
151
152
153
154
155
156
157
158
159
160 static void
161 ipc_post_disconnect(gpointer user_data)
162 {
163 pcmk_ipc_api_t *api = user_data;
164
165 crm_info("Disconnected from %s", pcmk_ipc_name(api, true));
166
167
168 if ((api->cmds != NULL) && (api->cmds->post_disconnect != NULL)) {
169 api->cmds->post_disconnect(api);
170 }
171
172
173 pcmk__call_ipc_callback(api, pcmk_ipc_event_disconnect, CRM_EX_DISCONNECT,
174 NULL);
175
176
177
178
179
180
181 api->ipc = NULL;
182 api->mainloop_io = NULL;
183
184 if (api->free_on_disconnect) {
185
186
187
188 free_daemon_specific_data(api);
189 crm_trace("Freeing IPC API object after disconnect");
190 free(api);
191 }
192 }
193
194
195
196
197
198
199 void
200 pcmk_free_ipc_api(pcmk_ipc_api_t *api)
201 {
202 bool free_on_disconnect = false;
203
204 if (api == NULL) {
205 return;
206 }
207 crm_debug("Releasing %s IPC API", pcmk_ipc_name(api, true));
208
209 if (api->ipc != NULL) {
210 if (api->mainloop_io != NULL) {
211
212
213
214
215
216
217
218
219
220 free_on_disconnect = api->free_on_disconnect = true;
221 }
222 pcmk_disconnect_ipc(api);
223 }
224 if (!free_on_disconnect) {
225 free_daemon_specific_data(api);
226 crm_trace("Freeing IPC API object");
227 free(api);
228 }
229 }
230
231
232
233
234
235
236
237
238
239
240 const char *
241 pcmk_ipc_name(const pcmk_ipc_api_t *api, bool for_log)
242 {
243 if (api == NULL) {
244 return for_log? "Pacemaker" : NULL;
245 }
246 if (for_log) {
247 const char *name = pcmk__server_log_name(api->server);
248
249 return pcmk__s(name, "Pacemaker");
250 }
251 switch (api->server) {
252
253 case pcmk_ipc_based:
254 case pcmk_ipc_execd:
255 case pcmk_ipc_fenced:
256 return NULL;
257
258 default:
259 return pcmk__server_ipc_name(api->server);
260 }
261 }
262
263
264
265
266
267
268
269
270 bool
271 pcmk_ipc_is_connected(pcmk_ipc_api_t *api)
272 {
273 return (api != NULL) && crm_ipc_connected(api->ipc);
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287 static bool
288 call_api_dispatch(pcmk_ipc_api_t *api, xmlNode *message)
289 {
290 crm_log_xml_trace(message, "ipc-received");
291 if ((api->cmds != NULL) && (api->cmds->dispatch != NULL)) {
292 return api->cmds->dispatch(api, message);
293 }
294
295 return false;
296 }
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313 static int
314 dispatch_ipc_data(const char *buffer, pcmk_ipc_api_t *api)
315 {
316 bool more = false;
317 xmlNode *msg;
318
319 if (buffer == NULL) {
320 crm_warn("Empty message received from %s IPC",
321 pcmk_ipc_name(api, true));
322 return ENOMSG;
323 }
324
325 msg = pcmk__xml_parse(buffer);
326 if (msg == NULL) {
327 crm_warn("Malformed message received from %s IPC",
328 pcmk_ipc_name(api, true));
329 return EPROTO;
330 }
331
332 more = call_api_dispatch(api, msg);
333 pcmk__xml_free(msg);
334
335 if (more) {
336 return EINPROGRESS;
337 } else {
338 return pcmk_rc_ok;
339 }
340 }
341
342
343
344
345
346
347
348
349
350
351
352
353
354 static int
355 dispatch_ipc_source_data(const char *buffer, ssize_t length, gpointer user_data)
356 {
357 pcmk_ipc_api_t *api = user_data;
358
359 CRM_CHECK(api != NULL, return 0);
360 dispatch_ipc_data(buffer, api);
361 return 0;
362 }
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382 int
383 pcmk_poll_ipc(const pcmk_ipc_api_t *api, int timeout_ms)
384 {
385 int rc;
386 struct pollfd pollfd = { 0, };
387
388 if ((api == NULL) || (api->dispatch_type != pcmk_ipc_dispatch_poll)) {
389 return EINVAL;
390 }
391
392 rc = pcmk__ipc_fd(api->ipc, &(pollfd.fd));
393 if (rc != pcmk_rc_ok) {
394 crm_debug("Could not obtain file descriptor for %s IPC: %s",
395 pcmk_ipc_name(api, true), pcmk_rc_str(rc));
396 return rc;
397 }
398
399 pollfd.events = POLLIN;
400 rc = poll(&pollfd, 1, timeout_ms);
401 if (rc < 0) {
402
403
404
405 return (errno == EAGAIN)? ENOMEM : errno;
406 } else if (rc == 0) {
407 return EAGAIN;
408 }
409 return pcmk_rc_ok;
410 }
411
412
413
414
415
416
417
418
419
420
421
422 void
423 pcmk_dispatch_ipc(pcmk_ipc_api_t *api)
424 {
425 if (api == NULL) {
426 return;
427 }
428 while (crm_ipc_ready(api->ipc) > 0) {
429 if (crm_ipc_read(api->ipc) > 0) {
430 dispatch_ipc_data(crm_ipc_buffer(api->ipc), api);
431 pcmk__ipc_free_client_buffer(api->ipc);
432 }
433 }
434 }
435
436
437 static int
438 connect_with_main_loop(pcmk_ipc_api_t *api)
439 {
440 int rc;
441
442 struct ipc_client_callbacks callbacks = {
443 .dispatch = dispatch_ipc_source_data,
444 .destroy = ipc_post_disconnect,
445 };
446
447 rc = pcmk__add_mainloop_ipc(api->ipc, G_PRIORITY_DEFAULT, api,
448 &callbacks, &(api->mainloop_io));
449 if (rc != pcmk_rc_ok) {
450 return rc;
451 }
452 crm_debug("Connected to %s IPC (attached to main loop)",
453 pcmk_ipc_name(api, true));
454
455
456
457 return pcmk_rc_ok;
458 }
459
460
461 static int
462 connect_without_main_loop(pcmk_ipc_api_t *api)
463 {
464 int rc = pcmk__connect_generic_ipc(api->ipc);
465
466 if (rc != pcmk_rc_ok) {
467 crm_ipc_close(api->ipc);
468 } else {
469 crm_debug("Connected to %s IPC (without main loop)",
470 pcmk_ipc_name(api, true));
471 }
472 return rc;
473 }
474
475
476
477
478
479
480
481
482
483
484
485
486 int
487 pcmk__connect_ipc_retry_conrefused(pcmk_ipc_api_t *api,
488 enum pcmk_ipc_dispatch dispatch_type,
489 int attempts)
490 {
491 int remaining = attempts;
492 int rc = pcmk_rc_ok;
493
494 do {
495 if (rc == ECONNREFUSED) {
496 pcmk__sleep_ms((attempts - remaining) * 500);
497 }
498 rc = pcmk__connect_ipc(api, dispatch_type, remaining);
499 remaining--;
500 } while (rc == ECONNREFUSED && remaining >= 0);
501
502 return rc;
503 }
504
505
506
507
508
509
510
511
512
513
514
515
516 int
517 pcmk__connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type,
518 int attempts)
519 {
520 int rc = pcmk_rc_ok;
521
522 if ((api == NULL) || (attempts < 1)) {
523 return EINVAL;
524 }
525
526 if (api->ipc == NULL) {
527 api->ipc = crm_ipc_new(pcmk_ipc_name(api, false), 0);
528 if (api->ipc == NULL) {
529 return ENOMEM;
530 }
531 }
532
533 if (crm_ipc_connected(api->ipc)) {
534 crm_trace("Already connected to %s", pcmk_ipc_name(api, true));
535 return pcmk_rc_ok;
536 }
537
538 api->dispatch_type = dispatch_type;
539
540 crm_debug("Attempting connection to %s (up to %d time%s)",
541 pcmk_ipc_name(api, true), attempts, pcmk__plural_s(attempts));
542 for (int remaining = attempts - 1; remaining >= 0; --remaining) {
543 switch (dispatch_type) {
544 case pcmk_ipc_dispatch_main:
545 rc = connect_with_main_loop(api);
546 break;
547
548 case pcmk_ipc_dispatch_sync:
549 case pcmk_ipc_dispatch_poll:
550 rc = connect_without_main_loop(api);
551 break;
552 }
553
554 if ((remaining == 0) || ((rc != EAGAIN) && (rc != EALREADY))) {
555 break;
556 }
557
558
559 pcmk__sleep_ms((attempts - remaining) * 500);
560 crm_debug("Re-attempting connection to %s (%d attempt%s remaining)",
561 pcmk_ipc_name(api, true), remaining,
562 pcmk__plural_s(remaining));
563 }
564
565 if (rc != pcmk_rc_ok) {
566 return rc;
567 }
568
569 if ((api->cmds != NULL) && (api->cmds->post_connect != NULL)) {
570 rc = api->cmds->post_connect(api);
571 if (rc != pcmk_rc_ok) {
572 crm_ipc_close(api->ipc);
573 }
574 }
575 return rc;
576 }
577
578
579
580
581
582
583
584
585
586 int
587 pcmk_connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type)
588 {
589 int rc = pcmk__connect_ipc(api, dispatch_type, 2);
590
591 if (rc != pcmk_rc_ok) {
592 crm_err("Connection to %s failed: %s",
593 pcmk_ipc_name(api, true), pcmk_rc_str(rc));
594 }
595 return rc;
596 }
597
598
599
600
601
602
603
604
605
606
607
608
609 void
610 pcmk_disconnect_ipc(pcmk_ipc_api_t *api)
611 {
612 if ((api == NULL) || (api->ipc == NULL)) {
613 return;
614 }
615 switch (api->dispatch_type) {
616 case pcmk_ipc_dispatch_main:
617 {
618 mainloop_io_t *mainloop_io = api->mainloop_io;
619
620
621 api->mainloop_io = NULL;
622 api->ipc = NULL;
623
624 mainloop_del_ipc_client(mainloop_io);
625
626 }
627 break;
628
629 case pcmk_ipc_dispatch_poll:
630 case pcmk_ipc_dispatch_sync:
631 {
632 crm_ipc_t *ipc = api->ipc;
633
634
635 api->ipc = NULL;
636
637
638 api->free_on_disconnect = false;
639
640 crm_ipc_close(ipc);
641 crm_ipc_destroy(ipc);
642 ipc_post_disconnect(api);
643 }
644 break;
645 }
646 }
647
648
649
650
651
652
653
654
655
656
657
658
659
660 void
661 pcmk_register_ipc_callback(pcmk_ipc_api_t *api, pcmk_ipc_callback_t cb,
662 void *user_data)
663 {
664 if (api == NULL) {
665 return;
666 }
667 api->cb = cb;
668 api->user_data = user_data;
669 }
670
671
672
673
674
675
676
677
678
679
680
681
682
683 int
684 pcmk__send_ipc_request(pcmk_ipc_api_t *api, const xmlNode *request)
685 {
686 int rc;
687 xmlNode *reply = NULL;
688 enum crm_ipc_flags flags = crm_ipc_flags_none;
689
690 if ((api == NULL) || (api->ipc == NULL) || (request == NULL)) {
691 return EINVAL;
692 }
693 crm_log_xml_trace(request, "ipc-sent");
694
695
696 if ((api->dispatch_type == pcmk_ipc_dispatch_sync)
697 && (api->cmds != NULL)
698 && (api->cmds->reply_expected != NULL)
699 && (api->cmds->reply_expected(api, request))) {
700 flags = crm_ipc_client_response;
701 }
702
703
704
705
706
707
708 rc = crm_ipc_send(api->ipc, request, flags, 0, &reply);
709
710 if (rc < 0) {
711 return pcmk_legacy2rc(rc);
712 } else if (rc == 0) {
713 return ENODATA;
714 }
715
716
717 if (reply != NULL) {
718 bool more = call_api_dispatch(api, reply);
719
720 pcmk__xml_free(reply);
721
722 while (more) {
723 rc = crm_ipc_read(api->ipc);
724
725 if (rc == -EAGAIN) {
726 continue;
727 } else if (rc == -ENOMSG || rc == pcmk_ok) {
728 return pcmk_rc_ok;
729 } else if (rc < 0) {
730 return -rc;
731 }
732
733 rc = dispatch_ipc_data(crm_ipc_buffer(api->ipc), api);
734 pcmk__ipc_free_client_buffer(api->ipc);
735
736 if (rc == pcmk_rc_ok) {
737 more = false;
738 } else if (rc == EINPROGRESS) {
739 more = true;
740 } else {
741 continue;
742 }
743 }
744 }
745 return pcmk_rc_ok;
746 }
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770 static xmlNode *
771 create_purge_node_request(const pcmk_ipc_api_t *api, const char *node_name,
772 uint32_t nodeid)
773 {
774 xmlNode *request = NULL;
775 const char *client = crm_system_name? crm_system_name : "client";
776
777 switch (api->server) {
778 case pcmk_ipc_attrd:
779 request = pcmk__xe_create(NULL, __func__);
780 crm_xml_add(request, PCMK__XA_T, PCMK__VALUE_ATTRD);
781 crm_xml_add(request, PCMK__XA_SRC, crm_system_name);
782 crm_xml_add(request, PCMK_XA_TASK, PCMK__ATTRD_CMD_PEER_REMOVE);
783 pcmk__xe_set_bool_attr(request, PCMK__XA_REAP, true);
784 crm_xml_add(request, PCMK__XA_ATTR_HOST, node_name);
785 if (nodeid > 0) {
786 crm_xml_add_int(request, PCMK__XA_ATTR_HOST_ID, nodeid);
787 }
788 break;
789
790 case pcmk_ipc_controld:
791 case pcmk_ipc_fenced:
792 case pcmk_ipc_pacemakerd:
793 request = pcmk__new_request(api->server, client, NULL,
794 pcmk_ipc_name(api, false),
795 CRM_OP_RM_NODE_CACHE, NULL);
796 if (nodeid > 0) {
797 crm_xml_add_ll(request, PCMK_XA_ID, (long long) nodeid);
798 }
799 crm_xml_add(request, PCMK_XA_UNAME, node_name);
800 break;
801
802 case pcmk_ipc_based:
803 case pcmk_ipc_execd:
804 case pcmk_ipc_schedulerd:
805 break;
806
807 default:
808 return NULL;
809 }
810 return request;
811 }
812
813
814
815
816
817
818
819
820
821
822
823
824 int
825 pcmk_ipc_purge_node(pcmk_ipc_api_t *api, const char *node_name, uint32_t nodeid)
826 {
827 int rc = 0;
828 xmlNode *request = NULL;
829
830 if (api == NULL) {
831 return EINVAL;
832 }
833 if ((node_name == NULL) && (nodeid == 0)) {
834 return EINVAL;
835 }
836
837 request = create_purge_node_request(api, node_name, nodeid);
838 if (request == NULL) {
839 return EOPNOTSUPP;
840 }
841 rc = pcmk__send_ipc_request(api, request);
842 pcmk__xml_free(request);
843
844 crm_debug("%s peer cache purge of node %s[%lu]: rc=%d",
845 pcmk_ipc_name(api, true), node_name, (unsigned long) nodeid, rc);
846 return rc;
847 }
848
849
850
851
852
853 struct crm_ipc_s {
854 struct pollfd pfd;
855 int need_reply;
856 GByteArray *buffer;
857 char *server_name;
858 qb_ipcc_connection_t *ipc;
859 };
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876 crm_ipc_t *
877 crm_ipc_new(const char *name, size_t max_size)
878 {
879 crm_ipc_t *client = NULL;
880
881 client = calloc(1, sizeof(crm_ipc_t));
882 if (client == NULL) {
883 crm_err("Could not create IPC connection: %s", strerror(errno));
884 return NULL;
885 }
886
887 client->server_name = strdup(name);
888 if (client->server_name == NULL) {
889 crm_err("Could not create %s IPC connection: %s",
890 name, strerror(errno));
891 free(client);
892 return NULL;
893 }
894
895 client->buffer = NULL;
896 client->pfd.fd = -1;
897 client->pfd.events = POLLIN;
898 client->pfd.revents = 0;
899
900 return client;
901 }
902
903
904
905
906
907
908
909
910
911 int
912 pcmk__connect_generic_ipc(crm_ipc_t *ipc)
913 {
914 uid_t cl_uid = 0;
915 gid_t cl_gid = 0;
916 pid_t found_pid = 0;
917 uid_t found_uid = 0;
918 gid_t found_gid = 0;
919 int rc = pcmk_rc_ok;
920
921 if (ipc == NULL) {
922 return EINVAL;
923 }
924
925 ipc->need_reply = FALSE;
926 ipc->ipc = qb_ipcc_connect(ipc->server_name, crm_ipc_default_buffer_size());
927 if (ipc->ipc == NULL) {
928 return errno;
929 }
930
931 rc = qb_ipcc_fd_get(ipc->ipc, &ipc->pfd.fd);
932 if (rc < 0) {
933 crm_ipc_close(ipc);
934 return -rc;
935 }
936
937 rc = pcmk_daemon_user(&cl_uid, &cl_gid);
938 rc = pcmk_legacy2rc(rc);
939 if (rc != pcmk_rc_ok) {
940 crm_ipc_close(ipc);
941 return rc;
942 }
943
944 rc = is_ipc_provider_expected(ipc->ipc, ipc->pfd.fd, cl_uid, cl_gid,
945 &found_pid, &found_uid, &found_gid);
946 if (rc != pcmk_rc_ok) {
947 if (rc == pcmk_rc_ipc_unauthorized) {
948 crm_info("%s IPC provider authentication failed: process %lld has "
949 "uid %lld (expected %lld) and gid %lld (expected %lld)",
950 ipc->server_name,
951 (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
952 (long long) found_uid, (long long) cl_uid,
953 (long long) found_gid, (long long) cl_gid);
954 }
955 crm_ipc_close(ipc);
956 return rc;
957 }
958
959 return pcmk_rc_ok;
960 }
961
962 void
963 crm_ipc_close(crm_ipc_t * client)
964 {
965 if (client) {
966 if (client->ipc) {
967 qb_ipcc_connection_t *ipc = client->ipc;
968
969 client->ipc = NULL;
970 qb_ipcc_disconnect(ipc);
971 }
972 }
973 }
974
975 void
976 crm_ipc_destroy(crm_ipc_t * client)
977 {
978 if (client) {
979 if (client->ipc && qb_ipcc_is_connected(client->ipc)) {
980 crm_notice("Destroying active %s IPC connection",
981 client->server_name);
982
983
984
985
986
987
988
989
990
991 } else {
992 crm_trace("Destroying inactive %s IPC connection",
993 client->server_name);
994 }
995
996 if (client->buffer != NULL) {
997 pcmk__ipc_free_client_buffer(client);
998 }
999
1000 free(client->server_name);
1001 free(client);
1002 }
1003 }
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014 int
1015 pcmk__ipc_fd(crm_ipc_t *ipc, int *fd)
1016 {
1017 if ((ipc == NULL) || (fd == NULL)) {
1018 return EINVAL;
1019 }
1020 if ((ipc->ipc == NULL) || (ipc->pfd.fd < 0)) {
1021 return ENOTCONN;
1022 }
1023 *fd = ipc->pfd.fd;
1024 return pcmk_rc_ok;
1025 }
1026
1027 int
1028 crm_ipc_get_fd(crm_ipc_t * client)
1029 {
1030 int fd = -1;
1031
1032 if (pcmk__ipc_fd(client, &fd) != pcmk_rc_ok) {
1033 crm_err("Could not obtain file descriptor for %s IPC",
1034 ((client == NULL)? "unspecified" : client->server_name));
1035 errno = EINVAL;
1036 return -EINVAL;
1037 }
1038 return fd;
1039 }
1040
1041 bool
1042 crm_ipc_connected(crm_ipc_t * client)
1043 {
1044 bool rc = FALSE;
1045
1046 if (client == NULL) {
1047 crm_trace("No client");
1048 return FALSE;
1049
1050 } else if (client->ipc == NULL) {
1051 crm_trace("No connection");
1052 return FALSE;
1053
1054 } else if (client->pfd.fd < 0) {
1055 crm_trace("Bad descriptor");
1056 return FALSE;
1057 }
1058
1059 rc = qb_ipcc_is_connected(client->ipc);
1060 if (rc == FALSE) {
1061 client->pfd.fd = -EINVAL;
1062 }
1063 return rc;
1064 }
1065
1066
1067
1068
1069
1070
1071
1072
1073 int
1074 crm_ipc_ready(crm_ipc_t *client)
1075 {
1076 int rc;
1077
1078 pcmk__assert(client != NULL);
1079
1080 if (!crm_ipc_connected(client)) {
1081 return -ENOTCONN;
1082 }
1083
1084 client->pfd.revents = 0;
1085 rc = poll(&(client->pfd), 1, 0);
1086 return (rc < 0)? -errno : rc;
1087 }
1088
1089 long
1090 crm_ipc_read(crm_ipc_t *client)
1091 {
1092 guint8 *buffer = NULL;
1093 long rc = -ENOMSG;
1094
1095 pcmk__assert((client != NULL) && (client->ipc != NULL));
1096 buffer = g_malloc0(crm_ipc_default_buffer_size());
1097
1098 do {
1099 pcmk__ipc_header_t *header = NULL;
1100 ssize_t bytes = qb_ipcc_event_recv(client->ipc, buffer,
1101 crm_ipc_default_buffer_size(), 0);
1102
1103 header = (pcmk__ipc_header_t *)(void *) buffer;
1104
1105 if (bytes <= 0) {
1106 crm_trace("No message received from %s IPC: %s",
1107 client->server_name, strerror(-bytes));
1108
1109 if (!crm_ipc_connected(client) || bytes == -ENOTCONN) {
1110 crm_err("Connection to %s IPC failed", client->server_name);
1111 rc = -ENOTCONN;
1112 pcmk__ipc_free_client_buffer(client);
1113 } else if (bytes == -EAGAIN) {
1114 rc = -EAGAIN;
1115 }
1116
1117 goto done;
1118
1119 } else if (bytes != header->size + sizeof(pcmk__ipc_header_t)) {
1120 crm_trace("Message size does not match header");
1121 rc = -EBADMSG;
1122 pcmk__ipc_free_client_buffer(client);
1123 goto done;
1124 }
1125
1126 crm_trace("Received %s IPC event %" PRId32 " size=%" PRIu32 " rc=%zu",
1127 client->server_name, header->qb.id, header->qb.size,
1128 bytes);
1129
1130 rc = pcmk__ipc_msg_append(&client->buffer, buffer);
1131
1132 if (rc == pcmk_rc_ok) {
1133 break;
1134 } else if (rc == pcmk_rc_ipc_more) {
1135 continue;
1136 } else {
1137 pcmk__ipc_free_client_buffer(client);
1138 rc = pcmk_rc2legacy(rc);
1139 goto done;
1140 }
1141 } while (true);
1142
1143 if (client->buffer->len > 0) {
1144
1145 rc = client->buffer->len - sizeof(pcmk__ipc_header_t);
1146 }
1147
1148 done:
1149 g_free(buffer);
1150 return rc;
1151 }
1152
1153 void
1154 pcmk__ipc_free_client_buffer(crm_ipc_t *client)
1155 {
1156 pcmk__assert(client != NULL);
1157
1158 if (client->buffer != NULL) {
1159 g_byte_array_free(client->buffer, TRUE);
1160 client->buffer = NULL;
1161 }
1162 }
1163
1164 const char *
1165 crm_ipc_buffer(crm_ipc_t * client)
1166 {
1167 pcmk__assert(client != NULL);
1168 CRM_CHECK(client->buffer != NULL, return NULL);
1169 return (const char *) (client->buffer->data + sizeof(pcmk__ipc_header_t));
1170 }
1171
1172 uint32_t
1173 crm_ipc_buffer_flags(crm_ipc_t * client)
1174 {
1175 pcmk__ipc_header_t *header = NULL;
1176
1177 pcmk__assert(client != NULL);
1178 if (client->buffer == NULL) {
1179 return 0;
1180 }
1181
1182 header = (pcmk__ipc_header_t *)(void*) client->buffer->data;
1183 return header->flags;
1184 }
1185
1186 const char *
1187 crm_ipc_name(crm_ipc_t * client)
1188 {
1189 pcmk__assert(client != NULL);
1190 return client->server_name;
1191 }
1192
1193
1194 static int
1195 internal_ipc_get_reply(crm_ipc_t *client, int request_id, int ms_timeout,
1196 ssize_t *bytes, xmlNode **reply)
1197 {
1198 guint8 *buffer = NULL;
1199 pcmk__ipc_header_t *hdr = NULL;
1200 time_t timeout = 0;
1201 int32_t qb_timeout = -1;
1202 int rc = pcmk_rc_ok;
1203 int reply_id = 0;
1204
1205 if (ms_timeout > 0) {
1206 timeout = time(NULL) + 1 + pcmk__timeout_ms2s(ms_timeout);
1207 qb_timeout = 1000;
1208 }
1209
1210
1211 crm_trace("Expecting reply to %s IPC message %d", client->server_name,
1212 request_id);
1213
1214 buffer = g_malloc0(crm_ipc_default_buffer_size());
1215
1216 do {
1217 guint8 *data = NULL;
1218 xmlNode *xml = NULL;
1219
1220 *bytes = qb_ipcc_recv(client->ipc, buffer, crm_ipc_default_buffer_size(),
1221 qb_timeout);
1222
1223 hdr = (pcmk__ipc_header_t *) (void *) buffer;
1224
1225 if (*bytes <= 0) {
1226 if (!crm_ipc_connected(client)) {
1227 crm_err("%s IPC provider disconnected while waiting for message %d",
1228 client->server_name, request_id);
1229 break;
1230 }
1231
1232 continue;
1233
1234 } else if (*bytes != hdr->size + sizeof(pcmk__ipc_header_t)) {
1235 crm_trace("Message size does not match header");
1236 rc = -EBADMSG;
1237 break;
1238 }
1239
1240 reply_id = hdr->qb.id;
1241
1242 if (reply_id == request_id) {
1243
1244 rc = pcmk__ipc_msg_append(&client->buffer, buffer);
1245
1246 if (rc == pcmk_rc_ok) {
1247 break;
1248 } else if (rc == pcmk_rc_ipc_more) {
1249 continue;
1250 } else {
1251 goto done;
1252 }
1253 }
1254
1255 data = buffer + sizeof(pcmk__ipc_header_t);
1256 xml = pcmk__xml_parse((const char *) data);
1257
1258 if (reply_id < request_id) {
1259 crm_err("Discarding old reply %d (need %d)", reply_id, request_id);
1260 crm_log_xml_notice(xml, "OldIpcReply");
1261 } else if (reply_id > request_id) {
1262 crm_err("Discarding newer reply %d (need %d)", reply_id, request_id);
1263 crm_log_xml_notice(xml, "ImpossibleReply");
1264 pcmk__assert(hdr->qb.id <= request_id);
1265 }
1266 } while (time(NULL) < timeout || (timeout == 0 && *bytes == -EAGAIN));
1267
1268 if (client->buffer->len > 0) {
1269 crm_trace("Received %u-byte reply %d to %s IPC %d: %.100s",
1270 client->buffer->len, reply_id, client->server_name,
1271 request_id, crm_ipc_buffer(client));
1272
1273 if (reply != NULL) {
1274 *reply = pcmk__xml_parse(crm_ipc_buffer(client));
1275 }
1276 } else if (*bytes < 0) {
1277 rc = (int) -*bytes;
1278 crm_trace("No reply to %s IPC %d: %s " QB_XS " rc=%d",
1279 client->server_name, request_id, pcmk_rc_str(rc), rc);
1280 }
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291 done:
1292 pcmk__ipc_free_client_buffer(client);
1293 g_free(buffer);
1294 return rc;
1295 }
1296
1297 static int
1298 discard_old_replies(crm_ipc_t *client, int32_t ms_timeout)
1299 {
1300 pcmk__ipc_header_t *header = NULL;
1301 int rc = pcmk_rc_ok;
1302 ssize_t qb_rc = 0;
1303 char *buffer = pcmk__assert_alloc(crm_ipc_default_buffer_size(),
1304 sizeof(char));
1305
1306 qb_rc = qb_ipcc_recv(client->ipc, buffer, crm_ipc_default_buffer_size(),
1307 ms_timeout);
1308
1309 if (qb_rc < 0) {
1310 crm_warn("Sending %s IPC disabled until pending reply received",
1311 client->server_name);
1312 rc = EALREADY;
1313 goto done;
1314 }
1315
1316 header = (pcmk__ipc_header_t *)(void *) buffer;
1317
1318 if (!pcmk__valid_ipc_header(header)) {
1319 rc = EBADMSG;
1320
1321 } else if (!pcmk_is_set(header->flags, crm_ipc_multipart)
1322 || pcmk_is_set(header->flags, crm_ipc_multipart_end)) {
1323 crm_notice("Sending %s IPC re-enabled after pending reply received",
1324 client->server_name);
1325 client->need_reply = FALSE;
1326
1327 } else {
1328 crm_warn("Sending %s IPC disabled until multipart IPC message "
1329 "reply received", client->server_name);
1330 rc = EALREADY;
1331 }
1332
1333 done:
1334 free(buffer);
1335 return rc;
1336 }
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351 int
1352 crm_ipc_send(crm_ipc_t *client, const xmlNode *message,
1353 enum crm_ipc_flags flags, int32_t ms_timeout, xmlNode **reply)
1354 {
1355 int rc = 0;
1356 ssize_t bytes = 0;
1357 ssize_t sent_bytes = 0;
1358 struct iovec *iov = NULL;
1359 static uint32_t id = 0;
1360 pcmk__ipc_header_t *header;
1361 GString *iov_buffer = NULL;
1362 uint16_t index = 0;
1363
1364 if (client == NULL) {
1365 crm_notice("Can't send IPC request without connection (bug?): %.100s",
1366 message);
1367 return -ENOTCONN;
1368
1369 } else if (!crm_ipc_connected(client)) {
1370
1371 crm_notice("Can't send %s IPC requests: Connection closed",
1372 client->server_name);
1373 return -ENOTCONN;
1374 }
1375
1376 if (ms_timeout == 0) {
1377 ms_timeout = 5000;
1378 }
1379
1380
1381
1382
1383
1384 if (client->need_reply) {
1385 int discard_rc = discard_old_replies(client, ms_timeout);
1386
1387 if (discard_rc != pcmk_rc_ok) {
1388 return pcmk_rc2legacy(discard_rc);
1389 }
1390 }
1391
1392 id++;
1393 CRM_LOG_ASSERT(id != 0);
1394
1395 iov_buffer = g_string_sized_new(1024);
1396 pcmk__xml_string(message, 0, iov_buffer, 0);
1397
1398 do {
1399 ssize_t qb_rc = 0;
1400 time_t timeout = 0;
1401
1402 rc = pcmk__ipc_prepare_iov(id, iov_buffer, index, &iov, &bytes);
1403
1404 if ((rc != pcmk_rc_ok) && (rc != pcmk_rc_ipc_more)) {
1405 crm_warn("Couldn't prepare %s IPC request: %s " QB_XS " rc=%d",
1406 client->server_name, pcmk_rc_str(rc), rc);
1407 g_string_free(iov_buffer, TRUE);
1408 return pcmk_rc2legacy(rc);
1409 }
1410
1411 header = iov[0].iov_base;
1412 pcmk__set_ipc_flags(header->flags, client->server_name, flags);
1413
1414 if (pcmk_is_set(flags, crm_ipc_proxied)) {
1415
1416 pcmk__clear_ipc_flags(flags, "client", crm_ipc_client_response);
1417 }
1418
1419 if (pcmk_is_set(header->flags, crm_ipc_multipart)) {
1420 bool is_end = pcmk_is_set(header->flags, crm_ipc_multipart_end);
1421 crm_trace("Sending %s IPC request %" PRId32 " (%spart %" PRIu16 ") of "
1422 "%" PRId32 " bytes using %dms timeout",
1423 client->server_name, header->qb.id, is_end ? "final " : "",
1424 index, header->qb.size, ms_timeout);
1425 crm_trace("Text = %s", (char *) iov[1].iov_base);
1426 } else {
1427 crm_trace("Sending %s IPC request %" PRId32 " of %" PRId32 " bytes "
1428 "using %dms timeout",
1429 client->server_name, header->qb.id, header->qb.size,
1430 ms_timeout);
1431 crm_trace("Text = %s", (char *) iov[1].iov_base);
1432 }
1433
1434
1435 if (ms_timeout > 0) {
1436 timeout = time(NULL) + 1 + pcmk__timeout_ms2s(ms_timeout);
1437 }
1438
1439 do {
1440 qb_rc = qb_ipcc_sendv(client->ipc, iov, 2);
1441 } while ((qb_rc == -EAGAIN) && ((timeout == 0) || (time(NULL) < timeout)));
1442
1443
1444 if (qb_rc <= 0) {
1445 rc = (int) qb_rc;
1446 goto send_cleanup;
1447 }
1448
1449
1450
1451
1452 if (rc == pcmk_rc_ok) {
1453
1454
1455
1456
1457 sent_bytes += qb_rc;
1458 rc = (int) sent_bytes;
1459 break;
1460 } else {
1461
1462
1463
1464
1465
1466 sent_bytes += qb_rc;
1467 index++;
1468 }
1469
1470 pcmk_free_ipc_event(iov);
1471 iov = NULL;
1472 } while (true);
1473
1474
1475 if (!pcmk_is_set(flags, crm_ipc_client_response)) {
1476 crm_trace("Not waiting for reply to %s IPC request %d",
1477 client->server_name, header->qb.id);
1478 goto send_cleanup;
1479 }
1480
1481 pcmk__ipc_free_client_buffer(client);
1482 rc = internal_ipc_get_reply(client, header->qb.id, ms_timeout, &bytes, reply);
1483 if (rc == pcmk_rc_ok) {
1484 rc = (int) bytes;
1485 } else {
1486
1487
1488
1489
1490 rc = pcmk_rc2legacy(rc);
1491
1492 if (ms_timeout > 0) {
1493
1494
1495
1496
1497
1498
1499 client->need_reply = TRUE;
1500 }
1501 }
1502
1503 send_cleanup:
1504 if (!crm_ipc_connected(client)) {
1505 crm_notice("Couldn't send %s IPC request %d: Connection closed "
1506 QB_XS " rc=%d", client->server_name, header->qb.id, rc);
1507
1508 } else if (rc == -ETIMEDOUT) {
1509 crm_warn("%s IPC request %d failed: %s after %dms " QB_XS " rc=%d",
1510 client->server_name, header->qb.id, pcmk_strerror(rc),
1511 ms_timeout, rc);
1512 crm_write_blackbox(0, NULL);
1513
1514 } else if (rc <= 0) {
1515 crm_warn("%s IPC request %d failed: %s " QB_XS " rc=%d",
1516 client->server_name, header->qb.id,
1517 ((rc == 0)? "No bytes sent" : pcmk_strerror(rc)), rc);
1518 }
1519
1520 g_string_free(iov_buffer, TRUE);
1521 pcmk_free_ipc_event(iov);
1522
1523 return rc;
1524 }
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543 static int
1544 is_ipc_provider_expected(qb_ipcc_connection_t *qb_ipc, int sock,
1545 uid_t refuid, gid_t refgid,
1546 pid_t *gotpid, uid_t *gotuid, gid_t *gotgid)
1547 {
1548 int rc = EOPNOTSUPP;
1549 pid_t found_pid = 0;
1550 uid_t found_uid = 0;
1551 gid_t found_gid = 0;
1552
1553 #ifdef HAVE_QB_IPCC_AUTH_GET
1554 if (qb_ipc != NULL) {
1555 rc = qb_ipcc_auth_get(qb_ipc, &found_pid, &found_uid, &found_gid);
1556 rc = -rc;
1557 if (rc == pcmk_rc_ok) {
1558 goto found;
1559 }
1560 }
1561 #endif
1562
1563 #ifdef HAVE_UCRED
1564 {
1565 struct ucred ucred;
1566 socklen_t ucred_len = sizeof(ucred);
1567
1568 if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &ucred_len) < 0) {
1569 rc = errno;
1570 } else if (ucred_len != sizeof(ucred)) {
1571 rc = EOPNOTSUPP;
1572 } else {
1573 found_pid = ucred.pid;
1574 found_uid = ucred.uid;
1575 found_gid = ucred.gid;
1576 goto found;
1577 }
1578 }
1579 #endif
1580
1581 #ifdef HAVE_SOCKPEERCRED
1582 {
1583 struct sockpeercred sockpeercred;
1584 socklen_t sockpeercred_len = sizeof(sockpeercred);
1585
1586 if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED,
1587 &sockpeercred, &sockpeercred_len) < 0) {
1588 rc = errno;
1589 } else if (sockpeercred_len != sizeof(sockpeercred)) {
1590 rc = EOPNOTSUPP;
1591 } else {
1592 found_pid = sockpeercred.pid;
1593 found_uid = sockpeercred.uid;
1594 found_gid = sockpeercred.gid;
1595 goto found;
1596 }
1597 }
1598 #endif
1599
1600 #ifdef HAVE_GETPEEREID
1601 if (getpeereid(sock, &found_uid, &found_gid) < 0) {
1602 rc = errno;
1603 } else {
1604 found_pid = PCMK__SPECIAL_PID;
1605 goto found;
1606 }
1607 #endif
1608
1609 #ifdef HAVE_GETPEERUCRED
1610 {
1611 ucred_t *ucred = NULL;
1612
1613 if (getpeerucred(sock, &ucred) < 0) {
1614 rc = errno;
1615 } else {
1616 found_pid = ucred_getpid(ucred);
1617 found_uid = ucred_geteuid(ucred);
1618 found_gid = ucred_getegid(ucred);
1619 ucred_free(ucred);
1620 goto found;
1621 }
1622 }
1623 #endif
1624
1625 return rc;
1626
1627 found:
1628 if (gotpid != NULL) {
1629 *gotpid = found_pid;
1630 }
1631 if (gotuid != NULL) {
1632 *gotuid = found_uid;
1633 }
1634 if (gotgid != NULL) {
1635 *gotgid = found_gid;
1636 }
1637 if ((found_uid != 0) && (found_uid != refuid) && (found_gid != refgid)) {
1638 return pcmk_rc_ipc_unauthorized;
1639 }
1640 return pcmk_rc_ok;
1641 }
1642
1643 int
1644 crm_ipc_is_authentic_process(int sock, uid_t refuid, gid_t refgid,
1645 pid_t *gotpid, uid_t *gotuid, gid_t *gotgid)
1646 {
1647 int ret = is_ipc_provider_expected(NULL, sock, refuid, refgid,
1648 gotpid, gotuid, gotgid);
1649
1650
1651 if (ret == 0) {
1652 return 1;
1653 } else if (ret == pcmk_rc_ipc_unauthorized) {
1654 return 0;
1655 } else {
1656 return pcmk_rc2legacy(ret);
1657 }
1658 }
1659
1660 int
1661 pcmk__ipc_is_authentic_process_active(const char *name, uid_t refuid,
1662 gid_t refgid, pid_t *gotpid)
1663 {
1664 static char last_asked_name[PATH_MAX / 2] = "";
1665 int fd;
1666 int rc = pcmk_rc_ipc_unresponsive;
1667 int auth_rc = 0;
1668 int32_t qb_rc;
1669 pid_t found_pid = 0; uid_t found_uid = 0; gid_t found_gid = 0;
1670 qb_ipcc_connection_t *c;
1671 #ifdef HAVE_QB_IPCC_CONNECT_ASYNC
1672 struct pollfd pollfd = { 0, };
1673 int poll_rc;
1674
1675 c = qb_ipcc_connect_async(name, 0,
1676 &(pollfd.fd));
1677 #else
1678 c = qb_ipcc_connect(name, 0);
1679 #endif
1680 if (c == NULL) {
1681 crm_info("Could not connect to %s IPC: %s", name, strerror(errno));
1682 rc = pcmk_rc_ipc_unresponsive;
1683 goto bail;
1684 }
1685 #ifdef HAVE_QB_IPCC_CONNECT_ASYNC
1686 pollfd.events = POLLIN;
1687 do {
1688 poll_rc = poll(&pollfd, 1, 2000);
1689 } while ((poll_rc == -1) && (errno == EINTR));
1690
1691
1692
1693
1694
1695
1696 if (qb_ipcc_connect_continue(c) != 0) {
1697 crm_info("Could not connect to %s IPC: %s", name,
1698 (poll_rc == 0)?"timeout":strerror(errno));
1699 rc = pcmk_rc_ipc_unresponsive;
1700 c = NULL;
1701 goto bail;
1702 }
1703 #endif
1704
1705 qb_rc = qb_ipcc_fd_get(c, &fd);
1706 if (qb_rc != 0) {
1707 rc = (int) -qb_rc;
1708 crm_err("Could not get fd from %s IPC: %s " QB_XS " rc=%d",
1709 name, pcmk_rc_str(rc), rc);
1710 goto bail;
1711 }
1712
1713 auth_rc = is_ipc_provider_expected(c, fd, refuid, refgid,
1714 &found_pid, &found_uid, &found_gid);
1715 if (auth_rc == pcmk_rc_ipc_unauthorized) {
1716 crm_err("Daemon (IPC %s) effectively blocked with unauthorized"
1717 " process %lld (uid: %lld, gid: %lld)",
1718 name, (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
1719 (long long) found_uid, (long long) found_gid);
1720 rc = pcmk_rc_ipc_unauthorized;
1721 goto bail;
1722 }
1723
1724 if (auth_rc != pcmk_rc_ok) {
1725 rc = auth_rc;
1726 crm_err("Could not get peer credentials from %s IPC: %s "
1727 QB_XS " rc=%d", name, pcmk_rc_str(rc), rc);
1728 goto bail;
1729 }
1730
1731 if (gotpid != NULL) {
1732 *gotpid = found_pid;
1733 }
1734
1735 rc = pcmk_rc_ok;
1736 if ((found_uid != refuid || found_gid != refgid)
1737 && strncmp(last_asked_name, name, sizeof(last_asked_name))) {
1738 if ((found_uid == 0) && (refuid != 0)) {
1739 crm_warn("Daemon (IPC %s) runs as root, whereas the expected"
1740 " credentials are %lld:%lld, hazard of violating"
1741 " the least privilege principle",
1742 name, (long long) refuid, (long long) refgid);
1743 } else {
1744 crm_notice("Daemon (IPC %s) runs as %lld:%lld, whereas the"
1745 " expected credentials are %lld:%lld, which may"
1746 " mean a different set of privileges than expected",
1747 name, (long long) found_uid, (long long) found_gid,
1748 (long long) refuid, (long long) refgid);
1749 }
1750 memccpy(last_asked_name, name, '\0', sizeof(last_asked_name));
1751 }
1752
1753 bail:
1754 if (c != NULL) {
1755 qb_ipcc_disconnect(c);
1756 }
1757 return rc;
1758 }
1759
1760
1761
1762
1763 #include <crm/common/ipc_client_compat.h>
1764
1765 bool
1766 crm_ipc_connect(crm_ipc_t *client)
1767 {
1768 int rc = pcmk__connect_generic_ipc(client);
1769
1770 if (rc == pcmk_rc_ok) {
1771 return true;
1772 }
1773 if ((client != NULL) && (client->ipc == NULL)) {
1774 errno = (rc > 0)? rc : ENOTCONN;
1775 crm_debug("Could not establish %s IPC connection: %s (%d)",
1776 client->server_name, pcmk_rc_str(errno), errno);
1777 } else if (rc == pcmk_rc_ipc_unauthorized) {
1778 crm_err("%s IPC provider authentication failed",
1779 (client == NULL)? "Pacemaker" : client->server_name);
1780 errno = ECONNABORTED;
1781 } else {
1782 crm_err("Could not verify authenticity of %s IPC provider",
1783 (client == NULL)? "Pacemaker" : client->server_name);
1784 errno = ENOTCONN;
1785 }
1786 return false;
1787 }
1788
1789
1790