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 free_xml(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
161
162
163
164 if (pcmk__str_eq(msg_type, LRMD_IPC_OP_SHUTDOWN_ACK, pcmk__str_casei)) {
165 handle_shutdown_ack();
166 return;
167 }
168
169 if (pcmk__str_eq(msg_type, LRMD_IPC_OP_SHUTDOWN_NACK, pcmk__str_casei)) {
170 handle_shutdown_nack();
171 return;
172 }
173
174 ipc_client = pcmk__find_client_by_id(session);
175 if (ipc_client == NULL) {
176 xmlNode *msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
177 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_DESTROY);
178 crm_xml_add(msg, PCMK__XA_LRMD_IPC_SESSION, session);
179 lrmd_server_send_notify(ipc_proxy, msg);
180 free_xml(msg);
181 return;
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 if (pcmk__str_eq(msg_type, LRMD_IPC_OP_EVENT, pcmk__str_casei)) {
199 crm_trace("Sending event to %s", ipc_client->id);
200 rc = pcmk__ipc_send_xml(ipc_client, 0, msg, crm_ipc_server_event);
201
202 } else if (pcmk__str_eq(msg_type, LRMD_IPC_OP_RESPONSE, pcmk__str_casei)) {
203 int msg_id = 0;
204
205 crm_element_value_int(xml, PCMK__XA_LRMD_IPC_MSG_ID, &msg_id);
206 crm_trace("Sending response to %d - %s", ipc_client->request_id, ipc_client->id);
207 rc = pcmk__ipc_send_xml(ipc_client, msg_id, msg, FALSE);
208
209 CRM_LOG_ASSERT(msg_id == ipc_client->request_id);
210 ipc_client->request_id = 0;
211
212 } else if (pcmk__str_eq(msg_type, LRMD_IPC_OP_DESTROY, pcmk__str_casei)) {
213 qb_ipcs_disconnect(ipc_client->ipcs);
214
215 } else {
216 crm_err("Unknown ipc proxy msg type %s" , msg_type);
217 }
218
219 if (rc != pcmk_rc_ok) {
220 crm_warn("Could not proxy IPC to client %s: %s " CRM_XS " rc=%d",
221 ipc_client->id, pcmk_rc_str(rc), rc);
222 }
223 }
224
225 static int32_t
226 ipc_proxy_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
227 {
228 uint32_t id = 0;
229 uint32_t flags = 0;
230 pcmk__client_t *client = pcmk__find_client(c);
231 pcmk__client_t *ipc_proxy = pcmk__find_client_by_id(client->userdata);
232 xmlNode *wrapper = NULL;
233 xmlNode *request = NULL;
234 xmlNode *msg = NULL;
235
236 if (!ipc_proxy) {
237 qb_ipcs_disconnect(client->ipcs);
238 return 0;
239 }
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254 request = pcmk__client_data2xml(client, data, &id, &flags);
255
256 if (!request) {
257 return 0;
258 }
259
260 CRM_CHECK(client != NULL, crm_err("Invalid client");
261 free_xml(request); return FALSE);
262 CRM_CHECK(client->id != NULL, crm_err("Invalid client: %p", client);
263 free_xml(request); return FALSE);
264
265
266
267
268 pcmk__set_ipc_flags(flags, pcmk__client_name(client), crm_ipc_proxied);
269 client->request_id = id;
270
271 msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
272 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_REQUEST);
273 crm_xml_add(msg, PCMK__XA_LRMD_IPC_SESSION, client->id);
274 crm_xml_add(msg, PCMK__XA_LRMD_IPC_CLIENT, pcmk__client_name(client));
275 crm_xml_add(msg, PCMK__XA_LRMD_IPC_USER, client->user);
276 crm_xml_add_int(msg, PCMK__XA_LRMD_IPC_MSG_ID, id);
277 crm_xml_add_int(msg, PCMK__XA_LRMD_IPC_MSG_FLAGS, flags);
278
279 wrapper = pcmk__xe_create(msg, PCMK__XE_LRMD_IPC_MSG);
280
281 pcmk__xml_copy(wrapper, request);
282
283 lrmd_server_send_notify(ipc_proxy, msg);
284
285 free_xml(request);
286 free_xml(msg);
287 return 0;
288 }
289
290
291
292
293
294
295
296
297
298 int
299 ipc_proxy_shutdown_req(pcmk__client_t *ipc_proxy)
300 {
301 xmlNode *msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
302 int rc;
303
304 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_SHUTDOWN_REQ);
305
306
307
308
309 crm_xml_add(msg, PCMK__XA_LRMD_IPC_SESSION, "0");
310
311 rc = (lrmd_server_send_notify(ipc_proxy, msg) != pcmk_rc_ok)? -1 : 0;
312 free_xml(msg);
313 return rc;
314 }
315
316 static int32_t
317 ipc_proxy_closed(qb_ipcs_connection_t * c)
318 {
319 pcmk__client_t *client = pcmk__find_client(c);
320 pcmk__client_t *ipc_proxy;
321
322 if (client == NULL) {
323 return 0;
324 }
325
326 ipc_proxy = pcmk__find_client_by_id(client->userdata);
327
328 crm_trace("Connection %p", c);
329
330 if (ipc_proxy) {
331 xmlNode *msg = pcmk__xe_create(NULL, PCMK__XE_LRMD_IPC_PROXY);
332 crm_xml_add(msg, PCMK__XA_LRMD_IPC_OP, LRMD_IPC_OP_DESTROY);
333 crm_xml_add(msg, PCMK__XA_LRMD_IPC_SESSION, client->id);
334 lrmd_server_send_notify(ipc_proxy, msg);
335 free_xml(msg);
336 }
337
338 g_hash_table_remove(ipc_clients, client->id);
339
340 free(client->userdata);
341 client->userdata = NULL;
342 pcmk__free_client(client);
343 return 0;
344 }
345
346 static void
347 ipc_proxy_destroy(qb_ipcs_connection_t * c)
348 {
349 crm_trace("Connection %p", c);
350 ipc_proxy_closed(c);
351 }
352
353 static struct qb_ipcs_service_handlers crmd_proxy_callbacks = {
354 .connection_accept = crmd_proxy_accept,
355 .connection_created = NULL,
356 .msg_process = ipc_proxy_dispatch,
357 .connection_closed = ipc_proxy_closed,
358 .connection_destroyed = ipc_proxy_destroy
359 };
360
361 static struct qb_ipcs_service_handlers attrd_proxy_callbacks = {
362 .connection_accept = attrd_proxy_accept,
363 .connection_created = NULL,
364 .msg_process = ipc_proxy_dispatch,
365 .connection_closed = ipc_proxy_closed,
366 .connection_destroyed = ipc_proxy_destroy
367 };
368
369 static struct qb_ipcs_service_handlers stonith_proxy_callbacks = {
370 .connection_accept = stonith_proxy_accept,
371 .connection_created = NULL,
372 .msg_process = ipc_proxy_dispatch,
373 .connection_closed = ipc_proxy_closed,
374 .connection_destroyed = ipc_proxy_destroy
375 };
376
377 static struct qb_ipcs_service_handlers pacemakerd_proxy_callbacks = {
378 .connection_accept = pacemakerd_proxy_accept,
379 .connection_created = NULL,
380 .msg_process = NULL,
381 .connection_closed = NULL,
382 .connection_destroyed = NULL
383 };
384
385 static struct qb_ipcs_service_handlers cib_proxy_callbacks_ro = {
386 .connection_accept = cib_proxy_accept_ro,
387 .connection_created = NULL,
388 .msg_process = ipc_proxy_dispatch,
389 .connection_closed = ipc_proxy_closed,
390 .connection_destroyed = ipc_proxy_destroy
391 };
392
393 static struct qb_ipcs_service_handlers cib_proxy_callbacks_rw = {
394 .connection_accept = cib_proxy_accept_rw,
395 .connection_created = NULL,
396 .msg_process = ipc_proxy_dispatch,
397 .connection_closed = ipc_proxy_closed,
398 .connection_destroyed = ipc_proxy_destroy
399 };
400
401 void
402 ipc_proxy_add_provider(pcmk__client_t *ipc_proxy)
403 {
404
405 ipc_providers = g_list_prepend(ipc_providers, ipc_proxy);
406 }
407
408 void
409 ipc_proxy_remove_provider(pcmk__client_t *ipc_proxy)
410 {
411 GHashTableIter iter;
412 pcmk__client_t *ipc_client = NULL;
413 char *key = NULL;
414 GList *remove_these = NULL;
415 GList *gIter = NULL;
416
417 ipc_providers = g_list_remove(ipc_providers, ipc_proxy);
418
419 g_hash_table_iter_init(&iter, ipc_clients);
420 while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & ipc_client)) {
421 const char *proxy_id = ipc_client->userdata;
422 if (pcmk__str_eq(proxy_id, ipc_proxy->id, pcmk__str_casei)) {
423 crm_info("ipc proxy connection for client %s pid %d destroyed because cluster node disconnected.",
424 ipc_client->id, ipc_client->pid);
425
426
427 remove_these = g_list_append(remove_these, ipc_client);
428 }
429 }
430
431 for (gIter = remove_these; gIter != NULL; gIter = gIter->next) {
432 ipc_client = gIter->data;
433
434
435 qb_ipcs_disconnect(ipc_client->ipcs);
436 }
437
438
439 g_list_free(remove_these);
440 }
441
442 void
443 ipc_proxy_init(void)
444 {
445 ipc_clients = pcmk__strkey_table(NULL, NULL);
446
447 pcmk__serve_based_ipc(&cib_ro, &cib_rw, &cib_shm, &cib_proxy_callbacks_ro,
448 &cib_proxy_callbacks_rw);
449 pcmk__serve_attrd_ipc(&attrd_ipcs, &attrd_proxy_callbacks);
450 pcmk__serve_fenced_ipc(&stonith_ipcs, &stonith_proxy_callbacks);
451 pcmk__serve_pacemakerd_ipc(&pacemakerd_ipcs, &pacemakerd_proxy_callbacks);
452 crmd_ipcs = pcmk__serve_controld_ipc(&crmd_proxy_callbacks);
453 if (crmd_ipcs == NULL) {
454 crm_err("Failed to create controller: exiting and inhibiting respawn");
455 crm_warn("Verify pacemaker and pacemaker_remote are not both enabled");
456 crm_exit(CRM_EX_FATAL);
457 }
458 }
459
460 void
461 ipc_proxy_cleanup(void)
462 {
463 if (ipc_providers) {
464 g_list_free(ipc_providers);
465 ipc_providers = NULL;
466 }
467 if (ipc_clients) {
468 g_hash_table_destroy(ipc_clients);
469 ipc_clients = NULL;
470 }
471 pcmk__stop_based_ipc(cib_ro, cib_rw, cib_shm);
472 qb_ipcs_destroy(attrd_ipcs);
473 qb_ipcs_destroy(stonith_ipcs);
474 qb_ipcs_destroy(pacemakerd_ipcs);
475 qb_ipcs_destroy(crmd_ipcs);
476 cib_ro = NULL;
477 cib_rw = NULL;
478 cib_shm = NULL;
479 }