ctdb-protocol: Fix marshalling for struct ctdb_rec_data
[obnox/samba/samba-obnox.git] / ctdb / protocol / protocol_types.c
1 /*
2    CTDB protocol marshalling
3
4    Copyright (C) Amitay Isaacs  2015
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 <tdb.h>
25
26 #include "protocol.h"
27 #include "protocol_private.h"
28 #include "protocol_api.h"
29
30 size_t ctdb_uint32_len(uint32_t val)
31 {
32         return sizeof(uint32_t);
33 }
34
35 void ctdb_uint32_push(uint32_t val, uint8_t *buf)
36 {
37         memcpy(buf, &val, sizeof(uint32_t));
38 }
39
40 int ctdb_uint32_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
41                      uint32_t *out)
42 {
43         if (buflen < sizeof(uint32_t)) {
44                 return EMSGSIZE;
45         }
46
47         *out = *(uint32_t *)buf;
48         return 0;
49 }
50
51 size_t ctdb_uint64_len(uint64_t val)
52 {
53         return sizeof(uint64_t);
54 }
55
56 void ctdb_uint64_push(uint64_t val, uint8_t *buf)
57 {
58         memcpy(buf, &val, sizeof(uint64_t));
59 }
60
61 int ctdb_uint64_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
62                      uint64_t *out)
63 {
64         if (buflen < sizeof(uint64_t)) {
65                 return EMSGSIZE;
66         }
67
68         *out = *(uint64_t *)buf;
69         return 0;
70 }
71
72 size_t ctdb_double_len(double val)
73 {
74         return sizeof(double);
75 }
76
77 void ctdb_double_push(double val, uint8_t *buf)
78 {
79         memcpy(buf, &val, sizeof(double));
80 }
81
82 int ctdb_double_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
83                      double *out)
84 {
85         if (buflen < sizeof(double)) {
86                 return EMSGSIZE;
87         }
88
89         *out = *(double *)buf;
90         return 0;
91 }
92
93 size_t ctdb_uint8_array_len(struct ctdb_uint8_array *array)
94 {
95         return array->num * sizeof(uint8_t);
96 }
97
98 void ctdb_uint8_array_push(struct ctdb_uint8_array *array, uint8_t *buf)
99 {
100         memcpy(buf, array->val, array->num * sizeof(uint8_t));
101 }
102
103 int ctdb_uint8_array_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
104                           struct ctdb_uint8_array **out)
105 {
106         struct ctdb_uint8_array *array;
107
108         array = talloc(mem_ctx, struct ctdb_uint8_array);
109         if (array == NULL) {
110                 return ENOMEM;
111         }
112
113         array->num = buflen / sizeof(uint8_t);
114
115         array->val = talloc_array(array, uint8_t, array->num);
116         if (array->val == NULL) {
117                 talloc_free(array);
118                 return ENOMEM;
119         }
120         memcpy(array->val, buf, buflen);
121
122         *out = array;
123         return 0;
124 }
125
126 size_t ctdb_uint64_array_len(struct ctdb_uint64_array *array)
127 {
128         return array->num * sizeof(uint64_t);
129 }
130
131 void ctdb_uint64_array_push(struct ctdb_uint64_array *array, uint8_t *buf)
132 {
133         memcpy(buf, array->val, array->num * sizeof(uint64_t));
134 }
135
136 int ctdb_uint64_array_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
137                            struct ctdb_uint64_array **out)
138 {
139         struct ctdb_uint64_array *array;
140
141         array = talloc(mem_ctx, struct ctdb_uint64_array);
142         if (array == NULL) {
143                 return ENOMEM;
144         }
145
146         array->num = buflen / sizeof(uint64_t);
147
148         array->val = talloc_array(array, uint64_t, array->num);
149         if (array->val == NULL) {
150                 talloc_free(array);
151                 return ENOMEM;
152         }
153         memcpy(array->val, buf, buflen);
154
155         *out = array;
156         return 0;
157 }
158
159 size_t ctdb_pid_len(pid_t pid)
160 {
161         return sizeof(pid_t);
162 }
163
164 void ctdb_pid_push(pid_t pid, uint8_t *buf)
165 {
166         memcpy(buf, &pid, sizeof(pid_t));
167 }
168
169 int ctdb_pid_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
170                   pid_t *out)
171 {
172         if (buflen < sizeof(pid_t)) {
173                 return EMSGSIZE;
174         }
175
176         *out = *(pid_t *)buf;
177         return 0;
178 }
179
180 size_t ctdb_string_len(const char *str)
181 {
182         if (str == NULL) {
183                 return 0;
184         }
185         return strlen(str) + 1;
186 }
187
188 void ctdb_string_push(const char *str, uint8_t *buf)
189 {
190         if (str == NULL) {
191                 return;
192         }
193         memcpy(buf, str, strlen(str)+1);
194 }
195
196 int ctdb_string_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
197                      const char **out)
198 {
199         char *str;
200
201         if (buflen == 0) {
202                 return 0;
203         }
204
205         str = talloc_strndup(mem_ctx, (char *)buf, buflen);
206         if (str == NULL) {
207                 return ENOMEM;
208         }
209
210         *out = str;
211         return 0;
212 }
213
214 struct stringn_wire {
215         uint32_t length;
216         uint8_t str[1];
217 };
218
219 size_t ctdb_stringn_len(const char *str)
220 {
221         return sizeof(uint32_t) + strlen(str) + 1;
222 }
223
224 void ctdb_stringn_push(const char *str, uint8_t *buf)
225 {
226         struct stringn_wire *wire = (struct stringn_wire *)buf;
227
228         if (str == NULL) {
229                 wire->length = 0;
230         } else {
231                 wire->length = strlen(str) + 1;
232                 memcpy(wire->str, str, wire->length);
233         }
234 }
235
236 int ctdb_stringn_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
237                       const char **out)
238 {
239         char *str;
240         struct stringn_wire *wire = (struct stringn_wire *)buf;
241
242         if (buflen < sizeof(uint32_t)) {
243                 return EMSGSIZE;
244         }
245
246         if (buflen < sizeof(uint32_t) + wire->length) {
247                 return EMSGSIZE;
248         }
249
250         str = talloc_strndup(mem_ctx, (char *)wire->str, wire->length);
251         if (str == NULL) {
252                 return ENOMEM;
253         }
254
255         *out = str;
256         return 0;
257 }
258
259 size_t ctdb_statistics_len(struct ctdb_statistics *stats)
260 {
261         return sizeof(struct ctdb_statistics);
262 }
263
264 void ctdb_statistics_push(struct ctdb_statistics *stats, uint8_t *buf)
265 {
266         memcpy(buf, stats, sizeof(struct ctdb_statistics));
267 }
268
269 int ctdb_statistics_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
270                          struct ctdb_statistics **out)
271 {
272         struct ctdb_statistics *stats;
273         struct ctdb_statistics *wire = (struct ctdb_statistics *)buf;
274
275         if (buflen < sizeof(struct ctdb_statistics)) {
276                 return EMSGSIZE;
277         }
278
279         stats = talloc(mem_ctx, struct ctdb_statistics);
280         if (stats == NULL) {
281                 return ENOMEM;
282         }
283         memcpy(stats, wire, sizeof(struct ctdb_statistics));
284
285         *out = stats;
286         return 0;
287 }
288
289 struct ctdb_statistics_list_wire {
290         uint32_t num;
291         struct ctdb_statistics stats[1];
292 };
293
294 size_t ctdb_statistics_list_len(struct ctdb_statistics_list *stats_list)
295 {
296         return offsetof(struct ctdb_statistics_list_wire, stats) +
297                stats_list->num * sizeof(struct ctdb_statistics);
298 }
299
300 void ctdb_statistics_list_push(struct ctdb_statistics_list *stats_list,
301                                uint8_t *buf)
302 {
303         struct ctdb_statistics_list_wire *wire =
304                 (struct ctdb_statistics_list_wire *)buf;
305
306         wire->num = stats_list->num;
307         memcpy(wire->stats, stats_list->stats,
308                stats_list->num * sizeof(struct ctdb_statistics));
309 }
310
311 int ctdb_statistics_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
312                               struct ctdb_statistics_list **out)
313 {
314         struct ctdb_statistics_list *stats_list;
315         struct ctdb_statistics_list_wire *wire =
316                 (struct ctdb_statistics_list_wire *)buf;
317
318         if (buflen < offsetof(struct ctdb_statistics_list_wire, stats)) {
319                 return EMSGSIZE;
320         }
321         if (buflen < offsetof(struct ctdb_statistics_list_wire, stats) +
322                      wire->num * sizeof(struct ctdb_statistics)) {
323                 return EMSGSIZE;
324         }
325
326         stats_list = talloc(mem_ctx, struct ctdb_statistics_list);
327         if (stats_list == NULL) {
328                 return ENOMEM;
329         }
330
331         stats_list->num = wire->num;
332
333         stats_list->stats = talloc_array(stats_list, struct ctdb_statistics,
334                                          wire->num);
335         if (stats_list->stats == NULL) {
336                 talloc_free(stats_list);
337                 return ENOMEM;
338         }
339
340         memcpy(stats_list->stats, wire->stats,
341                wire->num * sizeof(struct ctdb_statistics));
342
343         *out = stats_list;
344         return 0;
345 }
346
347 struct ctdb_vnn_map_wire {
348         uint32_t generation;
349         uint32_t size;
350         uint32_t map[1];
351 };
352
353 size_t ctdb_vnn_map_len(struct ctdb_vnn_map *vnnmap)
354 {
355         return offsetof(struct ctdb_vnn_map, map) +
356                vnnmap->size * sizeof(uint32_t);
357 }
358
359 void ctdb_vnn_map_push(struct ctdb_vnn_map *vnnmap, uint8_t *buf)
360 {
361         struct ctdb_vnn_map_wire *wire = (struct ctdb_vnn_map_wire *)buf;
362
363         memcpy(wire, vnnmap, offsetof(struct ctdb_vnn_map, map));
364         memcpy(wire->map, vnnmap->map, vnnmap->size * sizeof(uint32_t));
365 }
366
367 int ctdb_vnn_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
368                       struct ctdb_vnn_map **out)
369 {
370         struct ctdb_vnn_map *vnnmap;
371         struct ctdb_vnn_map_wire *wire = (struct ctdb_vnn_map_wire *)buf;
372
373         if (buflen < offsetof(struct ctdb_vnn_map_wire, map)) {
374                 return EMSGSIZE;
375         }
376         if (buflen < offsetof(struct ctdb_vnn_map_wire, map) +
377                      wire->size * sizeof(uint32_t)) {
378                 return EMSGSIZE;
379         }
380
381         vnnmap = talloc(mem_ctx, struct ctdb_vnn_map);
382         if (vnnmap == NULL) {
383                 return ENOMEM;
384         }
385
386         memcpy(vnnmap, wire, offsetof(struct ctdb_vnn_map, map));
387
388         vnnmap->map = talloc_memdup(vnnmap, wire->map,
389                                     wire->size * sizeof(uint32_t));
390         if (vnnmap->map == NULL) {
391                 talloc_free(vnnmap);
392                 return ENOMEM;
393         }
394
395         *out = vnnmap;
396         return 0;
397 }
398
399 struct ctdb_dbid_map_wire {
400         uint32_t num;
401         struct ctdb_dbid dbs[1];
402 };
403
404 size_t ctdb_dbid_map_len(struct ctdb_dbid_map *dbmap)
405 {
406         return sizeof(uint32_t) + dbmap->num * sizeof(struct ctdb_dbid);
407 }
408
409 void ctdb_dbid_map_push(struct ctdb_dbid_map *dbmap, uint8_t *buf)
410 {
411         struct ctdb_dbid_map_wire *wire = (struct ctdb_dbid_map_wire *)buf;
412
413         wire->num = dbmap->num;
414         memcpy(wire->dbs, dbmap->dbs, dbmap->num * sizeof(struct ctdb_dbid));
415 }
416
417 int ctdb_dbid_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
418                        struct ctdb_dbid_map **out)
419 {
420         struct ctdb_dbid_map *dbmap;
421         struct ctdb_dbid_map_wire *wire = (struct ctdb_dbid_map_wire *)buf;
422
423         if (buflen < sizeof(uint32_t)) {
424                 return EMSGSIZE;
425         }
426         if (buflen < sizeof(uint32_t) + wire->num * sizeof(struct ctdb_dbid)) {
427                 return EMSGSIZE;
428         }
429
430         dbmap = talloc(mem_ctx, struct ctdb_dbid_map);
431         if (dbmap == NULL) {
432                 return ENOMEM;
433         }
434
435         dbmap->num = wire->num;
436
437         dbmap->dbs = talloc_memdup(dbmap, wire->dbs,
438                                    wire->num * sizeof(struct ctdb_dbid));
439         if (dbmap->dbs == NULL) {
440                 talloc_free(dbmap);
441                 return ENOMEM;
442         }
443
444         *out = dbmap;
445         return 0;
446 }
447
448 size_t ctdb_pulldb_len(struct ctdb_pulldb *pulldb)
449 {
450         return sizeof(struct ctdb_pulldb);
451 }
452
453 void ctdb_pulldb_push(struct ctdb_pulldb *pulldb, uint8_t *buf)
454 {
455         memcpy(buf, pulldb, sizeof(struct ctdb_pulldb));
456 }
457
458 int ctdb_pulldb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
459                      struct ctdb_pulldb **out)
460 {
461         struct ctdb_pulldb *pulldb;
462
463         if (buflen < sizeof(struct ctdb_pulldb)) {
464                 return EMSGSIZE;
465         }
466
467         pulldb = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_pulldb));
468         if (pulldb == NULL) {
469                 return ENOMEM;
470         }
471
472         *out = pulldb;
473         return 0;
474 }
475
476 size_t ctdb_ltdb_header_len(struct ctdb_ltdb_header *header)
477 {
478         return sizeof(struct ctdb_ltdb_header);
479 }
480
481 void ctdb_ltdb_header_push(struct ctdb_ltdb_header *header, uint8_t *buf)
482 {
483         memcpy(buf, header, sizeof(struct ctdb_ltdb_header));
484 }
485
486 int ctdb_ltdb_header_pull(uint8_t *buf, size_t buflen,
487                           struct ctdb_ltdb_header *header)
488 {
489         if (buflen < sizeof(struct ctdb_ltdb_header)) {
490                 return EMSGSIZE;
491         }
492
493         memcpy(header, buf, sizeof(struct ctdb_ltdb_header));
494         return 0;
495 }
496
497 int ctdb_ltdb_header_extract(TDB_DATA *data, struct ctdb_ltdb_header *header)
498 {
499         int ret;
500
501         ret = ctdb_ltdb_header_pull(data->dptr, data->dsize, header);
502         if (ret != 0) {
503                 return ret;
504         }
505
506         data->dptr += sizeof(struct ctdb_ltdb_header);
507         data->dsize -= sizeof(struct ctdb_ltdb_header);
508
509         return 0;
510 }
511
512 struct ctdb_rec_data_wire {
513         uint32_t length;
514         uint32_t reqid;
515         uint32_t keylen;
516         uint32_t datalen;
517         uint8_t data[1];
518 };
519
520 size_t ctdb_rec_data_len(struct ctdb_rec_data *rec)
521 {
522         return offsetof(struct ctdb_rec_data_wire, data) +
523                rec->key.dsize + rec->data.dsize +
524                (rec->header == NULL ? 0 : sizeof(struct ctdb_ltdb_header));
525 }
526
527 void ctdb_rec_data_push(struct ctdb_rec_data *rec, uint8_t *buf)
528 {
529         struct ctdb_rec_data_wire *wire = (struct ctdb_rec_data_wire *)buf;
530         size_t offset;
531
532         wire->length = ctdb_rec_data_len(rec);
533         wire->reqid = rec->reqid;
534         wire->keylen = rec->key.dsize;
535         wire->datalen = rec->data.dsize;
536         if (rec->header != NULL) {
537                 wire->datalen += sizeof(struct ctdb_ltdb_header);
538         }
539
540         memcpy(wire->data, rec->key.dptr, rec->key.dsize);
541         offset = rec->key.dsize;
542         if (rec->header != NULL) {
543                 memcpy(&wire->data[offset], rec->header,
544                        sizeof(struct ctdb_ltdb_header));
545                 offset += sizeof(struct ctdb_ltdb_header);
546         }
547         if (rec->data.dsize > 0) {
548                 memcpy(&wire->data[offset], rec->data.dptr, rec->data.dsize);
549         }
550 }
551
552 static int ctdb_rec_data_pull_data(uint8_t *buf, size_t buflen,
553                                    uint32_t *reqid,
554                                    struct ctdb_ltdb_header **header,
555                                    TDB_DATA *key, TDB_DATA *data,
556                                    size_t *reclen)
557 {
558         struct ctdb_rec_data_wire *wire = (struct ctdb_rec_data_wire *)buf;
559         size_t offset, n;
560
561         if (buflen < offsetof(struct ctdb_rec_data_wire, data)) {
562                 return EMSGSIZE;
563         }
564         n = offsetof(struct ctdb_rec_data_wire, data) +
565                 wire->keylen + wire->datalen;
566         if (buflen < n) {
567                 return EMSGSIZE;
568         }
569
570         *reqid = wire->reqid;
571
572         key->dsize = wire->keylen;
573         key->dptr = wire->data;
574         offset = wire->keylen;
575
576         /* Always set header to NULL.  If it is required, exact it using
577          * ctdb_rec_data_extract_header()
578          */
579         *header = NULL;
580
581         data->dsize = wire->datalen;
582         data->dptr = &wire->data[offset];
583
584         *reclen = n;
585
586         return 0;
587 }
588
589 static int ctdb_rec_data_pull_elems(uint8_t *buf, size_t buflen,
590                                     TALLOC_CTX *mem_ctx,
591                                     struct ctdb_rec_data *out)
592 {
593         uint32_t reqid;
594         struct ctdb_ltdb_header *header;
595         TDB_DATA key, data;
596         size_t reclen;
597         int ret;
598
599         ret = ctdb_rec_data_pull_data(buf, buflen, &reqid, &header,
600                                       &key, &data, &reclen);
601         if (ret != 0) {
602                 return ret;
603         }
604
605         out->reqid = reqid;
606         out->header = NULL;
607
608         out->key.dsize = key.dsize;
609         if (key.dsize > 0) {
610                 out->key.dptr = talloc_memdup(mem_ctx, key.dptr, key.dsize);
611                 if (out->key.dptr == NULL) {
612                         return ENOMEM;
613                 }
614         }
615
616         out->data.dsize = data.dsize;
617         if (data.dsize > 0) {
618                 out->data.dptr = talloc_memdup(mem_ctx, data.dptr, data.dsize);
619                 if (out->data.dptr == NULL) {
620                         return ENOMEM;
621                 }
622         }
623
624         return 0;
625 }
626
627 int ctdb_rec_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
628                        struct ctdb_rec_data **out)
629 {
630         struct ctdb_rec_data *rec;
631         int ret;
632
633         rec = talloc(mem_ctx, struct ctdb_rec_data);
634         if (rec == NULL) {
635                 return ENOMEM;
636         }
637
638         ret = ctdb_rec_data_pull_elems(buf, buflen, rec, rec);
639         if (ret != 0) {
640                 TALLOC_FREE(rec);
641         }
642
643         *out = rec;
644         return ret;
645 }
646
647 struct ctdb_rec_buffer_wire {
648         uint32_t db_id;
649         uint32_t count;
650         uint8_t data[1];
651 };
652
653 size_t ctdb_rec_buffer_len(struct ctdb_rec_buffer *recbuf)
654 {
655         return offsetof(struct ctdb_rec_buffer_wire, data) + recbuf->buflen;
656 }
657
658 void ctdb_rec_buffer_push(struct ctdb_rec_buffer *recbuf, uint8_t *buf)
659 {
660         struct ctdb_rec_buffer_wire *wire = (struct ctdb_rec_buffer_wire *)buf;
661
662         wire->db_id = recbuf->db_id;
663         wire->count = recbuf->count;
664         if (recbuf->buflen > 0) {
665                 memcpy(wire->data, recbuf->buf, recbuf->buflen);
666         }
667 }
668
669 int ctdb_rec_buffer_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
670                          struct ctdb_rec_buffer **out)
671 {
672         struct ctdb_rec_buffer *recbuf;
673         struct ctdb_rec_buffer_wire *wire = (struct ctdb_rec_buffer_wire *)buf;
674         size_t offset;
675
676         if (buflen < offsetof(struct ctdb_rec_buffer_wire, data)) {
677                 return EMSGSIZE;
678         }
679
680         recbuf = talloc(mem_ctx, struct ctdb_rec_buffer);
681         if (recbuf == NULL) {
682                 return ENOMEM;
683         }
684
685         recbuf->db_id = wire->db_id;
686         recbuf->count = wire->count;
687
688         offset = offsetof(struct ctdb_rec_buffer_wire, data);
689         recbuf->buflen = buflen - offset;
690         recbuf->buf = talloc_memdup(recbuf, wire->data, recbuf->buflen);
691         if (recbuf->buf == NULL) {
692                 talloc_free(recbuf);
693                 return ENOMEM;
694         }
695
696         *out = recbuf;
697         return 0;
698 }
699
700 struct ctdb_rec_buffer *ctdb_rec_buffer_init(TALLOC_CTX *mem_ctx,
701                                              uint32_t db_id)
702 {
703         struct ctdb_rec_buffer *recbuf;
704
705         recbuf = talloc_zero(mem_ctx, struct ctdb_rec_buffer);
706         if (recbuf == NULL) {
707                 return recbuf;
708         }
709
710         recbuf->db_id = db_id;
711
712         return recbuf;
713 }
714
715 int ctdb_rec_buffer_add(TALLOC_CTX *mem_ctx, struct ctdb_rec_buffer *recbuf,
716                         uint32_t reqid, struct ctdb_ltdb_header *header,
717                         TDB_DATA key, TDB_DATA data)
718 {
719         struct ctdb_rec_data recdata;
720         size_t len;
721         uint8_t *ptr;
722
723         recdata.reqid = reqid;
724         recdata.header = header;
725         recdata.key = key;
726         recdata.data = data;
727
728         len = ctdb_rec_data_len(&recdata);
729
730         ptr = talloc_realloc(mem_ctx, recbuf->buf, uint8_t,
731                              recbuf->buflen + len);
732         if (ptr == NULL) {
733                 return ENOMEM;
734         }
735
736         ctdb_rec_data_push(&recdata, &ptr[recbuf->buflen]);
737
738         recbuf->count++;
739         recbuf->buf = ptr;
740         recbuf->buflen += len;
741         return 0;
742 }
743
744 int ctdb_rec_buffer_traverse(struct ctdb_rec_buffer *recbuf,
745                              ctdb_rec_parser_func_t func,
746                              void *private_data)
747 {
748         struct ctdb_ltdb_header *header;
749         TDB_DATA key, data;
750         uint32_t reqid;
751         size_t offset, reclen;
752         int ret = 0, i;
753
754         offset = 0;
755         for (i=0; i<recbuf->count; i++) {
756                 ret = ctdb_rec_data_pull_data(&recbuf->buf[offset],
757                                               recbuf->buflen - offset,
758                                               &reqid, &header,
759                                               &key, &data, &reclen);
760                 if (ret != 0) {
761                         return ret;
762                 }
763
764                 ret = func(reqid, header, key, data, private_data);
765                 if (ret != 0) {
766                         break;
767                 }
768
769                 offset += reclen;
770         }
771
772         return ret;
773 }
774
775 size_t ctdb_traverse_start_len(struct ctdb_traverse_start *traverse)
776 {
777         return sizeof(struct ctdb_traverse_start);
778 }
779
780 void ctdb_traverse_start_push(struct ctdb_traverse_start *traverse,
781                               uint8_t *buf)
782 {
783         memcpy(buf, traverse, sizeof(struct ctdb_traverse_start));
784 }
785
786 int ctdb_traverse_start_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
787                              struct ctdb_traverse_start **out)
788 {
789         struct ctdb_traverse_start *traverse;
790
791         if (buflen < sizeof(struct ctdb_traverse_start)) {
792                 return EMSGSIZE;
793         }
794
795         traverse = talloc_memdup(mem_ctx, buf,
796                                  sizeof(struct ctdb_traverse_start));
797         if (traverse == NULL) {
798                 return ENOMEM;
799         }
800
801         *out = traverse;
802         return 0;
803 }
804
805 size_t ctdb_traverse_all_len(struct ctdb_traverse_all *traverse)
806 {
807         return sizeof(struct ctdb_traverse_all);
808 }
809
810 void ctdb_traverse_all_push(struct ctdb_traverse_all *traverse, uint8_t *buf)
811 {
812         memcpy(buf, traverse, sizeof(struct ctdb_traverse_all));
813 }
814
815 int ctdb_traverse_all_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
816                            struct ctdb_traverse_all **out)
817 {
818         struct ctdb_traverse_all *traverse;
819
820         if (buflen < sizeof(struct ctdb_traverse_all)) {
821                 return EMSGSIZE;
822         }
823
824         traverse = talloc_memdup(mem_ctx, buf,
825                                  sizeof(struct ctdb_traverse_all));
826         if (traverse == NULL) {
827                 return ENOMEM;
828         }
829
830         *out = traverse;
831         return 0;
832 }
833
834 size_t ctdb_traverse_start_ext_len(struct ctdb_traverse_start_ext *traverse)
835 {
836         return sizeof(struct ctdb_traverse_start_ext);
837 }
838
839 void ctdb_traverse_start_ext_push(struct ctdb_traverse_start_ext *traverse,
840                                   uint8_t *buf)
841 {
842         memcpy(buf, traverse, sizeof(struct ctdb_traverse_start_ext));
843 }
844
845 int ctdb_traverse_start_ext_pull(uint8_t *buf, size_t buflen,
846                                  TALLOC_CTX *mem_ctx,
847                                  struct ctdb_traverse_start_ext **out)
848 {
849         struct ctdb_traverse_start_ext *traverse;
850
851         if (buflen < sizeof(struct ctdb_traverse_start_ext)) {
852                 return EMSGSIZE;
853         }
854
855         traverse = talloc_memdup(mem_ctx, buf,
856                                  sizeof(struct ctdb_traverse_start_ext));
857         if (traverse == NULL) {
858                 return ENOMEM;
859         }
860
861         *out = traverse;
862         return 0;
863 }
864
865 size_t ctdb_traverse_all_ext_len(struct ctdb_traverse_all_ext *traverse)
866 {
867         return sizeof(struct ctdb_traverse_all_ext);
868 }
869
870 void ctdb_traverse_all_ext_push(struct ctdb_traverse_all_ext *traverse,
871                                 uint8_t *buf)
872 {
873         memcpy(buf, traverse, sizeof(struct ctdb_traverse_all_ext));
874 }
875
876 int ctdb_traverse_all_ext_pull(uint8_t *buf, size_t buflen,
877                                TALLOC_CTX *mem_ctx,
878                                struct ctdb_traverse_all_ext **out)
879 {
880         struct ctdb_traverse_all_ext *traverse;
881
882         if (buflen < sizeof(struct ctdb_traverse_all_ext)) {
883                 return EMSGSIZE;
884         }
885
886         traverse = talloc_memdup(mem_ctx, buf,
887                                  sizeof(struct ctdb_traverse_all_ext));
888         if (traverse == NULL) {
889                 return ENOMEM;
890         }
891
892         *out = traverse;
893         return 0;
894 }
895
896 size_t ctdb_sock_addr_len(ctdb_sock_addr *addr)
897 {
898         return sizeof(ctdb_sock_addr);
899 }
900
901 void ctdb_sock_addr_push(ctdb_sock_addr *addr, uint8_t *buf)
902 {
903         memcpy(buf, addr, sizeof(ctdb_sock_addr));
904 }
905
906 static int ctdb_sock_addr_pull_elems(uint8_t *buf, size_t buflen,
907                                      TALLOC_CTX *mem_ctx, ctdb_sock_addr *out)
908 {
909         if (buflen < sizeof(ctdb_sock_addr)) {
910                 return EMSGSIZE;
911         }
912
913         memcpy(out, buf, sizeof(ctdb_sock_addr));
914
915         return 0;
916 }
917
918 int ctdb_sock_addr_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
919                         ctdb_sock_addr **out)
920 {
921         ctdb_sock_addr *addr;
922         int ret;
923
924         addr = talloc(mem_ctx, ctdb_sock_addr);
925         if (addr == NULL) {
926                 return false;
927         }
928
929         ret = ctdb_sock_addr_pull_elems(buf, buflen, addr, addr);
930         if (ret != 0) {
931                 TALLOC_FREE(addr);
932         }
933
934         *out = addr;
935         return ret;
936 }
937
938 size_t ctdb_connection_len(struct ctdb_connection *conn)
939 {
940         return sizeof(struct ctdb_connection);
941 }
942
943 void ctdb_connection_push(struct ctdb_connection *conn, uint8_t *buf)
944 {
945         memcpy(buf, conn, sizeof(struct ctdb_connection));
946 }
947
948 static int ctdb_connection_pull_elems(uint8_t *buf, size_t buflen,
949                                       TALLOC_CTX *mem_ctx,
950                                       struct ctdb_connection *out)
951 {
952         if (buflen < sizeof(struct ctdb_connection)) {
953                 return EMSGSIZE;
954         }
955
956         memcpy(out, buf, sizeof(struct ctdb_connection));
957
958         return 0;
959 }
960
961 int ctdb_connection_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
962                          struct ctdb_connection **out)
963 {
964         struct ctdb_connection *conn;
965         int ret;
966
967         conn = talloc(mem_ctx, struct ctdb_connection);
968         if (conn == NULL) {
969                 return ENOMEM;
970         }
971
972         ret = ctdb_connection_pull_elems(buf, buflen, conn, conn);
973         if (ret != 0) {
974                 TALLOC_FREE(conn);
975         }
976
977         *out = conn;
978         return ret;
979 }
980
981 struct ctdb_tunable_wire {
982         uint32_t value;
983         uint32_t length;
984         uint8_t name[1];
985 };
986
987 size_t ctdb_tunable_len(struct ctdb_tunable *tunable)
988 {
989         return offsetof(struct ctdb_tunable_wire, name) +
990                strlen(tunable->name) + 1;
991 }
992
993 void ctdb_tunable_push(struct ctdb_tunable *tunable, uint8_t *buf)
994 {
995         struct ctdb_tunable_wire *wire = (struct ctdb_tunable_wire *)buf;
996
997         wire->value = tunable->value;
998         wire->length = strlen(tunable->name) + 1;
999         memcpy(wire->name, tunable->name, wire->length);
1000 }
1001
1002 int ctdb_tunable_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1003                       struct ctdb_tunable **out)
1004 {
1005         struct ctdb_tunable *tunable;
1006         struct ctdb_tunable_wire *wire = (struct ctdb_tunable_wire *)buf;
1007
1008         if (buflen < offsetof(struct ctdb_tunable_wire, name)) {
1009                 return EMSGSIZE;
1010         }
1011         if (buflen < offsetof(struct ctdb_tunable_wire, name) + wire->length) {
1012                 return EMSGSIZE;
1013         }
1014
1015         tunable = talloc(mem_ctx, struct ctdb_tunable);
1016         if (tunable == NULL) {
1017                 return ENOMEM;
1018         }
1019
1020         tunable->value = wire->value;
1021         tunable->name = talloc_memdup(tunable, wire->name, wire->length);
1022         if (tunable->name == NULL) {
1023                 talloc_free(tunable);
1024                 return ENOMEM;
1025         }
1026
1027         *out = tunable;
1028         return 0;
1029 }
1030
1031 size_t ctdb_node_flag_change_len(struct ctdb_node_flag_change *flag_change)
1032 {
1033         return sizeof(struct ctdb_node_flag_change);
1034 }
1035
1036 void ctdb_node_flag_change_push(struct ctdb_node_flag_change *flag_change,
1037                                 uint8_t *buf)
1038 {
1039         memcpy(buf, flag_change, sizeof(struct ctdb_node_flag_change));
1040 }
1041
1042 int ctdb_node_flag_change_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1043                                struct ctdb_node_flag_change **out)
1044 {
1045         struct ctdb_node_flag_change *flag_change;
1046
1047         if (buflen < sizeof(struct ctdb_node_flag_change)) {
1048                 return EMSGSIZE;
1049         }
1050
1051         flag_change = talloc_memdup(mem_ctx, buf,
1052                                     sizeof(struct ctdb_node_flag_change));
1053         if (flag_change == NULL) {
1054                 return ENOMEM;
1055         }
1056
1057         *out = flag_change;
1058         return 0;
1059 }
1060
1061 struct ctdb_var_list_wire {
1062         uint32_t length;
1063         char list_str[1];
1064 };
1065
1066 size_t ctdb_var_list_len(struct ctdb_var_list *var_list)
1067 {
1068         int i;
1069         size_t len = sizeof(uint32_t);
1070
1071         for (i=0; i<var_list->count; i++) {
1072                 len += strlen(var_list->var[i]) + 1;
1073         }
1074         return len;
1075 }
1076
1077 void ctdb_var_list_push(struct ctdb_var_list *var_list, uint8_t *buf)
1078 {
1079         struct ctdb_var_list_wire *wire = (struct ctdb_var_list_wire *)buf;
1080         int i, n;
1081         size_t offset = 0;
1082
1083         if (var_list->count > 0) {
1084                 n = sprintf(wire->list_str, "%s", var_list->var[0]);
1085                 offset += n;
1086         }
1087         for (i=1; i<var_list->count; i++) {
1088                 n = sprintf(&wire->list_str[offset], ":%s", var_list->var[i]);
1089                 offset += n;
1090         }
1091         wire->length = offset + 1;
1092 }
1093
1094 int ctdb_var_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1095                        struct ctdb_var_list **out)
1096 {
1097         struct ctdb_var_list *var_list = NULL;
1098         struct ctdb_var_list_wire *wire = (struct ctdb_var_list_wire *)buf;
1099         char *str, *s, *tok, *ptr;
1100         const char **list;
1101
1102         if (buflen < sizeof(uint32_t)) {
1103                 return EMSGSIZE;
1104         }
1105         if (buflen < sizeof(uint32_t) + wire->length) {
1106                 return EMSGSIZE;
1107         }
1108
1109         str = talloc_strndup(mem_ctx, (char *)wire->list_str, wire->length);
1110         if (str == NULL) {
1111                 return ENOMEM;
1112         }
1113
1114         var_list = talloc_zero(mem_ctx, struct ctdb_var_list);
1115         if (var_list == NULL) {
1116                 goto fail;
1117         }
1118
1119         s = str;
1120         while ((tok = strtok_r(s, ":", &ptr)) != NULL) {
1121                 s = NULL;
1122                 list = talloc_realloc(var_list, var_list->var, const char *,
1123                                       var_list->count+1);
1124                 if (list == NULL) {
1125                         goto fail;
1126                 }
1127
1128                 var_list->var = list;
1129                 var_list->var[var_list->count] = talloc_strdup(var_list, tok);
1130                 if (var_list->var[var_list->count] == NULL) {
1131                         goto fail;
1132                 }
1133                 var_list->count++;
1134         }
1135
1136         talloc_free(str);
1137         *out = var_list;
1138         return 0;
1139
1140 fail:
1141         talloc_free(str);
1142         talloc_free(var_list);
1143         return ENOMEM;
1144 }
1145
1146 size_t ctdb_tunable_list_len(struct ctdb_tunable_list *tun_list)
1147 {
1148         return sizeof(struct ctdb_tunable_list);
1149 }
1150
1151 void ctdb_tunable_list_push(struct ctdb_tunable_list *tun_list, uint8_t *buf)
1152 {
1153         memcpy(buf, tun_list, sizeof(struct ctdb_tunable_list));
1154 }
1155
1156 int ctdb_tunable_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1157                            struct ctdb_tunable_list **out)
1158 {
1159         struct ctdb_tunable_list *tun_list;
1160
1161         if (buflen < sizeof(struct ctdb_tunable_list)) {
1162                 return EMSGSIZE;
1163         }
1164
1165         tun_list = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_tunable_list));
1166         if (tun_list == NULL) {
1167                 return ENOMEM;
1168         }
1169
1170         *out = tun_list;
1171         return 0;
1172 }
1173
1174 struct ctdb_tickle_list_wire {
1175         ctdb_sock_addr addr;
1176         uint32_t num;
1177         struct ctdb_connection conn[1];
1178 };
1179
1180 size_t ctdb_tickle_list_len(struct ctdb_tickle_list *tickles)
1181 {
1182         return offsetof(struct ctdb_tickle_list, conn) +
1183                tickles->num * sizeof(struct ctdb_connection);
1184 }
1185
1186 void ctdb_tickle_list_push(struct ctdb_tickle_list *tickles, uint8_t *buf)
1187 {
1188         struct ctdb_tickle_list_wire *wire =
1189                 (struct ctdb_tickle_list_wire *)buf;
1190         size_t offset;
1191         int i;
1192
1193         memcpy(&wire->addr, &tickles->addr, sizeof(ctdb_sock_addr));
1194         wire->num = tickles->num;
1195
1196         offset = offsetof(struct ctdb_tickle_list_wire, conn);
1197         for (i=0; i<tickles->num; i++) {
1198                 ctdb_connection_push(&tickles->conn[i], &buf[offset]);
1199                 offset += ctdb_connection_len(&tickles->conn[i]);
1200         }
1201 }
1202
1203 int ctdb_tickle_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1204                            struct ctdb_tickle_list **out)
1205 {
1206         struct ctdb_tickle_list *tickles;
1207         struct ctdb_tickle_list_wire *wire =
1208                 (struct ctdb_tickle_list_wire *)buf;
1209         size_t offset;
1210         int i, ret;
1211
1212         if (buflen < offsetof(struct ctdb_tickle_list_wire, conn)) {
1213                 return EMSGSIZE;
1214         }
1215         if (buflen < offsetof(struct ctdb_tickle_list_wire, conn) +
1216                      wire->num * sizeof(struct ctdb_connection)) {
1217                 return EMSGSIZE;
1218         }
1219
1220         tickles = talloc(mem_ctx, struct ctdb_tickle_list);
1221         if (tickles == NULL) {
1222                 return ENOMEM;
1223         }
1224
1225         offset = offsetof(struct ctdb_tickle_list, conn);
1226         memcpy(tickles, wire, offset);
1227
1228         tickles->conn = talloc_array(tickles, struct ctdb_connection,
1229                                      wire->num);
1230         if (tickles->conn == NULL) {
1231                 talloc_free(tickles);
1232                 return ENOMEM;
1233         }
1234
1235         for (i=0; i<wire->num; i++) {
1236                 ret = ctdb_connection_pull_elems(&buf[offset], buflen-offset,
1237                                                  tickles->conn,
1238                                                  &tickles->conn[i]);
1239                 if (ret != 0) {
1240                         talloc_free(tickles);
1241                         return ret;
1242                 }
1243                 offset += ctdb_connection_len(&tickles->conn[i]);
1244         }
1245
1246         *out = tickles;
1247         return 0;
1248 }
1249
1250 size_t ctdb_client_id_len(struct ctdb_client_id *cid)
1251 {
1252         return sizeof(struct ctdb_client_id);
1253 }
1254
1255 void ctdb_client_id_push(struct ctdb_client_id *cid, uint8_t *buf)
1256 {
1257         memcpy(buf, cid, sizeof(struct ctdb_client_id));
1258 }
1259
1260 static int ctdb_client_id_pull_elems(uint8_t *buf, size_t buflen,
1261                                      TALLOC_CTX *mem_ctx,
1262                                      struct ctdb_client_id *out)
1263 {
1264         if (buflen < sizeof(struct ctdb_client_id)) {
1265                 return EMSGSIZE;
1266         }
1267
1268         memcpy(out, buf, sizeof(struct ctdb_client_id));
1269
1270         return 0;
1271 }
1272
1273 int ctdb_client_id_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1274                         struct ctdb_client_id **out)
1275 {
1276         struct ctdb_client_id *cid;
1277         int ret;
1278
1279         cid = talloc(mem_ctx, struct ctdb_client_id);
1280         if (cid == NULL) {
1281                 return ENOMEM;
1282         }
1283
1284         ret = ctdb_client_id_pull_elems(buf, buflen, cid, cid);
1285         if (ret != 0) {
1286                 TALLOC_FREE(cid);
1287         }
1288
1289         *out = cid;
1290         return ret;
1291 }
1292
1293 struct ctdb_client_id_list_wire {
1294         uint32_t num;
1295         struct ctdb_client_id cid[1];
1296 };
1297
1298 size_t ctdb_client_id_list_len(struct ctdb_client_id_list *cid_list)
1299 {
1300         return sizeof(uint32_t) +
1301                cid_list->num * sizeof(struct ctdb_client_id);
1302 }
1303
1304 void ctdb_client_id_list_push(struct ctdb_client_id_list *cid_list,
1305                               uint8_t *buf)
1306 {
1307         struct ctdb_client_id_list_wire *wire =
1308                 (struct ctdb_client_id_list_wire *)buf;
1309         size_t offset;
1310         int i;
1311
1312         wire->num = cid_list->num;
1313
1314         offset = offsetof(struct ctdb_client_id_list_wire, cid);
1315         for (i=0; i<cid_list->num; i++) {
1316                 ctdb_client_id_push(&cid_list->cid[i], &buf[offset]);
1317                 offset += ctdb_client_id_len(&cid_list->cid[i]);
1318         }
1319 }
1320
1321 static int ctdb_client_id_list_pull_elems(uint8_t *buf, size_t buflen,
1322                                           TALLOC_CTX *mem_ctx,
1323                                           struct ctdb_client_id_list *out)
1324 {
1325         struct ctdb_client_id_list_wire *wire =
1326                 (struct ctdb_client_id_list_wire *)buf;
1327         size_t offset;
1328         int i;
1329
1330         if (buflen < sizeof(uint32_t)) {
1331                 return EMSGSIZE;
1332         }
1333         if (buflen < sizeof(uint32_t) +
1334                      wire->num * sizeof(struct ctdb_client_id)) {
1335                 return EMSGSIZE;
1336         }
1337
1338         out->num = wire->num;
1339         out->cid = talloc_array(mem_ctx, struct ctdb_client_id,
1340                                 wire->num);
1341         if (out->cid == NULL) {
1342                 return ENOMEM;
1343         }
1344
1345         offset = offsetof(struct ctdb_client_id_list_wire, cid);
1346         for (i=0; i<wire->num; i++) {
1347                 bool ret;
1348                 ret = ctdb_client_id_pull_elems(&buf[offset], buflen-offset,
1349                                                 out->cid, &out->cid[i]);
1350                 if (ret != 0) {
1351                         return ret;
1352                 }
1353                 offset += ctdb_client_id_len(&out->cid[i]);
1354         }
1355
1356         return 0;
1357 }
1358
1359 int ctdb_client_id_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1360                              struct ctdb_client_id_list **out)
1361 {
1362         struct ctdb_client_id_list *cid_list;
1363         int ret;
1364
1365         cid_list = talloc(mem_ctx, struct ctdb_client_id_list);
1366         if (cid_list == NULL) {
1367                 return ENOMEM;
1368         }
1369
1370         ret = ctdb_client_id_list_pull_elems(buf, buflen, cid_list, cid_list);
1371         if (ret != 0) {
1372                 TALLOC_FREE(cid_list);
1373         }
1374
1375         *out = cid_list;
1376         return ret;
1377 }
1378
1379 struct ctdb_client_id_map_wire {
1380         int count;
1381         struct ctdb_client_id_list list[1];
1382 };
1383
1384 size_t ctdb_client_id_map_len(struct ctdb_client_id_map *cid_map)
1385 {
1386         int i;
1387         size_t len;
1388
1389         len = sizeof(int);
1390         for (i=0; i<cid_map->count; i++) {
1391                 len += ctdb_client_id_list_len(&cid_map->list[i]);
1392         }
1393         return len;
1394 }
1395
1396 void ctdb_client_id_map_push(struct ctdb_client_id_map *cid_map, uint8_t *buf)
1397 {
1398         struct ctdb_client_id_map_wire *wire =
1399                 (struct ctdb_client_id_map_wire *)buf;
1400         size_t offset;
1401         int i;
1402
1403         wire->count = cid_map->count;
1404
1405         offset = sizeof(int);
1406         for (i=0; i<cid_map->count; i++) {
1407                 ctdb_client_id_list_push(&cid_map->list[i], &buf[offset]);
1408                 offset += ctdb_client_id_list_len(&cid_map->list[i]);
1409         }
1410 }
1411
1412 int ctdb_client_id_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1413                             struct ctdb_client_id_map **out)
1414 {
1415         struct ctdb_client_id_map *cid_map;
1416         struct ctdb_client_id_map_wire *wire =
1417                 (struct ctdb_client_id_map_wire *)buf;
1418         size_t offset;
1419         int i;
1420         bool ret;
1421
1422         if (buflen < sizeof(int)) {
1423                 return EMSGSIZE;
1424         }
1425         if (buflen < sizeof(int) +
1426                      wire->count * sizeof(struct ctdb_client_id_list)) {
1427                 return EMSGSIZE;
1428         }
1429
1430         cid_map = talloc(mem_ctx, struct ctdb_client_id_map);
1431         if (cid_map == NULL) {
1432                 return ENOMEM;
1433         }
1434
1435         cid_map->count = wire->count;
1436         cid_map->list = talloc_array(cid_map, struct ctdb_client_id_list,
1437                                      wire->count);
1438         if (cid_map->list == NULL) {
1439                 return ENOMEM;
1440         }
1441
1442         offset = sizeof(int);
1443         for (i=0; i<wire->count; i++) {
1444                 ret = ctdb_client_id_list_pull_elems(&buf[offset],
1445                                                      buflen-offset,
1446                                                      cid_map->list,
1447                                                      &cid_map->list[i]);
1448                 if (ret != 0) {
1449                         talloc_free(cid_map);
1450                         return ret;
1451                 }
1452                 offset += ctdb_client_id_list_len(&cid_map->list[i]);
1453         }
1454
1455         *out = cid_map;
1456         return 0;
1457 }
1458
1459 struct ctdb_addr_info_wire {
1460         ctdb_sock_addr addr;
1461         uint32_t mask;
1462         uint32_t len;
1463         char iface[1];
1464 };
1465
1466 size_t ctdb_addr_info_len(struct ctdb_addr_info *arp)
1467 {
1468         uint32_t len;
1469
1470         len = offsetof(struct ctdb_addr_info_wire, iface);
1471         if (arp->iface != NULL) {
1472                len += strlen(arp->iface)+1;
1473         }
1474
1475         return len;
1476 }
1477
1478 void ctdb_addr_info_push(struct ctdb_addr_info *addr_info, uint8_t *buf)
1479 {
1480         struct ctdb_addr_info_wire *wire = (struct ctdb_addr_info_wire *)buf;
1481
1482         wire->addr = addr_info->addr;
1483         wire->mask = addr_info->mask;
1484         if (addr_info->iface == NULL) {
1485                 wire->len = 0;
1486         } else {
1487                 wire->len = strlen(addr_info->iface)+1;
1488                 memcpy(wire->iface, addr_info->iface, wire->len);
1489         }
1490 }
1491
1492 int ctdb_addr_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1493                         struct ctdb_addr_info **out)
1494 {
1495         struct ctdb_addr_info *addr_info;
1496         struct ctdb_addr_info_wire *wire = (struct ctdb_addr_info_wire *)buf;
1497
1498         if (buflen < offsetof(struct ctdb_addr_info_wire, iface)) {
1499                 return EMSGSIZE;
1500         }
1501         if (buflen < offsetof(struct ctdb_addr_info_wire, iface) + wire->len) {
1502                 return EMSGSIZE;
1503         }
1504
1505         addr_info = talloc(mem_ctx, struct ctdb_addr_info);
1506         if (addr_info == NULL) {
1507                 return ENOMEM;
1508         }
1509
1510         addr_info->addr = wire->addr;
1511         addr_info->mask = wire->mask;
1512
1513         if (wire->len == 0) {
1514                 addr_info->iface = NULL;
1515         } else {
1516                 addr_info->iface = talloc_strndup(addr_info, wire->iface,
1517                                                   wire->len);
1518                 if (addr_info->iface == NULL) {
1519                         talloc_free(addr_info);
1520                         return ENOMEM;
1521                 }
1522         }
1523
1524         *out = addr_info;
1525         return 0;
1526 }
1527
1528 size_t ctdb_transdb_len(struct ctdb_transdb *transdb)
1529 {
1530         return sizeof(struct ctdb_transdb);
1531 }
1532
1533 void ctdb_transdb_push(struct ctdb_transdb *transdb, uint8_t *buf)
1534 {
1535         memcpy(buf, transdb, sizeof(struct ctdb_transdb));
1536 }
1537
1538 int ctdb_transdb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1539                      struct ctdb_transdb **out)
1540 {
1541         struct ctdb_transdb *transdb;
1542
1543         if (buflen < sizeof(struct ctdb_transdb)) {
1544                 return EMSGSIZE;
1545         }
1546
1547         transdb = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_transdb));
1548         if (transdb == NULL) {
1549                 return ENOMEM;
1550         }
1551
1552         *out = transdb;
1553         return 0;
1554 }
1555
1556 size_t ctdb_uptime_len(struct ctdb_uptime *uptime)
1557 {
1558         return sizeof(struct ctdb_uptime);
1559 }
1560
1561 void ctdb_uptime_push(struct ctdb_uptime *uptime, uint8_t *buf)
1562 {
1563         memcpy(buf, uptime, sizeof(struct ctdb_uptime));
1564 }
1565
1566 int ctdb_uptime_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1567                      struct ctdb_uptime **out)
1568 {
1569         struct ctdb_uptime *uptime;
1570
1571         if (buflen < sizeof(struct ctdb_uptime)) {
1572                 return EMSGSIZE;
1573         }
1574
1575         uptime = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_uptime));
1576         if (uptime == NULL) {
1577                 return ENOMEM;
1578         }
1579
1580         *out = uptime;
1581         return 0;
1582 }
1583
1584 size_t ctdb_public_ip_len(struct ctdb_public_ip *pubip)
1585 {
1586         return sizeof(struct ctdb_public_ip);
1587 }
1588
1589 void ctdb_public_ip_push(struct ctdb_public_ip *pubip, uint8_t *buf)
1590 {
1591         memcpy(buf, pubip, sizeof(struct ctdb_public_ip));
1592 }
1593
1594 static int ctdb_public_ip_pull_elems(uint8_t *buf, size_t buflen,
1595                                      TALLOC_CTX *mem_ctx,
1596                                      struct ctdb_public_ip *out)
1597 {
1598         if (buflen < sizeof(struct ctdb_public_ip)) {
1599                 return EMSGSIZE;
1600         }
1601
1602         memcpy(out, buf, sizeof(struct ctdb_public_ip));
1603
1604         return 0;
1605 }
1606
1607 int ctdb_public_ip_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1608                         struct ctdb_public_ip **out)
1609 {
1610         struct ctdb_public_ip *pubip;
1611         int ret;
1612
1613         pubip = talloc(mem_ctx, struct ctdb_public_ip);
1614         if (pubip == NULL) {
1615                 return ENOMEM;
1616         }
1617
1618         ret = ctdb_public_ip_pull_elems(buf, buflen, pubip, pubip);
1619         if (ret != 0) {
1620                 TALLOC_FREE(pubip);
1621         }
1622
1623         *out = pubip;
1624         return ret;
1625 }
1626
1627 struct ctdb_public_ip_list_wire {
1628         uint32_t num;
1629         struct ctdb_public_ip ip[1];
1630 };
1631
1632 size_t ctdb_public_ip_list_len(struct ctdb_public_ip_list *pubip_list)
1633 {
1634         int i;
1635         size_t len;
1636
1637         len = sizeof(uint32_t);
1638         for (i=0; i<pubip_list->num; i++) {
1639                 len += ctdb_public_ip_len(&pubip_list->ip[i]);
1640         }
1641         return len;
1642 }
1643
1644 void ctdb_public_ip_list_push(struct ctdb_public_ip_list *pubip_list,
1645                               uint8_t *buf)
1646 {
1647         struct ctdb_public_ip_list_wire *wire =
1648                 (struct ctdb_public_ip_list_wire *)buf;
1649         size_t offset;
1650         int i;
1651
1652         wire->num = pubip_list->num;
1653
1654         offset = offsetof(struct ctdb_public_ip_list_wire, ip);
1655         for (i=0; i<pubip_list->num; i++) {
1656                 ctdb_public_ip_push(&pubip_list->ip[i], &buf[offset]);
1657                 offset += ctdb_public_ip_len(&pubip_list->ip[i]);
1658         }
1659 }
1660
1661 int ctdb_public_ip_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1662                              struct ctdb_public_ip_list **out)
1663 {
1664         struct ctdb_public_ip_list *pubip_list;
1665         struct ctdb_public_ip_list_wire *wire =
1666                 (struct ctdb_public_ip_list_wire *)buf;
1667         size_t offset;
1668         int i;
1669         bool ret;
1670
1671         if (buflen < sizeof(uint32_t)) {
1672                 return EMSGSIZE;
1673         }
1674         if (buflen < sizeof(uint32_t) +
1675                      wire->num * sizeof(struct ctdb_public_ip)) {
1676                 return EMSGSIZE;
1677         }
1678
1679         pubip_list = talloc(mem_ctx, struct ctdb_public_ip_list);
1680         if (pubip_list == NULL) {
1681                 return ENOMEM;
1682         }
1683
1684         pubip_list->num = wire->num;
1685         if (wire->num == 0) {
1686                 pubip_list->ip = NULL;
1687                 *out = pubip_list;
1688                 return 0;
1689         }
1690         pubip_list->ip = talloc_array(pubip_list, struct ctdb_public_ip,
1691                                       wire->num);
1692         if (pubip_list->ip == NULL) {
1693                 talloc_free(pubip_list);
1694                 return ENOMEM;
1695         }
1696
1697         offset = offsetof(struct ctdb_public_ip_list_wire, ip);
1698         for (i=0; i<wire->num; i++) {
1699                 ret = ctdb_public_ip_pull_elems(&buf[offset], buflen-offset,
1700                                                 pubip_list->ip,
1701                                                 &pubip_list->ip[i]);
1702                 if (ret != 0) {
1703                         talloc_free(pubip_list);
1704                         return ret;
1705                 }
1706                 offset += ctdb_public_ip_len(&pubip_list->ip[i]);
1707         }
1708
1709         *out = pubip_list;
1710         return 0;
1711 }
1712
1713 size_t ctdb_node_and_flags_len(struct ctdb_node_and_flags *node)
1714 {
1715         return sizeof(struct ctdb_node_and_flags);
1716 }
1717
1718 void ctdb_node_and_flags_push(struct ctdb_node_and_flags *node, uint8_t *buf)
1719 {
1720         memcpy(buf, node, sizeof(struct ctdb_node_and_flags));
1721 }
1722
1723 static int ctdb_node_and_flags_pull_elems(TALLOC_CTX *mem_ctx,
1724                                           uint8_t *buf, size_t buflen,
1725                                           struct ctdb_node_and_flags *out)
1726 {
1727         if (buflen < sizeof(struct ctdb_node_and_flags)) {
1728                 return EMSGSIZE;
1729         }
1730
1731         memcpy(out, buf, sizeof(struct ctdb_node_and_flags));
1732
1733         return 0;
1734 }
1735
1736 int ctdb_node_and_flags_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1737                               struct ctdb_node_and_flags **out)
1738 {
1739         struct ctdb_node_and_flags *node;
1740         int ret;
1741
1742         node = talloc(mem_ctx, struct ctdb_node_and_flags);
1743         if (node == NULL) {
1744                 return ENOMEM;
1745         }
1746
1747         ret = ctdb_node_and_flags_pull_elems(node, buf, buflen, node);
1748         if (ret != 0) {
1749                 TALLOC_FREE(node);
1750         }
1751
1752         *out = node;
1753         return ret;
1754 }
1755
1756 struct ctdb_node_map_wire {
1757         uint32_t num;
1758         struct ctdb_node_and_flags node[1];
1759 };
1760
1761 size_t ctdb_node_map_len(struct ctdb_node_map *nodemap)
1762 {
1763         return sizeof(uint32_t) +
1764                nodemap->num * sizeof(struct ctdb_node_and_flags);
1765 }
1766
1767 void ctdb_node_map_push(struct ctdb_node_map *nodemap, uint8_t *buf)
1768 {
1769         struct ctdb_node_map_wire *wire = (struct ctdb_node_map_wire *)buf;
1770         size_t offset;
1771         int i;
1772
1773         wire->num = nodemap->num;
1774
1775         offset = offsetof(struct ctdb_node_map_wire, node);
1776         for (i=0; i<nodemap->num; i++) {
1777                 ctdb_node_and_flags_push(&nodemap->node[i], &buf[offset]);
1778                 offset += ctdb_node_and_flags_len(&nodemap->node[i]);
1779         }
1780 }
1781
1782 int ctdb_node_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1783                        struct ctdb_node_map **out)
1784 {
1785         struct ctdb_node_map *nodemap;
1786         struct ctdb_node_map_wire *wire = (struct ctdb_node_map_wire *)buf;
1787         size_t offset;
1788         int i;
1789         bool ret;
1790
1791         nodemap = talloc(mem_ctx, struct ctdb_node_map);
1792         if (nodemap == NULL) {
1793                 return ENOMEM;
1794         }
1795
1796         nodemap->num = wire->num;
1797         nodemap->node = talloc_array(nodemap, struct ctdb_node_and_flags,
1798                                      wire->num);
1799         if (nodemap->node == NULL) {
1800                 talloc_free(nodemap);
1801                 return ENOMEM;
1802         }
1803
1804         offset = offsetof(struct ctdb_node_map_wire, node);
1805         for (i=0; i<wire->num; i++) {
1806                 ret = ctdb_node_and_flags_pull_elems(nodemap->node,
1807                                                      &buf[offset],
1808                                                      buflen-offset,
1809                                                      &nodemap->node[i]);
1810                 if (ret != 0) {
1811                         talloc_free(nodemap);
1812                         return ret;
1813                 }
1814                 offset += ctdb_node_and_flags_len(&nodemap->node[i]);
1815         }
1816
1817         *out = nodemap;
1818         return 0;
1819 }
1820
1821 size_t ctdb_script_len(struct ctdb_script *script)
1822 {
1823         return sizeof(struct ctdb_script);
1824 }
1825
1826 void ctdb_script_push(struct ctdb_script *script, uint8_t *buf)
1827 {
1828         memcpy(buf, script, sizeof(struct ctdb_script));
1829 }
1830
1831 static int ctdb_script_pull_elems(uint8_t *buf, size_t buflen,
1832                                   TALLOC_CTX *mem_ctx,
1833                                   struct ctdb_script *out)
1834 {
1835         if (buflen < sizeof(struct ctdb_script)) {
1836                 return EMSGSIZE;
1837         }
1838
1839         memcpy(out, buf, sizeof(struct ctdb_script));
1840
1841         return 0;
1842 }
1843
1844 int ctdb_script_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1845                      struct ctdb_script **out)
1846 {
1847         struct ctdb_script *script;
1848         int ret;
1849
1850         script = talloc(mem_ctx, struct ctdb_script);
1851         if (script == NULL) {
1852                 return ENOMEM;
1853         }
1854
1855         ret = ctdb_script_pull_elems(buf, buflen, script, script);
1856         if (ret != 0) {
1857                 TALLOC_FREE(script);
1858         }
1859
1860         *out = script;
1861         return ret;
1862 }
1863
1864 struct ctdb_script_list_wire {
1865         uint32_t num_scripts;
1866         struct ctdb_script script[1];
1867 };
1868
1869 size_t ctdb_script_list_len(struct ctdb_script_list *script_list)
1870 {
1871         int i;
1872         size_t len;
1873
1874         if (script_list == NULL) {
1875                 return 0;
1876         }
1877
1878         len = offsetof(struct ctdb_script_list_wire, script);
1879         for (i=0; i<script_list->num_scripts; i++) {
1880                 len += ctdb_script_len(&script_list->script[i]);
1881         }
1882         return len;
1883 }
1884
1885 void ctdb_script_list_push(struct ctdb_script_list *script_list, uint8_t *buf)
1886 {
1887         struct ctdb_script_list_wire *wire =
1888                 (struct ctdb_script_list_wire *)buf;
1889         size_t offset;
1890         int i;
1891
1892         if (script_list == NULL) {
1893                 return;
1894         }
1895
1896         wire->num_scripts = script_list->num_scripts;
1897
1898         offset = offsetof(struct ctdb_script_list_wire, script);
1899         for (i=0; i<script_list->num_scripts; i++) {
1900                 ctdb_script_push(&script_list->script[i], &buf[offset]);
1901                 offset += ctdb_script_len(&script_list->script[i]);
1902         }
1903 }
1904
1905 int ctdb_script_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1906                           struct ctdb_script_list **out)
1907 {
1908         struct ctdb_script_list *script_list;
1909         struct ctdb_script_list_wire *wire =
1910                 (struct ctdb_script_list_wire *)buf;
1911         size_t offset;
1912         int i;
1913         bool ret;
1914
1915         /* If event scripts have never been run, the result will be NULL */
1916         if (buflen == 0) {
1917                 *out = NULL;
1918                 return 0;
1919         }
1920
1921         offset = offsetof(struct ctdb_script_list_wire, script);
1922
1923         if (buflen < offset) {
1924                 return EMSGSIZE;
1925         }
1926         if (buflen < offset + wire->num_scripts * sizeof(struct ctdb_script)) {
1927                 return EMSGSIZE;
1928         }
1929
1930         script_list = talloc(mem_ctx, struct ctdb_script_list);
1931         if (script_list == NULL) {
1932                 return ENOMEM;
1933
1934         }
1935
1936         script_list->num_scripts = wire->num_scripts;
1937         script_list->script = talloc_array(script_list, struct ctdb_script,
1938                                            wire->num_scripts);
1939         if (script_list->script == NULL) {
1940                 talloc_free(script_list);
1941                 return ENOMEM;
1942         }
1943
1944         for (i=0; i<wire->num_scripts; i++) {
1945                 ret = ctdb_script_pull_elems(&buf[offset], buflen-offset,
1946                                              script_list->script,
1947                                              &script_list->script[i]);
1948                 if (ret != 0) {
1949                         talloc_free(script_list);
1950                         return ret;
1951                 }
1952                 offset += ctdb_script_len(&script_list->script[i]);
1953         }
1954
1955         *out = script_list;
1956         return 0;
1957 }
1958
1959 size_t ctdb_ban_state_len(struct ctdb_ban_state *ban_state)
1960 {
1961         return sizeof(struct ctdb_ban_state);
1962 }
1963
1964 void ctdb_ban_state_push(struct ctdb_ban_state *ban_state, uint8_t *buf)
1965 {
1966         memcpy(buf, ban_state, sizeof(struct ctdb_ban_state));
1967 }
1968
1969 int ctdb_ban_state_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1970                         struct ctdb_ban_state **out)
1971 {
1972         struct ctdb_ban_state *ban_state;
1973
1974         if (buflen < sizeof(struct ctdb_ban_state)) {
1975                 return EMSGSIZE;
1976         }
1977
1978         ban_state = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_ban_state));
1979         if (ban_state == NULL) {
1980                 return ENOMEM;
1981         }
1982
1983         *out = ban_state;
1984         return 0;
1985 }
1986
1987 size_t ctdb_db_priority_len(struct ctdb_db_priority *db_prio)
1988 {
1989         return sizeof(struct ctdb_db_priority);
1990 }
1991
1992 void ctdb_db_priority_push(struct ctdb_db_priority *db_prio, uint8_t *buf)
1993 {
1994         memcpy(buf, db_prio, sizeof(struct ctdb_db_priority));
1995 }
1996
1997 int ctdb_db_priority_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1998                           struct ctdb_db_priority **out)
1999 {
2000         struct ctdb_db_priority *db_prio;
2001
2002         if (buflen < sizeof(struct ctdb_db_priority)) {
2003                 return EMSGSIZE;
2004         }
2005
2006         db_prio = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_db_priority));
2007         if (db_prio == NULL) {
2008                 return ENOMEM;
2009         }
2010
2011         *out = db_prio;
2012         return 0;
2013 }
2014
2015 struct ctdb_notify_data_wire {
2016         uint64_t srvid;
2017         uint32_t len;
2018         uint8_t data[1];
2019 };
2020
2021 size_t ctdb_notify_data_len(struct ctdb_notify_data *notify)
2022 {
2023         return offsetof(struct ctdb_notify_data_wire, data) +
2024                notify->data.dsize;
2025 }
2026
2027 void ctdb_notify_data_push(struct ctdb_notify_data *notify, uint8_t *buf)
2028 {
2029         struct ctdb_notify_data_wire *wire =
2030                 (struct ctdb_notify_data_wire *)buf;
2031
2032         wire->srvid = notify->srvid;
2033         wire->len = notify->data.dsize;
2034         memcpy(wire->data, notify->data.dptr, notify->data.dsize);
2035 }
2036
2037 int ctdb_notify_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2038                           struct ctdb_notify_data **out)
2039 {
2040         struct ctdb_notify_data *notify;
2041         struct ctdb_notify_data_wire *wire =
2042                 (struct ctdb_notify_data_wire *)buf;
2043
2044         if (buflen < offsetof(struct ctdb_notify_data_wire, data)) {
2045                 return EMSGSIZE;
2046         }
2047         if (buflen < offsetof(struct ctdb_notify_data_wire, data) + wire->len) {
2048                 return EMSGSIZE;
2049         }
2050
2051         notify = talloc(mem_ctx, struct ctdb_notify_data);
2052         if (notify == NULL) {
2053                 return ENOMEM;
2054         }
2055
2056         notify->srvid = wire->srvid;
2057         notify->data.dsize = wire->len;
2058         notify->data.dptr = talloc_memdup(notify, wire->data, wire->len);
2059         if (notify->data.dptr == NULL) {
2060                 talloc_free(notify);
2061                 return ENOMEM;
2062         }
2063
2064         *out = notify;
2065         return 0;
2066 }
2067
2068 size_t ctdb_iface_len(struct ctdb_iface *iface)
2069 {
2070         return sizeof(struct ctdb_iface);
2071 }
2072
2073 void ctdb_iface_push(struct ctdb_iface *iface, uint8_t *buf)
2074 {
2075         memcpy(buf, iface, sizeof(struct ctdb_iface));
2076 }
2077
2078 static int ctdb_iface_pull_elems(uint8_t *buf, size_t buflen,
2079                                  TALLOC_CTX *mem_ctx,
2080                                  struct ctdb_iface *out)
2081 {
2082         if (buflen < sizeof(struct ctdb_iface)) {
2083                 return EMSGSIZE;
2084         }
2085
2086         memcpy(out, buf, sizeof(struct ctdb_iface));
2087
2088         return 0;
2089 }
2090
2091 int ctdb_iface_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2092                     struct ctdb_iface **out)
2093 {
2094         struct ctdb_iface *iface;
2095         int ret;
2096
2097         iface = talloc(mem_ctx, struct ctdb_iface);
2098         if (iface == NULL) {
2099                 return ENOMEM;
2100         }
2101
2102         ret = ctdb_iface_pull_elems(buf, buflen, iface, iface);
2103         if (ret != 0) {
2104                 TALLOC_FREE(iface);
2105         }
2106
2107         *out = iface;
2108         return ret;
2109 }
2110
2111 struct ctdb_iface_list_wire {
2112         uint32_t num;
2113         struct ctdb_iface iface[1];
2114 };
2115
2116 size_t ctdb_iface_list_len(struct ctdb_iface_list *iface_list)
2117 {
2118         return sizeof(uint32_t) +
2119                iface_list->num * sizeof(struct ctdb_iface);
2120 }
2121
2122 void ctdb_iface_list_push(struct ctdb_iface_list *iface_list, uint8_t *buf)
2123 {
2124         struct ctdb_iface_list_wire *wire =
2125                 (struct ctdb_iface_list_wire *)buf;
2126
2127         wire->num = iface_list->num;
2128         memcpy(wire->iface, iface_list->iface,
2129                iface_list->num * sizeof(struct ctdb_iface));
2130 }
2131
2132 int ctdb_iface_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2133                          struct ctdb_iface_list **out)
2134 {
2135         struct ctdb_iface_list *iface_list;
2136         struct ctdb_iface_list_wire *wire =
2137                 (struct ctdb_iface_list_wire *)buf;
2138
2139         if (buflen < sizeof(uint32_t)) {
2140                 return EMSGSIZE;
2141         }
2142         if (buflen < sizeof(uint32_t) + wire->num * sizeof(struct ctdb_iface)) {
2143                 return EMSGSIZE;
2144         }
2145
2146         iface_list = talloc(mem_ctx, struct ctdb_iface_list);
2147         if (iface_list == NULL) {
2148                 return ENOMEM;
2149         }
2150
2151         iface_list->num = wire->num;
2152         iface_list->iface = talloc_array(iface_list, struct ctdb_iface,
2153                                          wire->num);
2154         if (iface_list->iface == NULL) {
2155                 talloc_free(iface_list);
2156                 return ENOMEM;
2157         }
2158
2159         memcpy(iface_list->iface, wire->iface,
2160                wire->num * sizeof(struct ctdb_iface));
2161
2162         *out = iface_list;
2163         return 0;
2164 }
2165
2166 struct ctdb_public_ip_info_wire {
2167         struct ctdb_public_ip ip;
2168         uint32_t active_idx;
2169         uint32_t num;
2170         struct ctdb_iface ifaces[1];
2171 };
2172
2173 size_t ctdb_public_ip_info_len(struct ctdb_public_ip_info *ipinfo)
2174 {
2175         return offsetof(struct ctdb_public_ip_info_wire, num) +
2176                ctdb_iface_list_len(ipinfo->ifaces);
2177 }
2178
2179 void ctdb_public_ip_info_push(struct ctdb_public_ip_info *ipinfo, uint8_t *buf)
2180 {
2181         struct ctdb_public_ip_info_wire *wire =
2182                 (struct ctdb_public_ip_info_wire *)buf;
2183         size_t offset;
2184
2185         offset = offsetof(struct ctdb_public_ip_info_wire, num);
2186         memcpy(wire, ipinfo, offset);
2187         wire->num = ipinfo->ifaces->num;
2188         memcpy(wire->ifaces, ipinfo->ifaces->iface,
2189                ipinfo->ifaces->num * sizeof(struct ctdb_iface));
2190 }
2191
2192 int ctdb_public_ip_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2193                              struct ctdb_public_ip_info **out)
2194 {
2195         struct ctdb_public_ip_info *ipinfo;
2196         struct ctdb_public_ip_info_wire *wire =
2197                 (struct ctdb_public_ip_info_wire *)buf;
2198
2199         if (buflen < offsetof(struct ctdb_public_ip_info_wire, ifaces)) {
2200                 return EMSGSIZE;
2201         }
2202
2203         ipinfo = talloc(mem_ctx, struct ctdb_public_ip_info);
2204         if (ipinfo == NULL) {
2205                 return ENOMEM;
2206         }
2207
2208         memcpy(ipinfo, wire, offsetof(struct ctdb_public_ip_info_wire, num));
2209
2210         ipinfo->ifaces = talloc(ipinfo, struct ctdb_iface_list);
2211         if (ipinfo->ifaces == NULL) {
2212                 talloc_free(ipinfo);
2213                 return ENOMEM;
2214         }
2215
2216         ipinfo->ifaces->num = wire->num;
2217         ipinfo->ifaces->iface = talloc_array(ipinfo->ifaces, struct ctdb_iface,
2218                                              wire->num);
2219         if (ipinfo->ifaces->iface == NULL) {
2220                 talloc_free(ipinfo);
2221                 return ENOMEM;
2222         }
2223
2224         memcpy(ipinfo->ifaces->iface, wire->ifaces,
2225                wire->num * sizeof(struct ctdb_iface));
2226
2227         *out = ipinfo;
2228         return 0;
2229 }
2230
2231 struct ctdb_key_data_wire {
2232         uint32_t db_id;
2233         struct ctdb_ltdb_header header;
2234         uint32_t keylen;
2235         uint8_t key[1];
2236 };
2237
2238 size_t ctdb_key_data_len(struct ctdb_key_data *key)
2239 {
2240         return offsetof(struct ctdb_key_data_wire, key) + key->key.dsize;
2241 }
2242
2243 void ctdb_key_data_push(struct ctdb_key_data *key, uint8_t *buf)
2244 {
2245         struct ctdb_key_data_wire *wire = (struct ctdb_key_data_wire *)buf;
2246
2247         memcpy(wire, key, offsetof(struct ctdb_key_data, key));
2248         wire->keylen = key->key.dsize;
2249         memcpy(wire->key, key->key.dptr, key->key.dsize);
2250 }
2251
2252 int ctdb_key_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2253                        struct ctdb_key_data **out)
2254 {
2255         struct ctdb_key_data *key_data;
2256         struct ctdb_key_data_wire *wire = (struct ctdb_key_data_wire *)buf;
2257
2258         if (buflen < offsetof(struct ctdb_key_data_wire, key)) {
2259                 return EMSGSIZE;
2260         }
2261         if (buflen < offsetof(struct ctdb_key_data_wire, key) + wire->keylen) {
2262                 return EMSGSIZE;
2263         }
2264
2265         key_data = talloc(mem_ctx, struct ctdb_key_data);
2266         if (key_data == NULL) {
2267                 return ENOMEM;
2268         }
2269
2270         memcpy(key_data, wire, offsetof(struct ctdb_key_data, key));
2271
2272         key_data->key.dsize = wire->keylen;
2273         key_data->key.dptr = talloc_memdup(key_data, wire->key, wire->keylen);
2274         if (key_data->key.dptr == NULL) {
2275                 talloc_free(key_data);
2276                 return ENOMEM;
2277         }
2278
2279         *out = key_data;
2280         return 0;
2281 }
2282
2283 struct ctdb_db_statistics_wire {
2284         struct ctdb_db_statistics dbstats;
2285         char hot_keys_wire[1];
2286 };
2287
2288 size_t ctdb_db_statistics_len(struct ctdb_db_statistics *dbstats)
2289 {
2290         size_t len;
2291         int i;
2292
2293         len = sizeof(struct ctdb_db_statistics);
2294         for (i=0; i<MAX_HOT_KEYS; i++) {
2295                 len += dbstats->hot_keys[i].key.dsize;
2296         }
2297         return len;
2298 }
2299
2300 void ctdb_db_statistics_push(struct ctdb_db_statistics *dbstats, void *buf)
2301 {
2302         struct ctdb_db_statistics_wire *wire =
2303                 (struct ctdb_db_statistics_wire *)buf;
2304         size_t offset;
2305         int i;
2306
2307         dbstats->num_hot_keys = MAX_HOT_KEYS;
2308         memcpy(wire, dbstats, sizeof(struct ctdb_db_statistics));
2309
2310         offset = 0;
2311         for (i=0; i<MAX_HOT_KEYS; i++) {
2312                 memcpy(&wire->hot_keys_wire[offset],
2313                        dbstats->hot_keys[i].key.dptr,
2314                        dbstats->hot_keys[i].key.dsize);
2315                 offset += dbstats->hot_keys[i].key.dsize;
2316         }
2317 }
2318
2319 int ctdb_db_statistics_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2320                             struct ctdb_db_statistics **out)
2321 {
2322         struct ctdb_db_statistics *dbstats;
2323         struct ctdb_db_statistics_wire *wire =
2324                 (struct ctdb_db_statistics_wire *)buf;
2325         size_t offset;
2326         int i;
2327
2328         if (buflen < sizeof(struct ctdb_db_statistics)) {
2329                 return EMSGSIZE;
2330         }
2331         offset = 0;
2332         for (i=0; i<wire->dbstats.num_hot_keys; i++) {
2333                 offset += wire->dbstats.hot_keys[i].key.dsize;
2334         }
2335         if (buflen < sizeof(struct ctdb_db_statistics) + offset) {
2336                 return EMSGSIZE;
2337         }
2338
2339         dbstats = talloc(mem_ctx, struct ctdb_db_statistics);
2340         if (dbstats == NULL) {
2341                 return ENOMEM;
2342         }
2343
2344         memcpy(dbstats, wire, sizeof(struct ctdb_db_statistics));
2345
2346         offset = 0;
2347         for (i=0; i<wire->dbstats.num_hot_keys; i++) {
2348                 uint8_t *ptr;
2349                 size_t key_size;
2350
2351                 key_size = dbstats->hot_keys[i].key.dsize;
2352                 ptr = talloc_memdup(mem_ctx, &wire->hot_keys_wire[offset],
2353                                     key_size);
2354                 if (ptr == NULL) {
2355                         talloc_free(dbstats);
2356                         return ENOMEM;
2357                 }
2358                 dbstats->hot_keys[i].key.dptr = ptr;
2359                 offset += key_size;
2360         }
2361
2362         *out = dbstats;
2363         return 0;
2364 }
2365
2366 size_t ctdb_election_message_len(struct ctdb_election_message *election)
2367 {
2368         return sizeof(struct ctdb_election_message);
2369 }
2370
2371 void ctdb_election_message_push(struct ctdb_election_message *election,
2372                                 uint8_t *buf)
2373 {
2374         memcpy(buf, election, sizeof(struct ctdb_election_message));
2375 }
2376
2377 int ctdb_election_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2378                                struct ctdb_election_message **out)
2379 {
2380         struct ctdb_election_message *election;
2381
2382         if (buflen < sizeof(struct ctdb_election_message)) {
2383                 return EMSGSIZE;
2384         }
2385
2386         election = talloc_memdup(mem_ctx, buf,
2387                                  sizeof(struct ctdb_election_message));
2388         if (election == NULL) {
2389                 return ENOMEM;
2390         }
2391
2392         *out = election;
2393         return 0;
2394 }
2395
2396 size_t ctdb_srvid_message_len(struct ctdb_srvid_message *msg)
2397 {
2398         return sizeof(struct ctdb_srvid_message);
2399 }
2400
2401 void ctdb_srvid_message_push(struct ctdb_srvid_message *msg, uint8_t *buf)
2402 {
2403         memcpy(buf, msg, sizeof(struct ctdb_srvid_message));
2404 }
2405
2406 int ctdb_srvid_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2407                             struct ctdb_srvid_message **out)
2408 {
2409         struct ctdb_srvid_message *msg;
2410
2411         if (buflen < sizeof(struct ctdb_srvid_message)) {
2412                 return EMSGSIZE;
2413         }
2414
2415         msg = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_srvid_message));
2416         if (msg == NULL) {
2417                 return ENOMEM;
2418         }
2419
2420         *out = msg;
2421         return 0;
2422 }
2423
2424 size_t ctdb_disable_message_len(struct ctdb_disable_message *disable)
2425 {
2426         return sizeof(struct ctdb_disable_message);
2427 }
2428
2429 void ctdb_disable_message_push(struct ctdb_disable_message *disable,
2430                                uint8_t *buf)
2431 {
2432         memcpy(buf, disable, sizeof(struct ctdb_disable_message));
2433 }
2434
2435 int ctdb_disable_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2436                               struct ctdb_disable_message **out)
2437 {
2438         struct ctdb_disable_message *disable;
2439
2440         if (buflen < sizeof(struct ctdb_disable_message)) {
2441                 return EMSGSIZE;
2442         }
2443
2444         disable = talloc_memdup(mem_ctx, buf,
2445                                 sizeof(struct ctdb_disable_message));
2446         if (disable == NULL) {
2447                 return ENOMEM;
2448         }
2449
2450         *out = disable;
2451         return 0;
2452 }
2453
2454 size_t ctdb_tdb_data_len(TDB_DATA data)
2455 {
2456         return data.dsize;
2457 }
2458
2459 void ctdb_tdb_data_push(TDB_DATA data, uint8_t *buf)
2460 {
2461         memcpy(buf, data.dptr, data.dsize);
2462 }
2463
2464 int ctdb_tdb_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2465                        TDB_DATA *out)
2466 {
2467         TDB_DATA data;
2468
2469         data.dsize = buflen;
2470         if (data.dsize > 0) {
2471                 data.dptr = talloc_memdup(mem_ctx, buf, buflen);
2472                 if (data.dptr == NULL) {
2473                         return ENOMEM;
2474                 }
2475         } else {
2476                 data.dptr = NULL;
2477         }
2478
2479         *out = data;
2480         return 0;
2481 }
2482
2483 size_t ctdb_server_id_len(struct ctdb_server_id *sid)
2484 {
2485         return sizeof(struct ctdb_server_id);
2486 }
2487
2488 void ctdb_server_id_push(struct ctdb_server_id *sid, uint8_t *buf)
2489 {
2490         memcpy(buf, sid, sizeof(struct ctdb_server_id));
2491 }
2492
2493 int ctdb_server_id_pull(uint8_t *buf, size_t buflen,
2494                         struct ctdb_server_id *sid)
2495 {
2496         if (buflen < sizeof(struct ctdb_server_id)) {
2497                 return EMSGSIZE;
2498         }
2499
2500         memcpy(sid, buf, sizeof(struct ctdb_server_id));
2501         return 0;
2502 }
2503
2504 size_t ctdb_g_lock_len(struct ctdb_g_lock *lock)
2505 {
2506         return sizeof(struct ctdb_g_lock);
2507 }
2508
2509 void ctdb_g_lock_push(struct ctdb_g_lock *lock, uint8_t *buf)
2510 {
2511         memcpy(buf, lock, sizeof(struct ctdb_g_lock));
2512 }
2513
2514 int ctdb_g_lock_pull(uint8_t *buf, size_t buflen, struct ctdb_g_lock *lock)
2515 {
2516         if (buflen < sizeof(struct ctdb_g_lock)) {
2517                 return EMSGSIZE;
2518         }
2519
2520         memcpy(lock, buf, sizeof(struct ctdb_g_lock));
2521         return 0;
2522 }
2523
2524 size_t ctdb_g_lock_list_len(struct ctdb_g_lock_list *lock_list)
2525 {
2526         return lock_list->num * sizeof(struct ctdb_g_lock);
2527 }
2528
2529 void ctdb_g_lock_list_push(struct ctdb_g_lock_list *lock_list, uint8_t *buf)
2530 {
2531         size_t offset = 0;
2532         int i;
2533
2534         for (i=0; i<lock_list->num; i++) {
2535                 ctdb_g_lock_push(&lock_list->lock[i], &buf[offset]);
2536                 offset += sizeof(struct ctdb_g_lock);
2537         }
2538 }
2539
2540 int ctdb_g_lock_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2541                           struct ctdb_g_lock_list **out)
2542 {
2543         struct ctdb_g_lock_list *lock_list;
2544         unsigned count;
2545         size_t offset;
2546         int ret, i;
2547
2548         lock_list = talloc_zero(mem_ctx, struct ctdb_g_lock_list);
2549         if (lock_list == NULL) {
2550                 return ENOMEM;
2551         }
2552
2553         count = buflen / sizeof(struct ctdb_g_lock);
2554         lock_list->lock = talloc_array(lock_list, struct ctdb_g_lock, count);
2555         if (lock_list->lock == NULL) {
2556                 talloc_free(lock_list);
2557                 return ENOMEM;
2558         }
2559
2560         offset = 0;
2561         for (i=0; i<count; i++) {
2562                 ret = ctdb_g_lock_pull(&buf[offset], buflen-offset,
2563                                        &lock_list->lock[i]);
2564                 if (ret != 0) {
2565                         talloc_free(lock_list);
2566                         return ret;
2567                 }
2568                 offset += sizeof(struct ctdb_g_lock);
2569         }
2570
2571         lock_list->num = count;
2572
2573         *out = lock_list;
2574         return 0;
2575 }