This source file includes following definitions.
- handle_node_cache_request
- handle_ping_request
- handle_shutdown_request
- handle_unknown_request
- pcmkd_register_handlers
- pcmk_ipc_accept
- pcmk_ipc_closed
- pcmk_ipc_destroy
- pcmk_ipc_dispatch
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include "pacemakerd.h"
12
13 #include <crm/crm.h>
14 #include <crm/common/xml.h>
15
16 #include <errno.h>
17 #include <stdbool.h>
18 #include <stdint.h>
19 #include <string.h>
20 #include <time.h>
21 #include <sys/types.h>
22
23 static GHashTable *pcmkd_handlers = NULL;
24
25 static xmlNode *
26 handle_node_cache_request(pcmk__request_t *request)
27 {
28 crm_trace("Ignoring request from client %s to purge node "
29 "because peer cache is not used",
30 pcmk__client_name(request->ipc_client));
31
32 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
33 PCMK__XE_ACK, NULL, CRM_EX_OK);
34 return NULL;
35 }
36
37 static xmlNode *
38 handle_ping_request(pcmk__request_t *request)
39 {
40 xmlNode *msg = request->xml;
41
42 const char *value = NULL;
43 xmlNode *ping = NULL;
44 xmlNode *reply = NULL;
45 const char *from = crm_element_value(msg, PCMK__XA_CRM_SYS_FROM);
46
47
48 crm_trace("Pinged from " PCMK__XA_CRM_SYS_FROM "='%s' "
49 PCMK_XA_ORIGIN "='%s'",
50 pcmk__s(from, ""),
51 pcmk__s(crm_element_value(msg, PCMK_XA_ORIGIN), ""));
52
53 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
54 PCMK__XE_ACK, NULL, CRM_EX_INDETERMINATE);
55
56 ping = pcmk__xe_create(NULL, PCMK__XE_PING_RESPONSE);
57 value = crm_element_value(msg, PCMK__XA_CRM_SYS_TO);
58 crm_xml_add(ping, PCMK__XA_CRM_SUBSYSTEM, value);
59 crm_xml_add(ping, PCMK__XA_PACEMAKERD_STATE, pacemakerd_state);
60 crm_xml_add_ll(ping, PCMK_XA_CRM_TIMESTAMP,
61 (long long) subdaemon_check_progress);
62 crm_xml_add(ping, PCMK_XA_RESULT, "ok");
63 reply = pcmk__new_reply(msg, ping);
64
65 pcmk__xml_free(ping);
66
67 if (reply == NULL) {
68 pcmk__format_result(&request->result, CRM_EX_ERROR, PCMK_EXEC_ERROR,
69 "Failed building ping reply for client %s",
70 pcmk__client_name(request->ipc_client));
71 } else {
72 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
73 }
74
75
76 if (from && strstr(from, "sbd")) {
77 if (pcmk__str_eq(pacemakerd_state, PCMK__VALUE_SHUTDOWN_COMPLETE,
78 pcmk__str_none)) {
79 if (pcmk__get_sbd_sync_resource_startup()) {
80 crm_notice("Shutdown-complete-state passed to SBD.");
81 }
82
83 shutdown_complete_state_reported_to = request->ipc_client->pid;
84
85 } else if (pcmk__str_eq(pacemakerd_state, PCMK__VALUE_WAIT_FOR_PING,
86 pcmk__str_none)) {
87 crm_notice("Received startup-trigger from SBD.");
88 pacemakerd_state = PCMK__VALUE_STARTING_DAEMONS;
89 mainloop_set_trigger(startup_trigger);
90 }
91 }
92
93 return reply;
94 }
95
96 static xmlNode *
97 handle_shutdown_request(pcmk__request_t *request)
98 {
99 xmlNode *msg = request->xml;
100
101 xmlNode *shutdown = NULL;
102 xmlNode *reply = NULL;
103
104
105
106
107
108 bool allowed = pcmk_is_set(request->ipc_client->flags, pcmk__client_privileged);
109
110 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
111 PCMK__XE_ACK, NULL, CRM_EX_INDETERMINATE);
112
113 shutdown = pcmk__xe_create(NULL, PCMK__XE_SHUTDOWN);
114
115 if (allowed) {
116 crm_notice("Shutting down in response to IPC request %s from %s",
117 crm_element_value(msg, PCMK_XA_REFERENCE),
118 crm_element_value(msg, PCMK_XA_ORIGIN));
119 crm_xml_add_int(shutdown, PCMK__XA_OP_STATUS, CRM_EX_OK);
120 } else {
121 crm_warn("Ignoring shutdown request from unprivileged client %s",
122 pcmk__client_name(request->ipc_client));
123 crm_xml_add_int(shutdown, PCMK__XA_OP_STATUS, CRM_EX_INSUFFICIENT_PRIV);
124 }
125
126 reply = pcmk__new_reply(msg, shutdown);
127 pcmk__xml_free(shutdown);
128
129 if (reply == NULL) {
130 pcmk__format_result(&request->result, CRM_EX_ERROR, PCMK_EXEC_ERROR,
131 "Failed building shutdown reply for client %s",
132 pcmk__client_name(request->ipc_client));
133 } else {
134 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
135 }
136
137 if (allowed) {
138 pcmk_shutdown(15);
139 }
140
141 return reply;
142 }
143
144 static xmlNode *
145 handle_unknown_request(pcmk__request_t *request)
146 {
147 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
148 PCMK__XE_ACK, NULL, CRM_EX_INVALID_PARAM);
149
150 pcmk__format_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID,
151 "Unknown IPC request type '%s' (bug?)",
152 pcmk__client_name(request->ipc_client));
153 return NULL;
154 }
155
156 static void
157 pcmkd_register_handlers(void)
158 {
159 pcmk__server_command_t handlers[] = {
160 { CRM_OP_RM_NODE_CACHE, handle_node_cache_request },
161 { CRM_OP_PING, handle_ping_request },
162 { CRM_OP_QUIT, handle_shutdown_request },
163 { NULL, handle_unknown_request },
164 };
165
166 pcmkd_handlers = pcmk__register_handlers(handlers);
167 }
168
169 static int32_t
170 pcmk_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
171 {
172 crm_trace("Connection %p", c);
173 if (pcmk__new_client(c, uid, gid) == NULL) {
174 return -ENOMEM;
175 }
176 return 0;
177 }
178
179
180 static int32_t
181 pcmk_ipc_closed(qb_ipcs_connection_t * c)
182 {
183 pcmk__client_t *client = pcmk__find_client(c);
184
185 if (client == NULL) {
186 return 0;
187 }
188 crm_trace("Connection %p", c);
189 if (shutdown_complete_state_reported_to == client->pid) {
190 shutdown_complete_state_reported_client_closed = TRUE;
191 if (shutdown_trigger) {
192 mainloop_set_trigger(shutdown_trigger);
193 }
194 }
195 pcmk__free_client(client);
196 return 0;
197 }
198
199 static void
200 pcmk_ipc_destroy(qb_ipcs_connection_t * c)
201 {
202 crm_trace("Connection %p", c);
203 pcmk_ipc_closed(c);
204 }
205
206
207 static int32_t
208 pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
209 {
210 int rc = pcmk_rc_ok;
211 uint32_t id = 0;
212 uint32_t flags = 0;
213 xmlNode *msg = NULL;
214 pcmk__client_t *c = pcmk__find_client(qbc);
215
216 CRM_CHECK(c != NULL, return 0);
217
218 if (pcmkd_handlers == NULL) {
219 pcmkd_register_handlers();
220 }
221
222 rc = pcmk__ipc_msg_append(&c->buffer, data);
223
224 if (rc == pcmk_rc_ipc_more) {
225
226 return 0;
227
228 } else if (rc == pcmk_rc_ok) {
229
230
231
232 msg = pcmk__client_data2xml(c, &id, &flags);
233 g_byte_array_free(c->buffer, TRUE);
234 c->buffer = NULL;
235
236 } else {
237
238
239
240 crm_err("Error when reading IPC message: %s", pcmk_rc_str(rc));
241
242 if (c->buffer != NULL) {
243 g_byte_array_free(c->buffer, TRUE);
244 c->buffer = NULL;
245 }
246
247 return 0;
248 }
249
250 if (msg == NULL) {
251 pcmk__ipc_send_ack(c, id, flags, PCMK__XE_ACK, NULL, CRM_EX_PROTOCOL);
252 return 0;
253
254 } else {
255 char *log_msg = NULL;
256 const char *reason = NULL;
257 xmlNode *reply = NULL;
258
259 pcmk__request_t request = {
260 .ipc_client = c,
261 .ipc_id = id,
262 .ipc_flags = flags,
263 .peer = NULL,
264 .xml = msg,
265 .call_options = 0,
266 .result = PCMK__UNKNOWN_RESULT,
267 };
268
269 request.op = crm_element_value_copy(request.xml, PCMK__XA_CRM_TASK);
270 CRM_CHECK(request.op != NULL, return 0);
271
272 reply = pcmk__process_request(&request, pcmkd_handlers);
273
274 if (reply != NULL) {
275 pcmk__ipc_send_xml(c, id, reply, crm_ipc_server_event);
276 pcmk__xml_free(reply);
277 }
278
279 reason = request.result.exit_reason;
280
281 log_msg = crm_strdup_printf("Processed %s request from %s %s: %s%s%s%s",
282 request.op, pcmk__request_origin_type(&request),
283 pcmk__request_origin(&request),
284 pcmk_exec_status_str(request.result.execution_status),
285 (reason == NULL)? "" : " (",
286 (reason == NULL)? "" : reason,
287 (reason == NULL)? "" : ")");
288
289 if (!pcmk__result_ok(&request.result)) {
290 crm_warn("%s", log_msg);
291 } else {
292 crm_debug("%s", log_msg);
293 }
294
295 free(log_msg);
296 pcmk__reset_request(&request);
297 }
298
299 pcmk__xml_free(msg);
300 return 0;
301 }
302
303 struct qb_ipcs_service_handlers pacemakerd_ipc_callbacks = {
304 .connection_accept = pcmk_ipc_accept,
305 .connection_created = NULL,
306 .msg_process = pcmk_ipc_dispatch,
307 .connection_closed = pcmk_ipc_closed,
308 .connection_destroyed = pcmk_ipc_destroy
309 };