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