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