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