fbd85e20d78bd104b434127b31f36910b5adf038
[vlendec/samba-autobuild/.git] / ctdb / protocol / protocol_event.c
1 /*
2    CTDB eventd protocol marshalling
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
25 #include "protocol.h"
26 #include "protocol_private.h"
27 #include "protocol_api.h"
28
29 static size_t ctdb_event_len(enum ctdb_event in)
30 {
31         uint32_t u32 = in;
32
33         return ctdb_uint32_len(&u32);
34 }
35
36 static void ctdb_event_push(enum ctdb_event in, uint8_t *buf, size_t *npush)
37 {
38         size_t np;
39         uint32_t u32 = in;
40
41         ctdb_uint32_push(&u32, buf, &np);
42
43         *npush = np;
44 }
45
46 static int ctdb_event_pull(uint8_t *buf, size_t buflen,
47                            TALLOC_CTX *mem_ctx, enum ctdb_event *out,
48                            size_t *npull)
49 {
50         uint32_t uint32_value;
51         enum ctdb_event value;
52         size_t np;
53         int ret;
54
55         ret = ctdb_uint32_pull(buf, buflen, &uint32_value, &np);
56         if (ret != 0) {
57                 return ret;
58         }
59
60         switch (uint32_value) {
61         case 0:
62                 value = CTDB_EVENT_INIT;
63                 break;
64
65         case 1:
66                 value = CTDB_EVENT_SETUP;
67                 break;
68
69         case 2:
70                 value = CTDB_EVENT_STARTUP;
71                 break;
72
73         case 3:
74                 value = CTDB_EVENT_START_RECOVERY;
75                 break;
76
77         case 4:
78                 value = CTDB_EVENT_RECOVERED;
79                 break;
80
81         case 5:
82                 value = CTDB_EVENT_TAKE_IP;
83                 break;
84
85         case 6:
86                 value = CTDB_EVENT_RELEASE_IP;
87                 break;
88
89         case 7:
90                 value = CTDB_EVENT_STOPPED;
91                 break;
92
93         case 8:
94                 value = CTDB_EVENT_MONITOR;
95                 break;
96
97         case 9:
98                 value = CTDB_EVENT_STATUS;
99                 break;
100
101         case 10:
102                 value = CTDB_EVENT_SHUTDOWN;
103                 break;
104
105         case 11:
106                 value = CTDB_EVENT_RELOAD;
107                 break;
108
109         case 12:
110                 value = CTDB_EVENT_UPDATE_IP;
111                 break;
112
113         case 13:
114                 value = CTDB_EVENT_IPREALLOCATED;
115                 break;
116
117         default:
118                 return EINVAL;
119         }
120
121         *out = value;
122         *npull = np;
123         return 0;
124 }
125
126 static size_t ctdb_event_command_len(enum ctdb_event_command in)
127 {
128         uint32_t u32 = in;
129
130         return ctdb_uint32_len(&u32);
131 }
132
133 static void ctdb_event_command_push(enum ctdb_event_command in, uint8_t *buf)
134 {
135         size_t np;
136         uint32_t u32 = in;
137
138         ctdb_uint32_push(&u32, buf, &np);
139 }
140
141 static int ctdb_event_command_pull(uint8_t *buf, size_t buflen,
142                                    TALLOC_CTX *mem_ctx,
143                                    enum ctdb_event_command *out)
144 {
145         uint32_t uint32_value;
146         enum ctdb_event_command value;
147         size_t np;
148         int ret;
149
150         ret = ctdb_uint32_pull(buf, buflen, &uint32_value, &np);
151         if (ret != 0) {
152                 return ret;
153         }
154
155         switch (uint32_value) {
156         case 1:
157                 value = CTDB_EVENT_COMMAND_RUN;
158                 break;
159
160         case 2:
161                 value = CTDB_EVENT_COMMAND_STATUS;
162                 break;
163
164         case 3:
165                 value = CTDB_EVENT_COMMAND_SCRIPT_LIST;
166                 break;
167
168         case 4:
169                 value = CTDB_EVENT_COMMAND_SCRIPT_ENABLE;
170                 break;
171
172         case 5:
173                 value = CTDB_EVENT_COMMAND_SCRIPT_DISABLE;
174                 break;
175
176         default:
177                 return EINVAL;
178         }
179
180         *out = value;
181         return 0;
182 }
183
184 static size_t ctdb_event_status_state_len(enum ctdb_event_status_state in)
185 {
186         uint32_t u32 = in;
187
188         return ctdb_uint32_len(&u32);
189 }
190
191 static void ctdb_event_status_state_push(enum ctdb_event_status_state in,
192                                          uint8_t *buf)
193 {
194         size_t np;
195         uint32_t u32 = in;
196
197         ctdb_uint32_push(&u32, buf, &np);
198 }
199
200 static int ctdb_event_status_state_pull(uint8_t *buf, size_t buflen,
201                                         TALLOC_CTX *mem_ctx,
202                                         enum ctdb_event_status_state *out)
203 {
204         uint32_t uint32_value;
205         enum ctdb_event_status_state value;
206         size_t np;
207         int ret;
208
209         ret = ctdb_uint32_pull(buf, buflen, &uint32_value, &np);
210         if (ret != 0) {
211                 return ret;
212         }
213
214         switch (uint32_value) {
215         case 1:
216                 value = CTDB_EVENT_LAST_RUN;
217                 break;
218
219         case 2:
220                 value = CTDB_EVENT_LAST_PASS;
221                 break;
222
223         case 3:
224                 value = CTDB_EVENT_LAST_FAIL;
225                 break;
226
227         default:
228                 return EINVAL;
229         }
230
231         *out = value;
232         return 0;
233 }
234
235 static size_t ctdb_event_request_run_len(struct ctdb_event_request_run *in)
236 {
237         return ctdb_event_len(in->event) +
238                ctdb_uint32_len(&in->timeout) +
239                ctdb_stringn_len(&in->arg_str);
240 }
241
242 static void ctdb_event_request_run_push(struct ctdb_event_request_run *in,
243                                         uint8_t *buf)
244 {
245         size_t offset = 0, np;
246
247         ctdb_event_push(in->event, buf, &np);
248         offset += np;
249
250         ctdb_uint32_push(&in->timeout, buf+offset, &np);
251         offset += np;
252
253         ctdb_stringn_push(&in->arg_str, buf+offset, &np);
254 }
255
256 static int ctdb_event_request_run_pull(uint8_t *buf, size_t buflen,
257                                        TALLOC_CTX *mem_ctx,
258                                        struct ctdb_event_request_run **out)
259 {
260         struct ctdb_event_request_run *rdata;
261         size_t offset = 0, np;
262         int ret;
263
264         rdata = talloc(mem_ctx, struct ctdb_event_request_run);
265         if (rdata == NULL) {
266                 return ENOMEM;
267         }
268
269         ret = ctdb_event_pull(buf, buflen, rdata, &rdata->event, &np);
270         if (ret != 0) {
271                 goto fail;
272         }
273         offset += np;
274
275         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &rdata->timeout,
276                                &np);
277         if (ret != 0) {
278                 goto fail;
279         }
280         offset += np;
281
282         ret = ctdb_stringn_pull(buf+offset, buflen-offset,
283                                 rdata, &rdata->arg_str, &np);
284         if (ret != 0) {
285                 goto fail;
286         }
287
288         *out = rdata;
289         return 0;
290
291 fail:
292         talloc_free(rdata);
293         return ret;
294 }
295
296 static size_t ctdb_event_request_status_len(
297                                 struct ctdb_event_request_status *in)
298 {
299         return ctdb_event_len(in->event) +
300                ctdb_event_status_state_len(in->state);
301 }
302
303 static void ctdb_event_request_status_push(
304                                 struct ctdb_event_request_status *in,
305                                 uint8_t *buf)
306 {
307         size_t offset = 0, np;
308
309         ctdb_event_push(in->event, buf, &np);
310         offset += np;
311
312         ctdb_event_status_state_push(in->state, buf+offset);
313 }
314
315 static int ctdb_event_request_status_pull(
316                                 uint8_t *buf, size_t buflen,
317                                 TALLOC_CTX *mem_ctx,
318                                 struct ctdb_event_request_status **out)
319 {
320         struct ctdb_event_request_status *rdata;
321         size_t offset = 0, np;
322         int ret;
323
324         rdata = talloc(mem_ctx, struct ctdb_event_request_status);
325         if (rdata == NULL) {
326                 return ENOMEM;
327         }
328
329         ret = ctdb_event_pull(buf, buflen, rdata, &rdata->event, &np);
330         if (ret != 0) {
331                 talloc_free(rdata);
332                 return ret;
333         }
334         offset += np;
335
336         ret = ctdb_event_status_state_pull(buf+offset, buflen-offset,
337                                            rdata, &rdata->state);
338         if (ret != 0) {
339                 talloc_free(rdata);
340                 return ret;
341         }
342
343         *out = rdata;
344         return 0;
345 }
346
347 static size_t ctdb_event_request_script_enable_len(
348                                 struct ctdb_event_request_script_enable *in)
349 {
350         return ctdb_stringn_len(&in->script_name);
351 }
352
353 static void ctdb_event_request_script_enable_push(
354                                 struct ctdb_event_request_script_enable *in,
355                                 uint8_t *buf)
356 {
357         size_t np;
358
359         ctdb_stringn_push(&in->script_name, buf, &np);
360 }
361
362 static int ctdb_event_request_script_enable_pull(
363                                 uint8_t *buf, size_t buflen,
364                                 TALLOC_CTX *mem_ctx,
365                                 struct ctdb_event_request_script_enable **out)
366 {
367         struct ctdb_event_request_script_enable *rdata;
368         size_t np;
369         int ret;
370
371         rdata = talloc(mem_ctx, struct ctdb_event_request_script_enable);
372         if (rdata == NULL) {
373                 return ENOMEM;
374         }
375
376         ret = ctdb_stringn_pull(buf, buflen, rdata, &rdata->script_name, &np);
377         if (ret != 0) {
378                 talloc_free(rdata);
379                 return ret;
380         }
381
382         *out = rdata;
383         return 0;
384 }
385
386 static size_t ctdb_event_request_script_disable_len(
387                                 struct ctdb_event_request_script_disable *in)
388 {
389         return ctdb_stringn_len(&in->script_name);
390 }
391
392 static void ctdb_event_request_script_disable_push(
393                                 struct ctdb_event_request_script_disable *in,
394                                 uint8_t *buf)
395 {
396         size_t np;
397
398         ctdb_stringn_push(&in->script_name, buf, &np);
399 }
400
401 static int ctdb_event_request_script_disable_pull(
402                                 uint8_t *buf, size_t buflen,
403                                 TALLOC_CTX *mem_ctx,
404                                 struct ctdb_event_request_script_disable **out)
405 {
406         struct ctdb_event_request_script_disable *rdata;
407         size_t np;
408         int ret;
409
410         rdata = talloc(mem_ctx, struct ctdb_event_request_script_disable);
411         if (rdata == NULL) {
412                 return ENOMEM;
413         }
414
415         ret = ctdb_stringn_pull(buf, buflen, rdata, &rdata->script_name, &np);
416         if (ret != 0) {
417                 talloc_free(rdata);
418                 return ret;
419         }
420
421         *out = rdata;
422         return 0;
423 }
424
425 static size_t ctdb_event_request_data_len(struct ctdb_event_request_data *in)
426 {
427         size_t len = 0;
428
429         len += ctdb_event_command_len(in->command);
430
431         switch(in->command) {
432         case CTDB_EVENT_COMMAND_RUN:
433                 len += ctdb_event_request_run_len(in->data.run);
434                 break;
435
436         case CTDB_EVENT_COMMAND_STATUS:
437                 len += ctdb_event_request_status_len(in->data.status);
438                 break;
439
440         case CTDB_EVENT_COMMAND_SCRIPT_LIST:
441                 break;
442
443         case CTDB_EVENT_COMMAND_SCRIPT_ENABLE:
444                 len += ctdb_event_request_script_enable_len(
445                                                 in->data.script_enable);
446                 break;
447
448         case CTDB_EVENT_COMMAND_SCRIPT_DISABLE:
449                 len += ctdb_event_request_script_disable_len(
450                                                 in->data.script_disable);
451                 break;
452         }
453
454         return len;
455 }
456
457 static void ctdb_event_request_data_push(struct ctdb_event_request_data *in,
458                                          uint8_t *buf)
459 {
460         size_t offset = 0;
461
462         ctdb_event_command_push(in->command, buf);
463         offset += ctdb_event_command_len(in->command);
464
465         switch (in->command) {
466         case CTDB_EVENT_COMMAND_RUN:
467                 ctdb_event_request_run_push(in->data.run, buf+offset);
468                 break;
469
470         case CTDB_EVENT_COMMAND_STATUS:
471                 ctdb_event_request_status_push(in->data.status, buf+offset);
472                 break;
473
474         case CTDB_EVENT_COMMAND_SCRIPT_LIST:
475                 break;
476
477         case CTDB_EVENT_COMMAND_SCRIPT_ENABLE:
478                 ctdb_event_request_script_enable_push(
479                                                 in->data.script_enable,
480                                                 buf+offset);
481                 break;
482
483         case CTDB_EVENT_COMMAND_SCRIPT_DISABLE:
484                 ctdb_event_request_script_disable_push(
485                                                 in->data.script_disable,
486                                                 buf+offset);
487                 break;
488         }
489 }
490
491 static int ctdb_event_request_data_pull(uint8_t *buf, size_t buflen,
492                                         TALLOC_CTX *mem_ctx,
493                                         struct ctdb_event_request_data *out)
494 {
495         size_t offset = 0;
496         int ret;
497
498         ret = ctdb_event_command_pull(buf, buflen, mem_ctx, &out->command);
499         if (ret != 0) {
500                 return ret;
501         }
502         offset += ctdb_event_command_len(out->command);
503
504         switch (out->command) {
505         case CTDB_EVENT_COMMAND_RUN:
506                 ret = ctdb_event_request_run_pull(buf+offset, buflen-offset,
507                                                   mem_ctx, &out->data.run);
508                 break;
509
510         case CTDB_EVENT_COMMAND_STATUS:
511                 ret = ctdb_event_request_status_pull(
512                                                 buf+offset, buflen-offset,
513                                                 mem_ctx, &out->data.status);
514                 break;
515
516         case CTDB_EVENT_COMMAND_SCRIPT_LIST:
517                 ret = 0;
518                 break;
519
520         case CTDB_EVENT_COMMAND_SCRIPT_ENABLE:
521                 ret = ctdb_event_request_script_enable_pull(
522                                                 buf+offset, buflen-offset,
523                                                 mem_ctx,
524                                                 &out->data.script_enable);
525                 break;
526
527         case CTDB_EVENT_COMMAND_SCRIPT_DISABLE:
528                 ret = ctdb_event_request_script_disable_pull(
529                                                 buf+offset, buflen-offset,
530                                                 mem_ctx,
531                                                 &out->data.script_disable);
532                 break;
533         }
534
535         if (ret != 0) {
536                 return ret;
537         }
538
539         return 0;
540 }
541
542 static size_t ctdb_event_reply_status_len(struct ctdb_event_reply_status *in)
543 {
544         return ctdb_int32_len(&in->status) +
545                ctdb_script_list_len(in->script_list);
546 }
547
548 static void ctdb_event_reply_status_push(struct ctdb_event_reply_status *in,
549                                          uint8_t *buf)
550 {
551         size_t offset = 0, np;
552
553         ctdb_int32_push(&in->status, buf, &np);
554         offset += np;
555
556         ctdb_script_list_push(in->script_list, buf+offset, &np);
557 }
558
559 static int ctdb_event_reply_status_pull(uint8_t *buf, size_t buflen,
560                                         TALLOC_CTX *mem_ctx,
561                                         struct ctdb_event_reply_status **out)
562 {
563         struct ctdb_event_reply_status *rdata;
564         size_t offset = 0, np;
565         int ret;
566
567         rdata = talloc(mem_ctx, struct ctdb_event_reply_status);
568         if (rdata == NULL) {
569                 return ENOMEM;
570         }
571
572         ret = ctdb_int32_pull(buf, buflen, &rdata->status, &np);
573         if (ret != 0) {
574                 talloc_free(rdata);
575                 return ret;
576         }
577         offset += np;
578
579         ret = ctdb_script_list_pull(buf+offset, buflen-offset,
580                                     rdata, &rdata->script_list, &np);
581         if (ret != 0) {
582                 talloc_free(rdata);
583                 return ret;
584         }
585
586         *out = rdata;
587         return 0;
588 }
589
590 static size_t ctdb_event_reply_script_list_len(
591                                 struct ctdb_event_reply_script_list *in)
592 {
593         return ctdb_script_list_len(in->script_list);
594 }
595
596 static void ctdb_event_reply_script_list_push(
597                                 struct ctdb_event_reply_script_list *in,
598                                 uint8_t *buf)
599 {
600         size_t np;
601
602         ctdb_script_list_push(in->script_list, buf, &np);
603 }
604
605 static int ctdb_event_reply_script_list_pull(
606                                 uint8_t *buf, size_t buflen,
607                                 TALLOC_CTX *mem_ctx,
608                                 struct ctdb_event_reply_script_list **out)
609 {
610         struct ctdb_event_reply_script_list *rdata;
611         size_t np;
612         int ret;
613
614         rdata = talloc(mem_ctx, struct ctdb_event_reply_script_list);
615         if (rdata == NULL) {
616                 return ENOMEM;
617         }
618
619         ret = ctdb_script_list_pull(buf, buflen, rdata, &rdata->script_list,
620                                     &np);
621         if (ret != 0) {
622                 talloc_free(rdata);
623                 return ret;
624         }
625
626         *out = rdata;
627         return 0;
628 }
629
630 static size_t ctdb_event_reply_data_len(struct ctdb_event_reply_data *in)
631 {
632         size_t len = 0;
633
634         len += ctdb_event_command_len(in->command);
635         len += ctdb_int32_len(&in->result);
636
637         switch (in->command) {
638         case CTDB_EVENT_COMMAND_RUN:
639                 break;
640
641         case CTDB_EVENT_COMMAND_STATUS:
642                 len += ctdb_event_reply_status_len(in->data.status);
643                 break;
644
645         case CTDB_EVENT_COMMAND_SCRIPT_LIST:
646                 len += ctdb_event_reply_script_list_len(in->data.script_list);
647                 break;
648
649         case CTDB_EVENT_COMMAND_SCRIPT_ENABLE:
650                 break;
651
652         case CTDB_EVENT_COMMAND_SCRIPT_DISABLE:
653                 break;
654         }
655
656         return len;
657 }
658
659 static void ctdb_event_reply_data_push(struct ctdb_event_reply_data *in,
660                                        uint8_t *buf)
661 {
662         size_t offset = 0, np;
663
664         ctdb_event_command_push(in->command, buf);
665         offset += ctdb_event_command_len(in->command);
666
667         ctdb_int32_push(&in->result, buf+offset, &np);
668         offset += np;
669
670         switch (in->command) {
671         case CTDB_EVENT_COMMAND_RUN:
672                 break;
673
674         case CTDB_EVENT_COMMAND_STATUS:
675                 ctdb_event_reply_status_push(in->data.status, buf+offset);
676                 break;
677
678         case CTDB_EVENT_COMMAND_SCRIPT_LIST:
679                 ctdb_event_reply_script_list_push(in->data.script_list,
680                                                   buf+offset);
681                 break;
682
683         case CTDB_EVENT_COMMAND_SCRIPT_ENABLE:
684                 break;
685
686         case CTDB_EVENT_COMMAND_SCRIPT_DISABLE:
687                 break;
688         }
689 }
690
691 static int ctdb_event_reply_data_pull(uint8_t *buf, size_t buflen,
692                                       TALLOC_CTX *mem_ctx,
693                                       struct ctdb_event_reply_data *out)
694 {
695         size_t offset = 0, np;
696         int ret;
697
698         ret = ctdb_event_command_pull(buf, buflen, mem_ctx, &out->command);
699         if (ret != 0) {
700                 return ret;
701         }
702         offset += ctdb_event_command_len(out->command);
703
704         ret = ctdb_int32_pull(buf+offset, buflen-offset, &out->result, &np);
705         if (ret != 0) {
706                 return ret;
707         }
708         offset += np;
709
710         switch (out->command) {
711         case CTDB_EVENT_COMMAND_RUN:
712                 break;
713
714         case CTDB_EVENT_COMMAND_STATUS:
715                 ret = ctdb_event_reply_status_pull(
716                                         buf+offset, buflen-offset,
717                                         mem_ctx, &out->data.status);
718                 break;
719
720         case CTDB_EVENT_COMMAND_SCRIPT_LIST:
721                 ret = ctdb_event_reply_script_list_pull(
722                                         buf+offset, buflen-offset,
723                                         mem_ctx, &out->data.script_list);
724                 break;
725
726         case CTDB_EVENT_COMMAND_SCRIPT_ENABLE:
727                 break;
728
729         case CTDB_EVENT_COMMAND_SCRIPT_DISABLE:
730                 break;
731         }
732
733         if (ret != 0) {
734                 return ret;
735         }
736
737         return 0;
738 }
739
740 static size_t ctdb_event_header_len(struct ctdb_event_header *in)
741 {
742         return ctdb_uint32_len(&in->length) + ctdb_uint32_len(&in->reqid);
743 }
744
745 static void ctdb_event_header_push(struct ctdb_event_header *in, uint8_t *buf)
746 {
747         size_t offset = 0, np;
748
749         ctdb_uint32_push(&in->length, buf, &np);
750         offset += np;
751
752         ctdb_uint32_push(&in->reqid, buf+offset, &np);
753 }
754
755 static int ctdb_event_header_pull(uint8_t *buf, size_t buflen,
756                                   TALLOC_CTX *mem_ctx,
757                                   struct ctdb_event_header *out)
758 {
759         size_t offset = 0, np;
760         int ret;
761
762         ret = ctdb_uint32_pull(buf, buflen, &out->length, &np);
763         if (ret != 0) {
764                 return ret;
765         }
766         offset += np;
767
768         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->reqid, &np);
769         if (ret != 0) {
770                 return ret;
771         }
772
773         return 0;
774 }
775
776 void ctdb_event_header_fill(struct ctdb_event_header *h, uint32_t reqid)
777 {
778         h->length = ctdb_event_header_len(h);
779         h->reqid = reqid;
780 }
781
782 size_t ctdb_event_request_len(struct ctdb_event_request *in)
783 {
784         return ctdb_event_header_len(&in->header) +
785                ctdb_event_request_data_len(&in->rdata);
786 }
787
788 int ctdb_event_request_push(struct ctdb_event_request *in,
789                             uint8_t *buf, size_t *buflen)
790 {
791         size_t len, offset = 0;
792
793         len = ctdb_event_request_len(in);
794         if (*buflen < len) {
795                 *buflen = len;
796                 return EMSGSIZE;
797         }
798
799         in->header.length = *buflen;
800
801         ctdb_event_header_push(&in->header, buf);
802         offset += ctdb_event_header_len(&in->header);
803
804         ctdb_event_request_data_push(&in->rdata, buf+offset);
805
806         return 0;
807 }
808
809 int ctdb_event_request_pull(uint8_t *buf, size_t buflen,
810                             TALLOC_CTX *mem_ctx,
811                             struct ctdb_event_request *out)
812 {
813         size_t offset = 0;
814         int ret;
815
816         ret = ctdb_event_header_pull(buf, buflen, mem_ctx, &out->header);
817         if (ret != 0) {
818                 return ret;
819         }
820         offset += ctdb_event_header_len(&out->header);
821
822         ret = ctdb_event_request_data_pull(buf+offset, buflen-offset,
823                                            mem_ctx, &out->rdata);
824         if (ret != 0) {
825                 return ret;
826         }
827
828         return 0;
829 }
830
831 size_t ctdb_event_reply_len(struct ctdb_event_reply *in)
832 {
833         return ctdb_event_header_len(&in->header) +
834                ctdb_event_reply_data_len(&in->rdata);
835 }
836
837 int ctdb_event_reply_push(struct ctdb_event_reply *in,
838                           uint8_t *buf, size_t *buflen)
839 {
840         size_t len, offset = 0;
841
842         len = ctdb_event_reply_len(in);
843         if (*buflen < len) {
844                 *buflen = len;
845                 return EMSGSIZE;
846         }
847
848         in->header.length = *buflen;
849
850         ctdb_event_header_push(&in->header, buf);
851         offset += ctdb_event_header_len(&in->header);
852
853         ctdb_event_reply_data_push(&in->rdata, buf+offset);
854
855         return 0;
856 }
857
858 int ctdb_event_reply_pull(uint8_t *buf, size_t buflen,
859                           TALLOC_CTX *mem_ctx,
860                           struct ctdb_event_reply *out)
861 {
862         size_t offset = 0;
863         int ret;
864
865         ret = ctdb_event_header_pull(buf, buflen, mem_ctx, &out->header);
866         if (ret != 0) {
867                 return ret;
868         }
869         offset += ctdb_event_header_len(&out->header);
870
871         ret = ctdb_event_reply_data_pull(buf+offset, buflen-offset,
872                                          mem_ctx, &out->rdata);
873         if (ret != 0) {
874                 return ret;
875         }
876
877         return 0;
878 }