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/msg_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 "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, F_CRM_SYS_FROM);
46
47
48 crm_trace("Pinged from " F_CRM_SYS_FROM "='%s' " F_CRM_ORIGIN "='%s'",
49 pcmk__s(from, ""),
50 pcmk__s(crm_element_value(msg, F_CRM_ORIGIN), ""));
51
52 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
53 "ack", NULL, CRM_EX_INDETERMINATE);
54
55 ping = create_xml_node(NULL, XML_CRM_TAG_PING);
56 value = crm_element_value(msg, F_CRM_SYS_TO);
57 crm_xml_add(ping, XML_PING_ATTR_SYSFROM, value);
58 crm_xml_add(ping, XML_PING_ATTR_PACEMAKERDSTATE, pacemakerd_state);
59 crm_xml_add_ll(ping, XML_ATTR_TSTAMP,
60 (long long) subdaemon_check_progress);
61 crm_xml_add(ping, XML_PING_ATTR_STATUS, "ok");
62 reply = create_reply(msg, ping);
63
64 free_xml(ping);
65
66 if (reply == NULL) {
67 pcmk__format_result(&request->result, CRM_EX_ERROR, PCMK_EXEC_ERROR,
68 "Failed building ping reply for client %s",
69 pcmk__client_name(request->ipc_client));
70 } else {
71 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
72 }
73
74
75 if (from && strstr(from, "sbd")) {
76 if (pcmk__str_eq(pacemakerd_state, XML_PING_ATTR_PACEMAKERDSTATE_SHUTDOWNCOMPLETE, pcmk__str_none)) {
77 if (pcmk__get_sbd_sync_resource_startup()) {
78 crm_notice("Shutdown-complete-state passed to SBD.");
79 }
80
81 shutdown_complete_state_reported_to = request->ipc_client->pid;
82
83 } else if (pcmk__str_eq(pacemakerd_state, XML_PING_ATTR_PACEMAKERDSTATE_WAITPING, pcmk__str_none)) {
84 crm_notice("Received startup-trigger from SBD.");
85 pacemakerd_state = XML_PING_ATTR_PACEMAKERDSTATE_STARTINGDAEMONS;
86 mainloop_set_trigger(startup_trigger);
87 }
88 }
89
90 return reply;
91 }
92
93 static xmlNode *
94 handle_shutdown_request(pcmk__request_t *request)
95 {
96 xmlNode *msg = request->xml;
97
98 xmlNode *shutdown = NULL;
99 xmlNode *reply = NULL;
100
101
102
103
104
105 bool allowed = pcmk_is_set(request->ipc_client->flags, pcmk__client_privileged);
106
107 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
108 "ack", NULL, CRM_EX_INDETERMINATE);
109
110 shutdown = create_xml_node(NULL, XML_CIB_ATTR_SHUTDOWN);
111
112 if (allowed) {
113 crm_notice("Shutting down in response to IPC request %s from %s",
114 crm_element_value(msg, F_CRM_REFERENCE),
115 crm_element_value(msg, F_CRM_ORIGIN));
116 crm_xml_add_int(shutdown, XML_LRM_ATTR_OPSTATUS, CRM_EX_OK);
117 } else {
118 crm_warn("Ignoring shutdown request from unprivileged client %s",
119 pcmk__client_name(request->ipc_client));
120 crm_xml_add_int(shutdown, XML_LRM_ATTR_OPSTATUS, CRM_EX_INSUFFICIENT_PRIV);
121 }
122
123 reply = create_reply(msg, shutdown);
124 free_xml(shutdown);
125
126 if (reply == NULL) {
127 pcmk__format_result(&request->result, CRM_EX_ERROR, PCMK_EXEC_ERROR,
128 "Failed building shutdown reply for client %s",
129 pcmk__client_name(request->ipc_client));
130 } else {
131 pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);
132 }
133
134 if (allowed) {
135 pcmk_shutdown(15);
136 }
137
138 return reply;
139 }
140
141 static xmlNode *
142 handle_unknown_request(pcmk__request_t *request)
143 {
144 pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags,
145 "ack", NULL, CRM_EX_INVALID_PARAM);
146
147 pcmk__format_result(&request->result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID,
148 "Unknown IPC request type '%s' (bug?)",
149 pcmk__client_name(request->ipc_client));
150 return NULL;
151 }
152
153 static void
154 pcmkd_register_handlers(void)
155 {
156 pcmk__server_command_t handlers[] = {
157 { CRM_OP_RM_NODE_CACHE, handle_node_cache_request },
158 { CRM_OP_PING, handle_ping_request },
159 { CRM_OP_QUIT, handle_shutdown_request },
160 { NULL, handle_unknown_request },
161 };
162
163 pcmkd_handlers = pcmk__register_handlers(handlers);
164 }
165
166 static int32_t
167 pcmk_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
168 {
169 crm_trace("Connection %p", c);
170 if (pcmk__new_client(c, uid, gid) == NULL) {
171 return -EIO;
172 }
173 return 0;
174 }
175
176
177 static int32_t
178 pcmk_ipc_closed(qb_ipcs_connection_t * c)
179 {
180 pcmk__client_t *client = pcmk__find_client(c);
181
182 if (client == NULL) {
183 return 0;
184 }
185 crm_trace("Connection %p", c);
186 if (shutdown_complete_state_reported_to == client->pid) {
187 shutdown_complete_state_reported_client_closed = TRUE;
188 if (shutdown_trigger) {
189 mainloop_set_trigger(shutdown_trigger);
190 }
191 }
192 pcmk__free_client(client);
193 return 0;
194 }
195
196 static void
197 pcmk_ipc_destroy(qb_ipcs_connection_t * c)
198 {
199 crm_trace("Connection %p", c);
200 pcmk_ipc_closed(c);
201 }
202
203
204 static int32_t
205 pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
206 {
207 uint32_t id = 0;
208 uint32_t flags = 0;
209 xmlNode *msg = NULL;
210 pcmk__client_t *c = pcmk__find_client(qbc);
211
212 CRM_CHECK(c != NULL, return 0);
213
214 if (pcmkd_handlers == NULL) {
215 pcmkd_register_handlers();
216 }
217
218 msg = pcmk__client_data2xml(c, data, &id, &flags);
219 if (msg == NULL) {
220 pcmk__ipc_send_ack(c, id, flags, "ack", NULL, CRM_EX_PROTOCOL);
221 return 0;
222
223 } else {
224 char *log_msg = NULL;
225 const char *reason = NULL;
226 xmlNode *reply = NULL;
227
228 pcmk__request_t request = {
229 .ipc_client = c,
230 .ipc_id = id,
231 .ipc_flags = flags,
232 .peer = NULL,
233 .xml = msg,
234 .call_options = 0,
235 .result = PCMK__UNKNOWN_RESULT,
236 };
237
238 request.op = crm_element_value_copy(request.xml, F_CRM_TASK);
239 CRM_CHECK(request.op != NULL, return 0);
240
241 reply = pcmk__process_request(&request, pcmkd_handlers);
242
243 if (reply != NULL) {
244 pcmk__ipc_send_xml(c, id, reply, crm_ipc_server_event);
245 free_xml(reply);
246 }
247
248 reason = request.result.exit_reason;
249
250 log_msg = crm_strdup_printf("Processed %s request from %s %s: %s%s%s%s",
251 request.op, pcmk__request_origin_type(&request),
252 pcmk__request_origin(&request),
253 pcmk_exec_status_str(request.result.execution_status),
254 (reason == NULL)? "" : " (",
255 (reason == NULL)? "" : reason,
256 (reason == NULL)? "" : ")");
257
258 if (!pcmk__result_ok(&request.result)) {
259 crm_warn("%s", log_msg);
260 } else {
261 crm_debug("%s", log_msg);
262 }
263
264 free(log_msg);
265 pcmk__reset_request(&request);
266 }
267
268 free_xml(msg);
269 return 0;
270 }
271
272 struct qb_ipcs_service_handlers mcp_ipc_callbacks = {
273 .connection_accept = pcmk_ipc_accept,
274 .connection_created = NULL,
275 .msg_process = pcmk_ipc_dispatch,
276 .connection_closed = pcmk_ipc_closed,
277 .connection_destroyed = pcmk_ipc_destroy
278 };