ctdb-common: Fix a warning in the pcap code
[metze/samba-autobuild/.git] / ctdb / client / client_event.c
1 /*
2    Eventd client api
3
4    Copyright (C) Amitay Isaacs  2016
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21 #include "system/network.h"
22
23 #include <talloc.h>
24 #include <tevent.h>
25
26 #include "lib/util/debug.h"
27 #include "lib/util/tevent_unix.h"
28
29 #include "common/logging.h"
30 #include "common/sock_client.h"
31
32 #include "protocol/protocol_api.h"
33
34 #include "client/client_event.h"
35
36 struct ctdb_event_context {
37         struct sock_client_context *sockc;
38 };
39
40 static int ctdb_event_msg_request_push(void *request_data, uint32_t reqid,
41                                        TALLOC_CTX *mem_ctx,
42                                        uint8_t **buf, size_t *buflen,
43                                        void *private_data)
44 {
45         struct ctdb_event_request *request =
46                 (struct ctdb_event_request *)request_data;
47         int ret;
48
49         sock_packet_header_set_reqid(&request->header, reqid);
50
51         *buflen = ctdb_event_request_len(request);
52         *buf = talloc_size(mem_ctx, *buflen);
53         if (*buf == NULL) {
54                 return ENOMEM;
55         }
56
57         ret = ctdb_event_request_push(request, *buf, buflen);
58         if (ret != 0) {
59                 return ret;
60         }
61
62         return 0;
63 }
64
65 static int ctdb_event_msg_reply_pull(uint8_t *buf, size_t buflen,
66                                      TALLOC_CTX *mem_ctx, void **reply_data,
67                                      void *private_data)
68 {
69         struct ctdb_event_reply *reply;
70         int ret;
71
72         reply = talloc_zero(mem_ctx, struct ctdb_event_reply);
73         if (reply == NULL) {
74                 return ENOMEM;
75         }
76
77         ret = ctdb_event_reply_pull(buf, buflen, reply, reply);
78         if (ret != 0) {
79                 talloc_free(reply);
80                 return ret;
81         }
82
83         *reply_data = reply;
84         return 0;
85 }
86
87 static int ctdb_event_msg_reply_reqid(uint8_t *buf, size_t buflen,
88                                       uint32_t *reqid, void *private_data)
89 {
90         struct sock_packet_header header;
91         size_t np;
92         int ret;
93
94         ret = sock_packet_header_pull(buf, buflen, &header, &np);
95         if (ret != 0) {
96                 return ret;
97         }
98
99         *reqid = header.reqid;
100         return 0;
101 }
102
103 struct sock_client_proto_funcs event_proto_funcs = {
104         .request_push = ctdb_event_msg_request_push,
105         .reply_pull = ctdb_event_msg_reply_pull,
106         .reply_reqid = ctdb_event_msg_reply_reqid,
107 };
108
109
110 int ctdb_event_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
111                     const char *sockpath, struct ctdb_event_context **out)
112 {
113         struct ctdb_event_context *eclient;
114         int ret;
115
116         eclient = talloc_zero(mem_ctx, struct ctdb_event_context);
117         if (eclient == NULL) {
118                 DEBUG(DEBUG_ERR, (__location__ " memory allocation error\n"));
119                 return ENOMEM;
120         }
121
122         ret = sock_client_setup(eclient, ev, sockpath,
123                                 &event_proto_funcs, eclient,
124                                 &eclient->sockc);
125         if (ret != 0) {
126                 talloc_free(eclient);
127                 return ret;
128         }
129
130         *out = eclient;
131         return 0;
132 }
133
134 void ctdb_event_set_disconnect_callback(struct ctdb_event_context *eclient,
135                                         ctdb_client_callback_func_t callback,
136                                         void *private_data)
137 {
138         sock_client_set_disconnect_callback(eclient->sockc,
139                                             callback, private_data);
140 }
141
142 /*
143  * Handle eventd_request and eventd_reply
144  */
145
146 struct tevent_req *ctdb_event_msg_send(TALLOC_CTX *mem_ctx,
147                                        struct tevent_context *ev,
148                                        struct ctdb_event_context *eclient,
149                                        struct ctdb_event_request *request)
150 {
151         struct tevent_req *req;
152
153         req = sock_client_msg_send(mem_ctx, ev, eclient->sockc,
154                                    tevent_timeval_zero(), request);
155         return req;
156 }
157
158 bool ctdb_event_msg_recv(struct tevent_req *req, int *perr,
159                          TALLOC_CTX *mem_ctx,
160                          struct ctdb_event_reply **reply)
161 {
162         void *reply_data;
163         bool status;
164
165         status = sock_client_msg_recv(req, perr, mem_ctx, &reply_data);
166
167         if (status && reply != NULL) {
168                 *reply = talloc_get_type_abort(
169                                 reply_data, struct ctdb_event_reply);
170         }
171
172         return status;
173 }
174
175 /*
176  * Run an event
177  */
178
179 struct tevent_req *ctdb_event_run_send(TALLOC_CTX *mem_ctx,
180                                        struct tevent_context *ev,
181                                        struct ctdb_event_context *eclient,
182                                        enum ctdb_event event,
183                                        uint32_t timeout, const char *arg_str)
184 {
185         struct ctdb_event_request request;
186         struct ctdb_event_request_run rdata;
187
188         rdata.event = event;
189         rdata.timeout = timeout;
190         rdata.arg_str = arg_str;
191
192         request.rdata.command = CTDB_EVENT_COMMAND_RUN;
193         request.rdata.data.run = &rdata;
194
195         return ctdb_event_msg_send(mem_ctx, ev, eclient, &request);
196 }
197
198 bool ctdb_event_run_recv(struct tevent_req *req, int *perr, int *result)
199 {
200         struct ctdb_event_reply *reply;
201         int ret;
202         bool status;
203
204         status = ctdb_event_msg_recv(req, &ret, req, &reply);
205         if (! status) {
206                 if (perr != NULL) {
207                         *perr = ret;
208                 }
209                 return false;
210         }
211
212         if (reply->rdata.command != CTDB_EVENT_COMMAND_RUN) {
213                 if (perr != NULL) {
214                         *perr = EPROTO;
215                 }
216                 talloc_free(reply);
217                 return false;
218         }
219
220         if (result != NULL) {
221                 *result = reply->rdata.result;
222         }
223
224         talloc_free(reply);
225         return true;
226 }
227
228 /*
229  * Get event status
230  */
231
232 struct tevent_req *ctdb_event_status_send(TALLOC_CTX *mem_ctx,
233                                           struct tevent_context *ev,
234                                           struct ctdb_event_context *eclient,
235                                           enum ctdb_event event,
236                                           enum ctdb_event_status_state state)
237 {
238         struct ctdb_event_request request;
239         struct ctdb_event_request_status rdata;
240
241         rdata.event = event;
242         rdata.state = state;
243
244         request.rdata.command = CTDB_EVENT_COMMAND_STATUS;
245         request.rdata.data.status = &rdata;
246
247         return ctdb_event_msg_send(mem_ctx, ev, eclient, &request);
248 }
249
250 bool ctdb_event_status_recv(struct tevent_req *req, int *perr,
251                             int32_t *result, int *event_status,
252                             TALLOC_CTX *mem_ctx,
253                             struct ctdb_script_list **script_list)
254 {
255         struct ctdb_event_reply *reply;
256         int ret;
257         bool status;
258
259         status = ctdb_event_msg_recv(req, &ret, req, &reply);
260         if (! status) {
261                 if (perr != NULL) {
262                         *perr = ret;
263                 }
264                 return false;
265         }
266
267         if (reply->rdata.command != CTDB_EVENT_COMMAND_STATUS) {
268                 if (perr != NULL) {
269                         *perr = EPROTO;
270                 }
271                 talloc_free(reply);
272                 return false;
273         }
274
275         if (result != NULL) {
276                 *result = reply->rdata.result;
277         }
278         if (event_status != NULL) {
279                 *event_status = reply->rdata.data.status->status;
280         }
281         if (script_list != NULL) {
282                 *script_list = talloc_steal(mem_ctx,
283                                         reply->rdata.data.status->script_list);
284         }
285
286         talloc_free(reply);
287         return true;
288 }
289
290 /*
291  * Get script list
292  */
293
294 struct tevent_req *ctdb_event_script_list_send(
295                                         TALLOC_CTX *mem_ctx,
296                                         struct tevent_context *ev,
297                                         struct ctdb_event_context *eclient)
298 {
299         struct ctdb_event_request request;
300
301         request.rdata.command = CTDB_EVENT_COMMAND_SCRIPT_LIST;
302
303         return ctdb_event_msg_send(mem_ctx, ev, eclient, &request);
304 }
305
306 bool ctdb_event_script_list_recv(struct tevent_req *req, int *perr,
307                                  int32_t *result, TALLOC_CTX *mem_ctx,
308                                  struct ctdb_script_list **script_list)
309 {
310         struct ctdb_event_reply *reply;
311         int ret;
312         bool status;
313
314         status = ctdb_event_msg_recv(req, &ret, req, &reply);
315         if (! status) {
316                 if (perr != NULL) {
317                         *perr = ret;
318                 }
319                 return false;
320         }
321
322         if (reply->rdata.command != CTDB_EVENT_COMMAND_SCRIPT_LIST) {
323                 if (perr != NULL) {
324                         *perr = EPROTO;
325                 }
326                 talloc_free(reply);
327                 return false;
328         }
329
330         if (result != NULL) {
331                 *result = reply->rdata.result;
332         }
333         if (script_list != NULL) {
334                 *script_list = talloc_steal(mem_ctx,
335                                 reply->rdata.data.script_list->script_list);
336         }
337
338         talloc_free(reply);
339         return true;
340 }
341
342 /*
343  * Enable a script
344  */
345
346 struct tevent_req *ctdb_event_script_enable_send(
347                                         TALLOC_CTX *mem_ctx,
348                                         struct tevent_context *ev,
349                                         struct ctdb_event_context *eclient,
350                                         const char *script_name)
351 {
352         struct ctdb_event_request request;
353         struct ctdb_event_request_script_enable rdata;
354
355         rdata.script_name = script_name;
356
357         request.rdata.command = CTDB_EVENT_COMMAND_SCRIPT_ENABLE;
358         request.rdata.data.script_enable = &rdata;
359
360         return ctdb_event_msg_send(mem_ctx, ev, eclient, &request);
361 }
362
363 bool ctdb_event_script_enable_recv(struct tevent_req *req, int *perr,
364                                    int *result)
365 {
366         struct ctdb_event_reply *reply;
367         int ret;
368         bool status;
369
370         status = ctdb_event_msg_recv(req, &ret, req, &reply);
371         if (! status) {
372                 if (perr != NULL) {
373                         *perr = ret;
374                 }
375                 return false;
376         }
377
378         if (reply->rdata.command != CTDB_EVENT_COMMAND_SCRIPT_ENABLE) {
379                 if (perr != NULL) {
380                         *perr = EPROTO;
381                 }
382                 talloc_free(reply);
383                 return false;
384         }
385
386         if (result != NULL) {
387                 *result = reply->rdata.result;
388         }
389
390         talloc_free(reply);
391         return true;
392 }
393
394 /*
395  * Disable a script
396  */
397
398 struct tevent_req *ctdb_event_script_disable_send(
399                                         TALLOC_CTX *mem_ctx,
400                                         struct tevent_context *ev,
401                                         struct ctdb_event_context *eclient,
402                                         const char *script_name)
403 {
404         struct ctdb_event_request request;
405         struct ctdb_event_request_script_disable rdata;
406
407         rdata.script_name = script_name;
408
409         request.rdata.command = CTDB_EVENT_COMMAND_SCRIPT_DISABLE;
410         request.rdata.data.script_disable = &rdata;
411
412         return ctdb_event_msg_send(mem_ctx, ev, eclient, &request);
413 }
414
415 bool ctdb_event_script_disable_recv(struct tevent_req *req, int *perr,
416                                     int *result)
417 {
418         struct ctdb_event_reply *reply;
419         int ret;
420         bool status;
421
422         status = ctdb_event_msg_recv(req, &ret, req, &reply);
423         if (! status) {
424                 if (perr != NULL) {
425                         *perr = ret;
426                 }
427                 return false;
428         }
429
430         if (reply->rdata.command != CTDB_EVENT_COMMAND_SCRIPT_DISABLE) {
431                 if (perr != NULL) {
432                         *perr = EPROTO;
433                 }
434                 talloc_free(reply);
435                 return false;
436         }
437
438         if (result != NULL) {
439                 *result = reply->rdata.result;
440         }
441
442         talloc_free(reply);
443         return true;
444 }