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