ctdb-event: Add event daemon protocol
[vlendec/samba-autobuild/.git] / ctdb / event / event_protocol.c
1 /*
2    CTDB event daemon protocol
3
4    Copyright (C) Amitay Isaacs  2018
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
22 #include <talloc.h>
23
24 #include "protocol/protocol_basic.h"
25
26 #include "event_protocol.h"
27 #include "event_protocol_api.h"
28
29 static size_t ctdb_event_script_action_len(enum ctdb_event_script_action in)
30 {
31         uint32_t u32 = in;
32
33         return ctdb_uint32_len(&u32);
34 }
35
36 static void ctdb_event_script_action_push(enum ctdb_event_script_action in,
37                                           uint8_t *buf,
38                                           size_t *npush)
39 {
40         uint32_t u32 = in;
41
42         ctdb_uint32_push(&u32, buf, npush);
43 }
44
45 static int ctdb_event_script_action_pull(uint8_t *buf,
46                                          size_t buflen,
47                                          enum ctdb_event_script_action *out,
48                                          size_t *npull)
49 {
50         enum ctdb_event_script_action value;
51         uint32_t u32;
52         size_t np;
53         int ret;
54
55         ret = ctdb_uint32_pull(buf, buflen, &u32, &np);
56         if (ret != 0) {
57                 return ret;
58         }
59
60         switch (u32) {
61         case 0:
62                 value = CTDB_EVENT_SCRIPT_DISABLE;
63                 break;
64
65         case 1:
66                 value = CTDB_EVENT_SCRIPT_ENABLE;
67                 break;
68
69         default:
70                 return EINVAL;
71         }
72
73         *out = value;
74         *npull = np;
75
76         return 0;
77 }
78
79 static size_t ctdb_event_command_len(enum ctdb_event_command in)
80 {
81         uint32_t u32 = in;
82
83         return ctdb_uint32_len(&u32);
84 }
85
86 static void ctdb_event_command_push(enum ctdb_event_command in,
87                                     uint8_t *buf,
88                                     size_t *npush)
89 {
90         uint32_t u32 = in;
91
92         ctdb_uint32_push(&u32, buf, npush);
93 }
94
95 static int ctdb_event_command_pull(uint8_t *buf,
96                                    size_t buflen,
97                                    enum ctdb_event_command *out,
98                                    size_t *npull)
99 {
100         enum ctdb_event_command value;
101         uint32_t u32;
102         size_t np;
103         int ret;
104
105         ret = ctdb_uint32_pull(buf, buflen, &u32, &np);
106         if (ret != 0) {
107                 return ret;
108         }
109
110         switch (u32) {
111         case 1:
112                 value = CTDB_EVENT_CMD_RUN;
113                 break;
114
115         case 2:
116                 value = CTDB_EVENT_CMD_STATUS;
117                 break;
118
119         case 3:
120                 value = CTDB_EVENT_CMD_SCRIPT;
121                 break;
122
123         default:
124                 return EINVAL;
125         }
126
127         *out = value;
128         *npull = np;
129
130         return 0;
131 }
132
133 static size_t ctdb_event_script_len(struct ctdb_event_script *in)
134 {
135         return ctdb_stringn_len(&in->name) +
136                 ctdb_timeval_len(&in->begin) +
137                 ctdb_timeval_len(&in->end) +
138                 ctdb_int32_len(&in->result) +
139                 ctdb_stringn_len(&in->output);
140 }
141
142 static void ctdb_event_script_push(struct ctdb_event_script *in,
143                                    uint8_t *buf,
144                                    size_t *npush)
145 {
146         size_t offset = 0, np;
147
148         ctdb_stringn_push(&in->name, buf+offset, &np);
149         offset += np;
150
151         ctdb_timeval_push(&in->begin, buf+offset, &np);
152         offset += np;
153
154         ctdb_timeval_push(&in->end, buf+offset, &np);
155         offset += np;
156
157         ctdb_int32_push(&in->result, buf+offset, &np);
158         offset += np;
159
160         ctdb_stringn_push(&in->output, buf+offset, &np);
161         offset += np;
162
163         *npush = offset;
164 }
165
166 static int ctdb_event_script_pull_elems(uint8_t *buf,
167                                         size_t buflen,
168                                         TALLOC_CTX *mem_ctx,
169                                         struct ctdb_event_script *value,
170                                         size_t *npull)
171 {
172         size_t offset = 0, np;
173         int ret;
174
175         ret = ctdb_stringn_pull(buf+offset,
176                                 buflen-offset,
177                                 mem_ctx,
178                                 &value->name,
179                                 &np);
180         if (ret != 0) {
181                 return ret;
182         }
183         offset += np;
184
185         ret = ctdb_timeval_pull(buf+offset,
186                                 buflen-offset,
187                                 &value->begin,
188                                 &np);
189         if (ret != 0) {
190                 return ret;
191         }
192         offset += np;
193
194         ret = ctdb_timeval_pull(buf+offset,
195                                 buflen-offset,
196                                 &value->end,
197                                 &np);
198         if (ret != 0) {
199                 return ret;
200         }
201         offset += np;
202
203         ret = ctdb_int32_pull(buf+offset,
204                               buflen-offset,
205                               &value->result,
206                               &np);
207         if (ret != 0) {
208                 return ret;
209         }
210         offset += np;
211
212         ret = ctdb_stringn_pull(buf+offset,
213                                 buflen-offset,
214                                 mem_ctx,
215                                 &value->output,
216                                 &np);
217         if (ret != 0) {
218                 return ret;
219         }
220         offset += np;
221
222         *npull = offset;
223
224         return 0;
225 }
226
227 #ifdef EVENT_PROTOCOL_TEST
228 static int ctdb_event_script_pull(uint8_t *buf,
229                                   size_t buflen,
230                                   TALLOC_CTX *mem_ctx,
231                                   struct ctdb_event_script **out,
232                                   size_t *npull)
233 {
234         struct ctdb_event_script *value;
235         int ret;
236
237         value = talloc(mem_ctx, struct ctdb_event_script);
238         if (value == NULL) {
239                 return ENOMEM;
240         }
241
242         ret = ctdb_event_script_pull_elems(buf, buflen, value, value, npull);
243         if (ret != 0) {
244                 talloc_free(value);
245                 return ret;
246         }
247
248         *out = value;
249
250         return 0;
251 }
252 #endif
253
254 static size_t ctdb_event_script_list_len(struct ctdb_event_script_list *in)
255 {
256         size_t len;
257         int i;
258
259         len = ctdb_int32_len(&in->num_scripts);
260
261         for (i=0; i<in->num_scripts; i++) {
262                 len += ctdb_event_script_len(&in->script[i]);
263         }
264
265         return len;
266 }
267
268 static void ctdb_event_script_list_push(struct ctdb_event_script_list *in,
269                                         uint8_t *buf,
270                                         size_t *npush)
271 {
272         size_t offset = 0, np;
273         int i;
274
275         ctdb_int32_push(&in->num_scripts, buf+offset, &np);
276         offset += np;
277
278         for (i=0; i<in->num_scripts; i++) {
279                 ctdb_event_script_push(&in->script[i], buf+offset, &np);
280                 offset += np;
281         }
282
283         *npush = offset;
284 }
285
286 static int ctdb_event_script_list_pull(uint8_t *buf,
287                                        size_t buflen,
288                                        TALLOC_CTX *mem_ctx,
289                                        struct ctdb_event_script_list **out,
290                                        size_t *npull)
291 {
292         struct ctdb_event_script_list *value = NULL;
293         size_t offset = 0, np;
294         int num_scripts;
295         int ret, i;
296
297         ret = ctdb_int32_pull(buf+offset, buflen-offset, &num_scripts, &np);
298         if (ret != 0) {
299                 return ret;
300         }
301         offset += np;
302
303         if (num_scripts < 0) {
304                 return EINVAL;
305         }
306
307         value = talloc_zero(mem_ctx, struct ctdb_event_script_list);
308         if (value == NULL) {
309                 return ENOMEM;
310         }
311
312         value->num_scripts = num_scripts;
313         if (num_scripts == 0) {
314                 goto done;
315         }
316
317         value->script = talloc_array(value, struct ctdb_event_script,
318                                      num_scripts);
319         if (value->script == NULL) {
320                 goto fail;
321         }
322
323         for (i=0; i<num_scripts; i++) {
324                 ret = ctdb_event_script_pull_elems(buf+offset,
325                                                    buflen-offset,
326                                                    value,
327                                                    &value->script[i],
328                                                    &np);
329                 if (ret != 0) {
330                         goto fail;
331                 }
332                 offset += np;
333         }
334
335 done:
336         *out = value;
337         *npull = offset;
338
339         return 0;
340
341 fail:
342         talloc_free(value);
343         return ret;
344 }
345
346 static size_t ctdb_event_request_run_len(struct ctdb_event_request_run *in)
347 {
348         return ctdb_stringn_len(&in->component) +
349                 ctdb_stringn_len(&in->event) +
350                 ctdb_stringn_len(&in->args) +
351                 ctdb_uint32_len(&in->timeout) +
352                 ctdb_uint32_len(&in->flags);
353 }
354
355 static void ctdb_event_request_run_push(struct ctdb_event_request_run *in,
356                                         uint8_t *buf,
357                                         size_t *npush)
358 {
359         size_t offset = 0, np;
360
361         ctdb_stringn_push(&in->component, buf+offset, &np);
362         offset += np;
363
364         ctdb_stringn_push(&in->event, buf+offset, &np);
365         offset += np;
366
367         ctdb_stringn_push(&in->args, buf+offset, &np);
368         offset += np;
369
370         ctdb_uint32_push(&in->timeout, buf+offset, &np);
371         offset += np;
372
373         ctdb_uint32_push(&in->flags, buf+offset, &np);
374         offset += np;
375
376         *npush = offset;
377 }
378
379 static int ctdb_event_request_run_pull(uint8_t *buf,
380                                        size_t buflen,
381                                        TALLOC_CTX *mem_ctx,
382                                        struct ctdb_event_request_run **out,
383                                        size_t *npull)
384 {
385         struct ctdb_event_request_run *value;
386         size_t offset = 0, np;
387         int ret;
388
389         value = talloc(mem_ctx, struct ctdb_event_request_run);
390         if (value == NULL) {
391                 return ENOMEM;
392         }
393
394         ret = ctdb_stringn_pull(buf+offset,
395                                 buflen-offset,
396                                 value,
397                                 &value->component,
398                                 &np);
399         if (ret != 0) {
400                 goto fail;
401         }
402         offset += np;
403
404         ret = ctdb_stringn_pull(buf+offset,
405                                 buflen-offset,
406                                 value,
407                                 &value->event,
408                                 &np);
409         if (ret != 0) {
410                 goto fail;
411         }
412         offset += np;
413
414         ret = ctdb_stringn_pull(buf+offset,
415                                 buflen-offset,
416                                 value,
417                                 &value->args,
418                                 &np);
419         if (ret != 0) {
420                 goto fail;
421         }
422         offset += np;
423
424         ret = ctdb_uint32_pull(buf+offset,
425                                buflen-offset,
426                                &value->timeout,
427                                &np);
428         if (ret != 0) {
429                 goto fail;
430         }
431         offset += np;
432
433         ret = ctdb_uint32_pull(buf+offset,
434                                buflen-offset,
435                                &value->flags,
436                                &np);
437         if (ret != 0) {
438                 goto fail;
439         }
440         offset += np;
441
442         *out = value;
443         *npull = offset;
444
445         return 0;
446
447 fail:
448         talloc_free(value);
449         return ret;
450 }
451
452 static size_t ctdb_event_request_status_len(
453                                 struct ctdb_event_request_status *in)
454 {
455         return ctdb_stringn_len(&in->component) +
456                 ctdb_stringn_len(&in->event);
457 }
458
459 static void ctdb_event_request_status_push(
460                                 struct ctdb_event_request_status *in,
461                                 uint8_t *buf,
462                                 size_t *npush)
463 {
464         size_t offset = 0, np;
465
466         ctdb_stringn_push(&in->component, buf+offset, &np);
467         offset += np;
468
469         ctdb_stringn_push(&in->event, buf+offset, &np);
470         offset += np;
471
472         *npush = offset;
473 }
474
475 static int ctdb_event_request_status_pull(
476                                 uint8_t *buf,
477                                 size_t buflen,
478                                 TALLOC_CTX *mem_ctx,
479                                 struct ctdb_event_request_status **out,
480                                 size_t *npull)
481 {
482         struct ctdb_event_request_status *value;
483         size_t offset = 0, np;
484         int ret;
485
486         value = talloc(mem_ctx, struct ctdb_event_request_status);
487         if (value == NULL) {
488                 return ENOMEM;
489         }
490
491         ret = ctdb_stringn_pull(buf+offset,
492                                 buflen-offset,
493                                 value,
494                                 &value->component,
495                                 &np);
496         if (ret != 0) {
497                 goto fail;
498         }
499         offset += np;
500
501         ret = ctdb_stringn_pull(buf+offset,
502                                 buflen-offset,
503                                 value,
504                                 &value->event,
505                                 &np);
506         if (ret != 0) {
507                 goto fail;
508         }
509         offset += np;
510
511         *out = value;
512         *npull = offset;
513
514         return 0;
515
516 fail:
517         talloc_free(value);
518         return ret;
519 }
520
521 static size_t ctdb_event_request_script_len(
522                                 struct ctdb_event_request_script *in)
523 {
524         return ctdb_stringn_len(&in->component) +
525                 ctdb_stringn_len(&in->script) +
526                 ctdb_event_script_action_len(in->action);
527 }
528
529 static void ctdb_event_request_script_push(
530                                 struct ctdb_event_request_script *in,
531                                 uint8_t *buf,
532                                 size_t *npush)
533 {
534         size_t offset = 0, np;
535
536         ctdb_stringn_push(&in->component, buf+offset, &np);
537         offset += np;
538
539         ctdb_stringn_push(&in->script, buf+offset, &np);
540         offset += np;
541
542         ctdb_event_script_action_push(in->action, buf+offset, &np);
543         offset += np;
544
545         *npush = offset;
546 }
547
548 static int ctdb_event_request_script_pull(
549                                 uint8_t *buf,
550                                 size_t buflen,
551                                 TALLOC_CTX *mem_ctx,
552                                 struct ctdb_event_request_script **out,
553                                 size_t *npull)
554 {
555         struct ctdb_event_request_script *value;
556         size_t offset = 0, np;
557         int ret;
558
559         value = talloc(mem_ctx, struct ctdb_event_request_script);
560         if (value == NULL) {
561                 return ENOMEM;
562         }
563
564         ret = ctdb_stringn_pull(buf+offset,
565                                 buflen-offset,
566                                 value,
567                                 &value->component,
568                                 &np);
569         if (ret != 0) {
570                 goto fail;
571         }
572         offset += np;
573
574         ret = ctdb_stringn_pull(buf+offset,
575                                 buflen-offset,
576                                 value,
577                                 &value->script,
578                                 &np);
579         if (ret != 0) {
580                 goto fail;
581         }
582         offset += np;
583
584         ret = ctdb_event_script_action_pull(buf+offset,
585                                             buflen-offset,
586                                             &value->action,
587                                             &np);
588         if (ret != 0) {
589                 goto fail;
590         }
591         offset += np;
592
593         *out = value;
594         *npull = offset;
595
596         return 0;
597
598 fail:
599         talloc_free(value);
600         return ret;
601 }
602
603 static size_t ctdb_event_reply_status_len(
604                                 struct ctdb_event_reply_status *in)
605 {
606         return ctdb_int32_len(&in->summary) +
607                 ctdb_event_script_list_len(in->script_list);
608 }
609
610 static void ctdb_event_reply_status_push(
611                                 struct ctdb_event_reply_status *in,
612                                 uint8_t *buf,
613                                 size_t *npush)
614 {
615         size_t offset = 0, np;
616
617         ctdb_int32_push(&in->summary, buf+offset, &np);
618         offset += np;
619
620         ctdb_event_script_list_push(in->script_list, buf+offset, &np);
621         offset += np;
622
623         *npush = offset;
624 }
625
626 static int ctdb_event_reply_status_pull(
627                                 uint8_t *buf,
628                                 size_t buflen,
629                                 TALLOC_CTX *mem_ctx,
630                                 struct ctdb_event_reply_status **out,
631                                 size_t *npull)
632 {
633         struct ctdb_event_reply_status *value;
634         size_t offset = 0, np;
635         int ret;
636
637         value = talloc(mem_ctx, struct ctdb_event_reply_status);
638         if (value == NULL) {
639                 return ENOMEM;
640         }
641
642         ret = ctdb_int32_pull(buf+offset, buflen-offset, &value->summary, &np);
643         if (ret != 0) {
644                 goto fail;
645         }
646         offset += np;
647
648         ret = ctdb_event_script_list_pull(buf+offset,
649                                           buflen-offset,
650                                           value,
651                                           &value->script_list,
652                                           &np);
653         if (ret != 0) {
654                 goto fail;
655         }
656         offset += np;
657
658         *out = value;
659         *npull = offset;
660
661         return 0;
662
663 fail:
664         talloc_free(value);
665         return ret;
666 }
667
668 static size_t ctdb_event_header_len(struct ctdb_event_header *in)
669 {
670         return ctdb_uint32_len(&in->length) +
671                 ctdb_uint32_len(&in->version) +
672                 ctdb_uint32_len(&in->reqid);
673 }
674
675 static void ctdb_event_header_push(struct ctdb_event_header *in,
676                                    uint8_t *buf,
677                                    size_t *npush)
678 {
679         size_t offset = 0, np;
680
681         ctdb_uint32_push(&in->length, buf+offset, &np);
682         offset += np;
683
684         ctdb_uint32_push(&in->version, buf+offset, &np);
685         offset += np;
686
687         ctdb_uint32_push(&in->reqid, buf+offset, &np);
688         offset += np;
689
690         *npush = offset;
691 }
692
693 static int ctdb_event_header_pull(uint8_t *buf,
694                                   size_t buflen,
695                                   struct ctdb_event_header *value,
696                                   size_t *npull)
697 {
698         size_t offset = 0, np;
699         int ret;
700
701         ret = ctdb_uint32_pull(buf+offset,
702                                buflen-offset,
703                                &value->length,
704                                &np);
705         if (ret != 0) {
706                 return ret;
707         }
708         offset += np;
709
710         ret = ctdb_uint32_pull(buf+offset,
711                                buflen-offset,
712                                &value->version,
713                                &np);
714         if (ret != 0) {
715                 return ret;
716         }
717         offset += np;
718
719         ret = ctdb_uint32_pull(buf+offset,
720                                buflen-offset,
721                                &value->reqid,
722                                &np);
723         if (ret != 0) {
724                 return ret;
725         }
726         offset += np;
727
728         *npull = offset;
729
730         return 0;
731 }
732
733 int ctdb_event_header_extract(uint8_t *buf,
734                               size_t buflen,
735                               struct ctdb_event_header *value)
736 {
737         size_t np;
738
739         return ctdb_event_header_pull(buf, buflen, value, &np);
740 }
741
742 static size_t ctdb_event_request_data_len(struct ctdb_event_request *in)
743 {
744         size_t len;
745
746         len = ctdb_event_command_len(in->cmd);
747
748         switch (in->cmd) {
749         case CTDB_EVENT_CMD_RUN:
750                 len += ctdb_event_request_run_len(in->data.run);
751                 break;
752
753         case CTDB_EVENT_CMD_STATUS:
754                 len += ctdb_event_request_status_len(in->data.status);
755                 break;
756
757         case CTDB_EVENT_CMD_SCRIPT:
758                 len += ctdb_event_request_script_len(in->data.script);
759                 break;
760
761         default:
762                 break;
763         }
764
765         return len;
766 }
767
768 static void ctdb_event_request_data_push(struct ctdb_event_request *in,
769                                          uint8_t *buf,
770                                          size_t *npush)
771 {
772         size_t offset = 0, np;
773
774         ctdb_event_command_push(in->cmd, buf+offset, &np);
775         offset += np;
776
777         switch (in->cmd) {
778         case CTDB_EVENT_CMD_RUN:
779                 ctdb_event_request_run_push(in->data.run, buf+offset, &np);
780                 break;
781
782         case CTDB_EVENT_CMD_STATUS:
783                 ctdb_event_request_status_push(in->data.status,
784                                                buf+offset,
785                                                &np);
786                 break;
787
788         case CTDB_EVENT_CMD_SCRIPT:
789                 ctdb_event_request_script_push(in->data.script,
790                                                buf+offset,
791                                                &np);
792                 break;
793         default:
794                 np = 0;
795                 break;
796         }
797         offset += np;
798
799         *npush = offset;
800 }
801
802 static int ctdb_event_request_data_pull(uint8_t *buf,
803                                         size_t buflen,
804                                         TALLOC_CTX *mem_ctx,
805                                         struct ctdb_event_request **out,
806                                         size_t *npull)
807 {
808         struct ctdb_event_request *value;
809         size_t offset = 0, np;
810         int ret;
811
812         value = talloc(mem_ctx, struct ctdb_event_request);
813         if (value == NULL) {
814                 return ENOMEM;
815         }
816
817         ret = ctdb_event_command_pull(buf+offset,
818                                       buflen-offset,
819                                       &value->cmd,
820                                       &np);
821         if (ret != 0) {
822                 goto fail;
823         }
824         offset += np;
825
826         switch (value->cmd) {
827         case CTDB_EVENT_CMD_RUN:
828                 ret = ctdb_event_request_run_pull(buf+offset,
829                                                   buflen-offset,
830                                                   value,
831                                                   &value->data.run,
832                                                   &np);
833                 break;
834
835         case CTDB_EVENT_CMD_STATUS:
836                 ret = ctdb_event_request_status_pull(buf+offset,
837                                                      buflen-offset,
838                                                      value,
839                                                      &value->data.status,
840                                                      &np);
841                 break;
842
843         case CTDB_EVENT_CMD_SCRIPT:
844                 ret = ctdb_event_request_script_pull(buf+offset,
845                                                      buflen-offset,
846                                                      value,
847                                                      &value->data.script,
848                                                      &np);
849                 break;
850
851         default:
852                 np = 0;
853                 break;
854         }
855
856         if (ret != 0) {
857                 goto fail;
858         }
859         offset += np;
860
861         *out = value;
862         *npull = offset;
863
864         return 0;
865
866 fail:
867         talloc_free(value);
868         return ret;
869 }
870
871 static size_t ctdb_event_reply_data_len(struct ctdb_event_reply *in)
872 {
873         size_t len;
874
875         len = ctdb_event_command_len(in->cmd) +
876                 ctdb_int32_len(&in->result);
877
878         if (in->result != 0) {
879                 goto done;
880         }
881
882         switch (in->cmd) {
883         case CTDB_EVENT_CMD_STATUS:
884                 len += ctdb_event_reply_status_len(in->data.status);
885                 break;
886
887         default:
888                 break;
889         }
890
891 done:
892         return len;
893 }
894
895 static void ctdb_event_reply_data_push(struct ctdb_event_reply *in,
896                                        uint8_t *buf,
897                                        size_t *npush)
898 {
899         size_t offset = 0, np;
900
901         ctdb_event_command_push(in->cmd, buf+offset, &np);
902         offset += np;
903
904         ctdb_int32_push(&in->result, buf+offset, &np);
905         offset += np;
906
907         if (in->result != 0) {
908                 goto done;
909         }
910
911         switch (in->cmd) {
912         case CTDB_EVENT_CMD_STATUS:
913                 ctdb_event_reply_status_push(in->data.status, buf+offset, &np);
914                 break;
915
916         default:
917                 np = 0;
918                 break;
919         }
920         offset += np;
921
922 done:
923         *npush = offset;
924 }
925
926 static int ctdb_event_reply_data_pull(uint8_t *buf,
927                                       size_t buflen,
928                                       TALLOC_CTX *mem_ctx,
929                                       struct ctdb_event_reply **out,
930                                       size_t *npull)
931 {
932         struct ctdb_event_reply *value;
933         size_t offset = 0, np;
934         int ret;
935
936         value = talloc(mem_ctx, struct ctdb_event_reply);
937         if (value == NULL) {
938                 return ENOMEM;
939         }
940
941         ret = ctdb_event_command_pull(buf+offset,
942                                       buflen-offset,
943                                       &value->cmd,
944                                       &np);
945         if (ret != 0) {
946                 goto fail;
947         }
948         offset += np;
949
950         ret = ctdb_int32_pull(buf+offset, buflen-offset, &value->result, &np);
951         if (ret != 0) {
952                 goto fail;
953         }
954         offset += np;
955
956         if (value->result != 0) {
957                 goto done;
958         }
959
960         switch (value->cmd) {
961         case CTDB_EVENT_CMD_STATUS:
962                 ret = ctdb_event_reply_status_pull(buf+offset,
963                                                    buflen-offset,
964                                                    value,
965                                                    &value->data.status,
966                                                    &np);
967                 break;
968
969         default:
970                 np = 0;
971                 break;
972         }
973
974         if (ret != 0) {
975                 goto fail;
976         }
977         offset += np;
978
979 done:
980         *out = value;
981         *npull = offset;
982
983         return 0;
984
985 fail:
986         talloc_free(value);
987         return ret;
988 }
989
990 size_t ctdb_event_request_len(struct ctdb_event_header *h,
991                               struct ctdb_event_request *in)
992 {
993         return ctdb_event_header_len(h) +
994                 ctdb_event_request_data_len(in);
995 }
996
997 int ctdb_event_request_push(struct ctdb_event_header *h,
998                             struct ctdb_event_request *in,
999                             uint8_t *buf,
1000                             size_t *buflen)
1001 {
1002         size_t len, offset = 0, np;
1003
1004         len = ctdb_event_request_len(h, in);
1005         if (*buflen < len) {
1006                 *buflen = len;
1007                 return EMSGSIZE;
1008         }
1009
1010         h->length = *buflen;
1011
1012         ctdb_event_header_push(h, buf+offset, &np);
1013         offset += np;
1014
1015         ctdb_event_request_data_push(in, buf+offset, &np);
1016         offset += np;
1017
1018         if (offset > *buflen) {
1019                 return EMSGSIZE;
1020         }
1021
1022         return 0;
1023 }
1024
1025 int ctdb_event_request_pull(uint8_t *buf,
1026                             size_t buflen,
1027                             struct ctdb_event_header *h,
1028                             TALLOC_CTX *mem_ctx,
1029                             struct ctdb_event_request **out)
1030 {
1031         size_t offset = 0, np;
1032         int ret;
1033
1034         ret = ctdb_event_header_pull(buf+offset, buflen-offset, h, &np);
1035         if (ret != 0) {
1036                 return ret;
1037         }
1038         offset += np;
1039
1040         ret = ctdb_event_request_data_pull(buf+offset,
1041                                            buflen-offset,
1042                                            mem_ctx,
1043                                            out,
1044                                            &np);
1045         if (ret != 0) {
1046                 return ret;
1047         }
1048         offset += np;
1049
1050         if (offset > buflen) {
1051                 return EMSGSIZE;
1052         }
1053
1054         return 0;
1055 }
1056
1057 size_t ctdb_event_reply_len(struct ctdb_event_header *h,
1058                             struct ctdb_event_reply *in)
1059 {
1060         return ctdb_event_header_len(h) +
1061                 ctdb_event_reply_data_len(in);
1062 }
1063
1064 int ctdb_event_reply_push(struct ctdb_event_header *h,
1065                           struct ctdb_event_reply *in,
1066                           uint8_t *buf,
1067                           size_t *buflen)
1068 {
1069         size_t len, offset = 0, np;
1070
1071         len = ctdb_event_reply_len(h, in);
1072         if (*buflen < len) {
1073                 *buflen = len;
1074                 return EMSGSIZE;
1075         }
1076
1077         h->length = *buflen;
1078
1079         ctdb_event_header_push(h, buf+offset, &np);
1080         offset += np;
1081
1082         ctdb_event_reply_data_push(in, buf+offset, &np);
1083         offset += np;
1084
1085         if (offset > *buflen) {
1086                 return EMSGSIZE;
1087         }
1088
1089         return 0;
1090 }
1091
1092 int ctdb_event_reply_pull(uint8_t *buf,
1093                           size_t buflen,
1094                           struct ctdb_event_header *h,
1095                           TALLOC_CTX *mem_ctx,
1096                           struct ctdb_event_reply **out)
1097 {
1098         size_t offset = 0, np;
1099         int ret;
1100
1101         ret = ctdb_event_header_pull(buf+offset, buflen-offset, h, &np);
1102         if (ret != 0) {
1103                 return ret;
1104         }
1105         offset += np;
1106
1107         ret = ctdb_event_reply_data_pull(buf+offset,
1108                                          buflen-offset,
1109                                          mem_ctx,
1110                                          out,
1111                                          &np);
1112         if (ret != 0) {
1113                 return ret;
1114         }
1115         offset += np;
1116
1117         if (offset > buflen) {
1118                 return EMSGSIZE;
1119         }
1120
1121         return 0;
1122 }