This source file includes following definitions.
- ipc_proxy_get_provider
- ipc_proxy_accept
- crmd_proxy_accept
- attrd_proxy_accept
- stonith_proxy_accept
- pacemakerd_proxy_accept
- cib_proxy_accept_rw
- cib_proxy_accept_ro
- ipc_proxy_forward_client
- ipc_proxy_dispatch
- ipc_proxy_shutdown_req
- ipc_proxy_closed
- ipc_proxy_destroy
- ipc_proxy_add_provider
- ipc_proxy_remove_provider
- ipc_proxy_init
- ipc_proxy_cleanup
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <glib.h>
13 #include <unistd.h>
14
15 #include "pacemaker-execd.h"
16 #include <crm/crm.h>
17 #include <crm/common/xml.h>
18 #include <crm/services.h>
19 #include <crm/common/mainloop.h>
20 #include <crm/common/ipc.h>
21 #include <crm/common/ipc_internal.h>
22 #include <crm/cib/internal.h>
23 #include <crm/fencing/internal.h>
24
25 static qb_ipcs_service_t *cib_ro = NULL;
26 static qb_ipcs_service_t *cib_rw = NULL;
27 static qb_ipcs_service_t *cib_shm = NULL;
28
29 static qb_ipcs_service_t *attrd_ipcs = NULL;
30 static qb_ipcs_service_t *crmd_ipcs = NULL;
31 static qb_ipcs_service_t *stonith_ipcs = NULL;
32 static qb_ipcs_service_t *pacemakerd_ipcs = NULL;
33
34
35 static GList *ipc_providers = NULL;
36
37 static GHashTable *ipc_clients = NULL;
38
39
40
41
42
43
44
45
46
47
48
49 pcmk__client_t *
50 ipc_proxy_get_provider(void)
51 {
52 return ipc_providers? (pcmk__client_t *) (ipc_providers->data) : NULL;
53 }
54
55
56
57
58
59
60
61
62
63
64
65
66 static int32_t
67 ipc_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid, const char *ipc_channel)
68 {
69 pcmk__client_t *client;
70 pcmk__client_t *ipc_proxy = ipc_proxy_get_provider();
71 xmlNode *msg;
72
73 if (ipc_proxy == NULL) {
74 crm_warn("Cannot proxy IPC connection from uid %d gid %d to %s "
75 "because not connected to cluster", uid, gid, ipc_channel);
76 return -EREMOTEIO;
77 }
78
79
80
81
82 client = pcmk__new_client(c, uid, gid);
83 if (client == NULL) {
84 return -ENOMEM;
85 }
86
87
88
89 client->userdata = pcmk__str_copy(ipc_proxy->id);
90 client->name = crm_strdup_printf("proxy-%s-%d-%.8s", ipc_channel, client->pid, client->id);
91
92
93
94
95 pcmk__set_client_flags(client, pcmk__client_to_proxy);
96
97 g_hash_table_insert(ipc_clients, client->id, client);
98
99 msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
100 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_NEW);
101 crm_xml_add(msg, PCMK__XA_LRMD_IPC_SERVER, ipc_channel);
102 crm_xml_add(msg, PCMK__XA_LRMD_IPC_SESSION, client->id);
103 lrmd_server_send_notify(ipc_proxy, msg);
104 pcmk__xml_free(msg);
105 crm_debug("Accepted IPC proxy connection (session ID %s) "
106 "from uid %d gid %d on channel %s",
107 client->id, uid, gid, ipc_channel);
108 return 0;
109 }
110
111 static int32_t
112 crmd_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
113 {
114 return ipc_proxy_accept(c, uid, gid, CRM_SYSTEM_CRMD);
115 }
116
117 static int32_t
118 attrd_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
119 {
120 return ipc_proxy_accept(c, uid, gid, PCMK__VALUE_ATTRD);
121 }
122
123 static int32_t
124 stonith_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
125 {
126 return ipc_proxy_accept(c, uid, gid, "stonith-ng");
127 }
128
129 static int32_t
130 pacemakerd_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
131 {
132 return -EREMOTEIO;
133 }
134
135 static int32_t
136 cib_proxy_accept_rw(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
137 {
138 return ipc_proxy_accept(c, uid, gid, PCMK__SERVER_BASED_RW);
139 }
140
141 static int32_t
142 cib_proxy_accept_ro(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
143 {
144 return ipc_proxy_accept(c, uid, gid, PCMK__SERVER_BASED_RO);
145 }
146
147 void
148 ipc_proxy_forward_client(pcmk__client_t *ipc_proxy, xmlNode *xml)
149 {
150 const char *session = crm_element_value(xml, PCMK__XA_LRMD_IPC_SESSION);
151 const char *msg_type = crm_element_value(xml, PCMK__XA_LRMD_IPC_OP);
152
153 xmlNode *wrapper = pcmk__xe_first_child(xml, PCMK__XE_LRMD_IPC_MSG, NULL,
154 NULL);
155 xmlNode *msg = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
156
157 pcmk__client_t *ipc_client;
158 int rc = pcmk_rc_ok;
159
160 if (pcmk__str_eq(msg_type, LRMD_IPC_OP_SHUTDOWN_ACK, pcmk__str_casei)) {
161 handle_shutdown_ack();
162 return;
163 }
164
165 if (pcmk__str_eq(msg_type, LRMD_IPC_OP_SHUTDOWN_NACK, pcmk__str_casei)) {
166 handle_shutdown_nack();
167 return;
168 }
169
170 ipc_client = pcmk__find_client_by_id(session);
171 if (ipc_client == NULL) {
172 xmlNode *msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
173 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_DESTROY);
174 crm_xml_add(msg, PCMK__XA_LRMD_IPC_SESSION, session);
175 lrmd_server_send_notify(ipc_proxy, msg);
176 pcmk__xml_free(msg);
177 return;
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 if (pcmk__str_eq(msg_type, LRMD_IPC_OP_EVENT, pcmk__str_casei)) {
195 crm_trace("Sending event to %s", ipc_client->id);
196 rc = pcmk__ipc_send_xml(ipc_client, 0, msg, crm_ipc_server_event);
197
198 } else if (pcmk__str_eq(msg_type, LRMD_IPC_OP_RESPONSE, pcmk__str_casei)) {
199 int msg_id = 0;
200
201 crm_element_value_int(xml, PCMK__XA_LRMD_IPC_MSG_ID, &msg_id);
202 crm_trace("Sending response to %d - %s", ipc_client->request_id, ipc_client->id);
203 rc = pcmk__ipc_send_xml(ipc_client, msg_id, msg, FALSE);
204
205 CRM_LOG_ASSERT(msg_id == ipc_client->request_id);
206 ipc_client->request_id = 0;
207
208 } else if (pcmk__str_eq(msg_type, LRMD_IPC_OP_DESTROY, pcmk__str_casei)) {
209 qb_ipcs_disconnect(ipc_client->ipcs);
210
211 } else {
212 crm_err("Unknown ipc proxy msg type %s" , msg_type);
213 }
214
215 if (rc != pcmk_rc_ok) {
216 crm_warn("Could not proxy IPC to client %s: %s " QB_XS " rc=%d",
217 ipc_client->id, pcmk_rc_str(rc), rc);
218 }
219 }
220
221 static int32_t
222 ipc_proxy_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
223 {
224 uint32_t id = 0;
225 uint32_t flags = 0;
226 pcmk__client_t *client = pcmk__find_client(c);
227 pcmk__client_t *ipc_proxy = pcmk__find_client_by_id(client->userdata);
228 xmlNode *wrapper = NULL;
229 xmlNode *request = NULL;
230 xmlNode *msg = NULL;
231
232 if (!ipc_proxy) {
233 qb_ipcs_disconnect(client->ipcs);
234 return 0;
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250 request = pcmk__client_data2xml(client, data, &id, &flags);
251
252 if (!request) {
253 return 0;
254 }
255
256 CRM_CHECK(client != NULL, crm_err("Invalid client");
257 pcmk__xml_free(request); return FALSE);
258 CRM_CHECK(client->id != NULL, crm_err("Invalid client: %p", client);
259 pcmk__xml_free(request); return FALSE);
260
261
262
263
264 pcmk__set_ipc_flags(flags, pcmk__client_name(client), crm_ipc_proxied);
265 client->request_id = id;
266
267 msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
268 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_REQUEST);
269 crm_xml_add(msg, PCMK__XA_LRMD_IPC_SESSION, client->id);
270 crm_xml_add(msg, PCMK__XA_LRMD_IPC_CLIENT, pcmk__client_name(client));
271 crm_xml_add(msg, PCMK__XA_LRMD_IPC_USER, client->user);
272 crm_xml_add_int(msg, PCMK__XA_LRMD_IPC_MSG_ID, id);
273 crm_xml_add_int(msg, PCMK__XA_LRMD_IPC_MSG_FLAGS, flags);
274
275 wrapper = pcmk__xe_create(msg, PCMK__XE_LRMD_IPC_MSG);
276
277 pcmk__xml_copy(wrapper, request);
278
279 lrmd_server_send_notify(ipc_proxy, msg);
280
281 pcmk__xml_free(request);
282 pcmk__xml_free(msg);
283 return 0;
284 }
285
286
287
288
289
290
291
292
293
294 int
295 ipc_proxy_shutdown_req(pcmk__client_t *ipc_proxy)
296 {
297 xmlNode *msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
298 int rc;
299
300 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_SHUTDOWN_REQ);
301
302
303
304
305 crm_xml_add(msg, PCMK__XA_LRMD_IPC_SESSION, "0");
306
307 rc = (lrmd_server_send_notify(ipc_proxy, msg) != pcmk_rc_ok)? -1 : 0;
308 pcmk__xml_free(msg);
309 return rc;
310 }
311
312 static int32_t
313 ipc_proxy_closed(qb_ipcs_connection_t * c)
314 {
315 pcmk__client_t *client = pcmk__find_client(c);
316 pcmk__client_t *ipc_proxy;
317
318 if (client == NULL) {
319 return 0;
320 }
321
322 ipc_proxy = pcmk__find_client_by_id(client->userdata);
323
324 crm_trace("Connection %p", c);
325
326 if (ipc_proxy) {
327 xmlNode *msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
328 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_DESTROY);
329 crm_xml_add(msg, PCMK__XA_LRMD_IPC_SESSION, client->id);
330 lrmd_server_send_notify(ipc_proxy, msg);
331 pcmk__xml_free(msg);
332 }
333
334 g_hash_table_remove(ipc_clients, client->id);
335
336 free(client->userdata);
337 client->userdata = NULL;
338 pcmk__free_client(client);
339 return 0;
340 }
341
342 static void
343 ipc_proxy_destroy(qb_ipcs_connection_t * c)
344 {
345 crm_trace("Connection %p", c);
346 ipc_proxy_closed(c);
347 }
348
349 static struct qb_ipcs_service_handlers crmd_proxy_callbacks = {
350 .connection_accept = crmd_proxy_accept,
351 .connection_created = NULL,
352 .msg_process = ipc_proxy_dispatch,
353 .connection_closed = ipc_proxy_closed,
354 .connection_destroyed = ipc_proxy_destroy
355 };
356
357 static struct qb_ipcs_service_handlers attrd_proxy_callbacks = {
358 .connection_accept = attrd_proxy_accept,
359 .connection_created = NULL,
360 .msg_process = ipc_proxy_dispatch,
361 .connection_closed = ipc_proxy_closed,
362 .connection_destroyed = ipc_proxy_destroy
363 };
364
365 static struct qb_ipcs_service_handlers stonith_proxy_callbacks = {
366 .connection_accept = stonith_proxy_accept,
367 .connection_created = NULL,
368 .msg_process = ipc_proxy_dispatch,
369 .connection_closed = ipc_proxy_closed,
370 .connection_destroyed = ipc_proxy_destroy
371 };
372
373 static struct qb_ipcs_service_handlers pacemakerd_proxy_callbacks = {
374 .connection_accept = pacemakerd_proxy_accept,
375 .connection_created = NULL,
376 .msg_process = NULL,
377 .connection_closed = NULL,
378 .connection_destroyed = NULL
379 };
380
381 static struct qb_ipcs_service_handlers cib_proxy_callbacks_ro = {
382 .connection_accept = cib_proxy_accept_ro,
383 .connection_created = NULL,
384 .msg_process = ipc_proxy_dispatch,
385 .connection_closed = ipc_proxy_closed,
386 .connection_destroyed = ipc_proxy_destroy
387 };
388
389 static struct qb_ipcs_service_handlers cib_proxy_callbacks_rw = {
390 .connection_accept = cib_proxy_accept_rw,
391 .connection_created = NULL,
392 .msg_process = ipc_proxy_dispatch,
393 .connection_closed = ipc_proxy_closed,
394 .connection_destroyed = ipc_proxy_destroy
395 };
396
397 void
398 ipc_proxy_add_provider(pcmk__client_t *ipc_proxy)
399 {
400
401 ipc_providers = g_list_prepend(ipc_providers, ipc_proxy);
402 }
403
404 void
405 ipc_proxy_remove_provider(pcmk__client_t *ipc_proxy)
406 {
407 GHashTableIter iter;
408 pcmk__client_t *ipc_client = NULL;
409 char *key = NULL;
410 GList *remove_these = NULL;
411 GList *gIter = NULL;
412
413 ipc_providers = g_list_remove(ipc_providers, ipc_proxy);
414
415 g_hash_table_iter_init(&iter, ipc_clients);
416 while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & ipc_client)) {
417 const char *proxy_id = ipc_client->userdata;
418 if (pcmk__str_eq(proxy_id, ipc_proxy->id, pcmk__str_casei)) {
419 crm_info("ipc proxy connection for client %s pid %d destroyed because cluster node disconnected.",
420 ipc_client->id, ipc_client->pid);
421
422
423 remove_these = g_list_append(remove_these, ipc_client);
424 }
425 }
426
427 for (gIter = remove_these; gIter != NULL; gIter = gIter->next) {
428 ipc_client = gIter->data;
429
430
431 qb_ipcs_disconnect(ipc_client->ipcs);
432 }
433
434
435 g_list_free(remove_these);
436 }
437
438 void
439 ipc_proxy_init(void)
440 {
441 ipc_clients = pcmk__strkey_table(NULL, NULL);
442
443 pcmk__serve_based_ipc(&cib_ro, &cib_rw, &cib_shm, &cib_proxy_callbacks_ro,
444 &cib_proxy_callbacks_rw);
445 pcmk__serve_attrd_ipc(&attrd_ipcs, &attrd_proxy_callbacks);
446 pcmk__serve_fenced_ipc(&stonith_ipcs, &stonith_proxy_callbacks);
447 pcmk__serve_pacemakerd_ipc(&pacemakerd_ipcs, &pacemakerd_proxy_callbacks);
448 crmd_ipcs = pcmk__serve_controld_ipc(&crmd_proxy_callbacks);
449 if (crmd_ipcs == NULL) {
450 crm_err("Failed to create controller: exiting and inhibiting respawn");
451 crm_warn("Verify pacemaker and pacemaker_remote are not both enabled");
452 crm_exit(CRM_EX_FATAL);
453 }
454 }
455
456 void
457 ipc_proxy_cleanup(void)
458 {
459 if (ipc_providers) {
460 g_list_free(ipc_providers);
461 ipc_providers = NULL;
462 }
463 if (ipc_clients) {
464 g_hash_table_destroy(ipc_clients);
465 ipc_clients = NULL;
466 }
467 pcmk__stop_based_ipc(cib_ro, cib_rw, cib_shm);
468 qb_ipcs_destroy(attrd_ipcs);
469 qb_ipcs_destroy(stonith_ipcs);
470 qb_ipcs_destroy(pacemakerd_ipcs);
471 qb_ipcs_destroy(crmd_ipcs);
472 cib_ro = NULL;
473 cib_rw = NULL;
474 cib_shm = NULL;
475 }