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 = create_reply(msg, ping);
64
65 free_xml(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 = create_reply(msg, shutdown);
127 free_xml(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 uint32_t id = 0;
211 uint32_t flags = 0;
212 xmlNode *msg = NULL;
213 pcmk__client_t *c = pcmk__find_client(qbc);
214
215 CRM_CHECK(c != NULL, return 0);
216
217 if (pcmkd_handlers == NULL) {
218 pcmkd_register_handlers();
219 }
220
221 msg = pcmk__client_data2xml(c, data, &id, &flags);
222 if (msg == NULL) {
223 pcmk__ipc_send_ack(c, id, flags, PCMK__XE_ACK, NULL, CRM_EX_PROTOCOL);
224 return 0;
225
226 } else {
227 char *log_msg = NULL;
228 const char *reason = NULL;
229 xmlNode *reply = NULL;
230
231 pcmk__request_t request = {
232 .ipc_client = c,
233 .ipc_id = id,
234 .ipc_flags = flags,
235 .peer = NULL,
236 .xml = msg,
237 .call_options = 0,
238 .result = PCMK__UNKNOWN_RESULT,
239 };
240
241 request.op = crm_element_value_copy(request.xml, PCMK__XA_CRM_TASK);
242 CRM_CHECK(request.op != NULL, return 0);
243
244 reply = pcmk__process_request(&request, pcmkd_handlers);
245
246 if (reply != NULL) {
247 pcmk__ipc_send_xml(c, id, reply, crm_ipc_server_event);
248 free_xml(reply);
249 }
250
251 reason = request.result.exit_reason;
252
253 log_msg = crm_strdup_printf("Processed %s request from %s %s: %s%s%s%s",
254 request.op, pcmk__request_origin_type(&request),
255 pcmk__request_origin(&request),
256 pcmk_exec_status_str(request.result.execution_status),
257 (reason == NULL)? "" : " (",
258 (reason == NULL)? "" : reason,
259 (reason == NULL)? "" : ")");
260
261 if (!pcmk__result_ok(&request.result)) {
262 crm_warn("%s", log_msg);
263 } else {
264 crm_debug("%s", log_msg);
265 }
266
267 free(log_msg);
268 pcmk__reset_request(&request);
269 }
270
271 free_xml(msg);
272 return 0;
273 }
274
275 struct qb_ipcs_service_handlers pacemakerd_ipc_callbacks = {
276 .connection_accept = pcmk_ipc_accept,
277 .connection_created = NULL,
278 .msg_process = pcmk_ipc_dispatch,
279 .connection_closed = pcmk_ipc_closed,
280 .connection_destroyed = pcmk_ipc_destroy
281 };