ctdb-protocol: Fix marshalling for ctdb_notify_data
[vlendec/samba-autobuild/.git] / ctdb / tests / src / protocol_types_compat_test.c
1 /*
2    protocol types backward compatibility test
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/filesys.h"
22
23 #include <assert.h>
24
25 #include "protocol/protocol_basic.c"
26 #include "protocol/protocol_types.c"
27
28 #include "tests/src/protocol_common.h"
29
30 #define COMPAT_TEST_FUNC(NAME)          test_ ##NAME## _compat
31 #define OLD_LEN_FUNC(NAME)              NAME## _len_old
32 #define OLD_PUSH_FUNC(NAME)             NAME## _push_old
33 #define OLD_PULL_FUNC(NAME)             NAME## _pull_old
34
35 #define COMPAT_TYPE1_TEST(TYPE, NAME)   \
36 static void COMPAT_TEST_FUNC(NAME)(void) \
37 { \
38         TALLOC_CTX *mem_ctx; \
39         uint8_t *buf1, *buf2; \
40         TYPE p = { 0 }, p1, p2; \
41         size_t buflen1, buflen2, np = 0; \
42         int ret; \
43 \
44         mem_ctx = talloc_new(NULL); \
45         assert(mem_ctx != NULL); \
46         FILL_FUNC(NAME)(&p); \
47         buflen1 = LEN_FUNC(NAME)(&p); \
48         buflen2 = OLD_LEN_FUNC(NAME)(&p); \
49         assert(buflen1 == buflen2); \
50         buf1 = talloc_zero_size(mem_ctx, buflen1); \
51         assert(buf1 != NULL); \
52         buf2 = talloc_zero_size(mem_ctx, buflen2); \
53         assert(buf2 != NULL); \
54         PUSH_FUNC(NAME)(&p, buf1, &np); \
55         OLD_PUSH_FUNC(NAME)(&p, buf2); \
56         assert(memcmp(buf1, buf2, buflen1) == 0); \
57         ret = PULL_FUNC(NAME)(buf1, buflen1, &p1, &np); \
58         assert(ret == 0); \
59         ret = OLD_PULL_FUNC(NAME)(buf2, buflen2, &p2); \
60         VERIFY_FUNC(NAME)(&p1, &p2); \
61         talloc_free(mem_ctx); \
62 }
63
64 #define COMPAT_TYPE3_TEST(TYPE, NAME)   \
65 static void COMPAT_TEST_FUNC(NAME)(void) \
66 { \
67         TALLOC_CTX *mem_ctx; \
68         uint8_t *buf1, *buf2; \
69         TYPE *p, *p1, *p2; \
70         size_t buflen1, buflen2, np = 0; \
71         int ret; \
72 \
73         mem_ctx = talloc_new(NULL); \
74         assert(mem_ctx != NULL); \
75         p = talloc_zero(mem_ctx, TYPE); \
76         assert(p != NULL); \
77         FILL_FUNC(NAME)(p, p); \
78         buflen1 = LEN_FUNC(NAME)(p); \
79         buflen2 = OLD_LEN_FUNC(NAME)(p); \
80         assert(buflen1 == buflen2); \
81         buf1 = talloc_zero_size(mem_ctx, buflen1); \
82         assert(buf1 != NULL); \
83         buf2 = talloc_zero_size(mem_ctx, buflen2); \
84         assert(buf2 != NULL); \
85         PUSH_FUNC(NAME)(p, buf1, &np); \
86         OLD_PUSH_FUNC(NAME)(p, buf2); \
87         assert(memcmp(buf1, buf2, buflen1) == 0); \
88         ret = PULL_FUNC(NAME)(buf1, buflen1, mem_ctx, &p1, &np); \
89         assert(ret == 0); \
90         ret = OLD_PULL_FUNC(NAME)(buf2, buflen2, mem_ctx, &p2); \
91         VERIFY_FUNC(NAME)(p1, p2); \
92         talloc_free(mem_ctx); \
93 }
94
95
96 static size_t ctdb_statistics_len_old(struct ctdb_statistics *in)
97 {
98         return sizeof(struct ctdb_statistics);
99 }
100
101 static void ctdb_statistics_push_old(struct ctdb_statistics *in, uint8_t *buf)
102 {
103         memcpy(buf, in, sizeof(struct ctdb_statistics));
104 }
105
106 static int ctdb_statistics_pull_old(uint8_t *buf, size_t buflen,
107                                     TALLOC_CTX *mem_ctx,
108                                     struct ctdb_statistics **out)
109 {
110         struct ctdb_statistics *val;
111
112         if (buflen < sizeof(struct ctdb_statistics)) {
113                 return EMSGSIZE;
114         }
115
116         val = talloc(mem_ctx, struct ctdb_statistics);
117         if (val == NULL) {
118                 return ENOMEM;
119         }
120
121         memcpy(val, buf, sizeof(struct ctdb_statistics));
122
123         *out = val;
124         return 0;
125 }
126
127 struct ctdb_vnn_map_wire {
128         uint32_t generation;
129         uint32_t size;
130         uint32_t map[1];
131 };
132
133 static size_t ctdb_vnn_map_len_old(struct ctdb_vnn_map *in)
134 {
135         return offsetof(struct ctdb_vnn_map, map) +
136                in->size * sizeof(uint32_t);
137 }
138
139 static void ctdb_vnn_map_push_old(struct ctdb_vnn_map *in, uint8_t *buf)
140 {
141         struct ctdb_vnn_map_wire *wire = (struct ctdb_vnn_map_wire *)buf;
142
143         memcpy(wire, in, offsetof(struct ctdb_vnn_map, map));
144         memcpy(wire->map, in->map, in->size * sizeof(uint32_t));
145 }
146
147 static int ctdb_vnn_map_pull_old(uint8_t *buf, size_t buflen,
148                                  TALLOC_CTX *mem_ctx,
149                                  struct ctdb_vnn_map **out)
150 {
151         struct ctdb_vnn_map *val;
152         struct ctdb_vnn_map_wire *wire = (struct ctdb_vnn_map_wire *)buf;
153
154         if (buflen < offsetof(struct ctdb_vnn_map_wire, map)) {
155                 return EMSGSIZE;
156         }
157         if (wire->size > buflen / sizeof(uint32_t)) {
158                 return EMSGSIZE;
159         }
160         if (offsetof(struct ctdb_vnn_map_wire, map) +
161             wire->size * sizeof(uint32_t) <
162             offsetof(struct ctdb_vnn_map_wire, map)) {
163                     return EMSGSIZE;
164         }
165         if (buflen < offsetof(struct ctdb_vnn_map_wire, map) +
166                      wire->size * sizeof(uint32_t)) {
167                 return EMSGSIZE;
168         }
169
170         val = talloc(mem_ctx, struct ctdb_vnn_map);
171         if (val == NULL) {
172                 return ENOMEM;
173         }
174
175         memcpy(val, wire, offsetof(struct ctdb_vnn_map, map));
176
177         val->map = talloc_memdup(val, wire->map,
178                                  wire->size * sizeof(uint32_t));
179         if (val->map == NULL) {
180                 talloc_free(val);
181                 return ENOMEM;
182         }
183
184         *out = val;
185         return 0;
186 }
187
188 struct ctdb_dbid_map_wire {
189         uint32_t num;
190         struct ctdb_dbid dbs[1];
191 };
192
193 static size_t ctdb_dbid_map_len_old(struct ctdb_dbid_map *in)
194 {
195         return sizeof(uint32_t) + in->num * sizeof(struct ctdb_dbid);
196 }
197
198 static void ctdb_dbid_map_push_old(struct ctdb_dbid_map *in, uint8_t *buf)
199 {
200         struct ctdb_dbid_map_wire *wire = (struct ctdb_dbid_map_wire *)buf;
201
202         wire->num = in->num;
203         memcpy(wire->dbs, in->dbs, in->num * sizeof(struct ctdb_dbid));
204 }
205
206 static int ctdb_dbid_map_pull_old(uint8_t *buf, size_t buflen,
207                                   TALLOC_CTX *mem_ctx,
208                                   struct ctdb_dbid_map **out)
209 {
210         struct ctdb_dbid_map *val;
211         struct ctdb_dbid_map_wire *wire = (struct ctdb_dbid_map_wire *)buf;
212
213         if (buflen < sizeof(uint32_t)) {
214                 return EMSGSIZE;
215         }
216         if (wire->num > buflen / sizeof(struct ctdb_dbid)) {
217                 return EMSGSIZE;
218         }
219         if (sizeof(uint32_t) + wire->num * sizeof(struct ctdb_dbid) <
220             sizeof(uint32_t)) {
221                 return EMSGSIZE;
222         }
223         if (buflen < sizeof(uint32_t) + wire->num * sizeof(struct ctdb_dbid)) {
224                 return EMSGSIZE;
225         }
226
227         val = talloc(mem_ctx, struct ctdb_dbid_map);
228         if (val == NULL) {
229                 return ENOMEM;
230         }
231
232         val->num = wire->num;
233
234         val->dbs = talloc_memdup(val, wire->dbs,
235                                  wire->num * sizeof(struct ctdb_dbid));
236         if (val->dbs == NULL) {
237                 talloc_free(val);
238                 return ENOMEM;
239         }
240
241         *out = val;
242         return 0;
243 }
244
245 static size_t ctdb_pulldb_len_old(struct ctdb_pulldb *in)
246 {
247         return sizeof(struct ctdb_pulldb);
248 }
249
250 static void ctdb_pulldb_push_old(struct ctdb_pulldb *in, uint8_t *buf)
251 {
252         memcpy(buf, in, sizeof(struct ctdb_pulldb));
253 }
254
255 static int ctdb_pulldb_pull_old(uint8_t *buf, size_t buflen,
256                                 TALLOC_CTX *mem_ctx, struct ctdb_pulldb **out)
257 {
258         struct ctdb_pulldb *val;
259
260         if (buflen < sizeof(struct ctdb_pulldb)) {
261                 return EMSGSIZE;
262         }
263
264         val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_pulldb));
265         if (val == NULL) {
266                 return ENOMEM;
267         }
268
269         *out = val;
270         return 0;
271 }
272
273 static size_t ctdb_pulldb_ext_len_old(struct ctdb_pulldb_ext *in)
274 {
275         return sizeof(struct ctdb_pulldb_ext);
276 }
277
278 static void ctdb_pulldb_ext_push_old(struct ctdb_pulldb_ext *in, uint8_t *buf)
279 {
280         memcpy(buf, in, sizeof(struct ctdb_pulldb_ext));
281 }
282
283 static int ctdb_pulldb_ext_pull_old(uint8_t *buf, size_t buflen,
284                                     TALLOC_CTX *mem_ctx,
285                                     struct ctdb_pulldb_ext **out)
286 {
287         struct ctdb_pulldb_ext *val;
288
289         if (buflen < sizeof(struct ctdb_pulldb_ext)) {
290                 return EMSGSIZE;
291         }
292
293         val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_pulldb_ext));
294         if (val == NULL) {
295                 return ENOMEM;
296         }
297
298         *out = val;
299         return 0;
300 }
301
302 static size_t ctdb_ltdb_header_len_old(struct ctdb_ltdb_header *in)
303 {
304         return sizeof(struct ctdb_ltdb_header);
305 }
306
307 static void ctdb_ltdb_header_push_old(struct ctdb_ltdb_header *in,
308                                       uint8_t *buf)
309 {
310         memcpy(buf, in, sizeof(struct ctdb_ltdb_header));
311 }
312
313 static int ctdb_ltdb_header_pull_old(uint8_t *buf, size_t buflen,
314                                      struct ctdb_ltdb_header *out)
315 {
316         if (buflen < sizeof(struct ctdb_ltdb_header)) {
317                 return EMSGSIZE;
318         }
319
320         memcpy(out, buf, sizeof(struct ctdb_ltdb_header));
321         return 0;
322 }
323
324 struct ctdb_rec_data_wire {
325         uint32_t length;
326         uint32_t reqid;
327         uint32_t keylen;
328         uint32_t datalen;
329         uint8_t data[1];
330 };
331
332 static size_t ctdb_rec_data_len_old(struct ctdb_rec_data *in)
333 {
334         return offsetof(struct ctdb_rec_data_wire, data) +
335                in->key.dsize + in->data.dsize +
336                (in->header == NULL ? 0 : sizeof(struct ctdb_ltdb_header));
337 }
338
339 static void ctdb_rec_data_push_old(struct ctdb_rec_data *in, uint8_t *buf)
340 {
341         struct ctdb_rec_data_wire *wire = (struct ctdb_rec_data_wire *)buf;
342         size_t offset;
343
344         wire->length = ctdb_rec_data_len(in);
345         wire->reqid = in->reqid;
346         wire->keylen = in->key.dsize;
347         wire->datalen = in->data.dsize;
348         if (in->header != NULL) {
349                 wire->datalen += sizeof(struct ctdb_ltdb_header);
350         }
351
352         memcpy(wire->data, in->key.dptr, in->key.dsize);
353         offset = in->key.dsize;
354         if (in->header != NULL) {
355                 memcpy(&wire->data[offset], in->header,
356                        sizeof(struct ctdb_ltdb_header));
357                 offset += sizeof(struct ctdb_ltdb_header);
358         }
359         if (in->data.dsize > 0) {
360                 memcpy(&wire->data[offset], in->data.dptr, in->data.dsize);
361         }
362 }
363
364 static int ctdb_rec_data_pull_data_old(uint8_t *buf, size_t buflen,
365                                        uint32_t *reqid,
366                                        struct ctdb_ltdb_header **header,
367                                        TDB_DATA *key, TDB_DATA *data,
368                                        size_t *reclen)
369 {
370         struct ctdb_rec_data_wire *wire = (struct ctdb_rec_data_wire *)buf;
371         size_t offset;
372
373         if (buflen < offsetof(struct ctdb_rec_data_wire, data)) {
374                 return EMSGSIZE;
375         }
376         if (wire->keylen > buflen || wire->datalen > buflen) {
377                 return EMSGSIZE;
378         }
379         if (offsetof(struct ctdb_rec_data_wire, data) + wire->keylen <
380             offsetof(struct ctdb_rec_data_wire, data)) {
381                 return EMSGSIZE;
382         }
383         if (offsetof(struct ctdb_rec_data_wire, data) +
384                 wire->keylen + wire->datalen <
385             offsetof(struct ctdb_rec_data_wire, data)) {
386                 return EMSGSIZE;
387         }
388         if (buflen < offsetof(struct ctdb_rec_data_wire, data) +
389                         wire->keylen + wire->datalen) {
390                 return EMSGSIZE;
391         }
392
393         *reqid = wire->reqid;
394
395         key->dsize = wire->keylen;
396         key->dptr = wire->data;
397         offset = wire->keylen;
398
399         /* Always set header to NULL.  If it is required, exact it using
400          * ctdb_rec_data_extract_header()
401          */
402         *header = NULL;
403
404         data->dsize = wire->datalen;
405         data->dptr = &wire->data[offset];
406
407         *reclen = offsetof(struct ctdb_rec_data_wire, data) +
408                         wire->keylen + wire->datalen;
409
410         return 0;
411 }
412
413 static int ctdb_rec_data_pull_elems_old(uint8_t *buf, size_t buflen,
414                                         TALLOC_CTX *mem_ctx,
415                                         struct ctdb_rec_data *out)
416 {
417         uint32_t reqid;
418         struct ctdb_ltdb_header *header;
419         TDB_DATA key, data;
420         size_t reclen;
421         int ret;
422
423         ret = ctdb_rec_data_pull_data_old(buf, buflen, &reqid, &header,
424                                           &key, &data, &reclen);
425         if (ret != 0) {
426                 return ret;
427         }
428
429         out->reqid = reqid;
430         out->header = NULL;
431
432         out->key.dsize = key.dsize;
433         if (key.dsize > 0) {
434                 out->key.dptr = talloc_memdup(mem_ctx, key.dptr, key.dsize);
435                 if (out->key.dptr == NULL) {
436                         return ENOMEM;
437                 }
438         }
439
440         out->data.dsize = data.dsize;
441         if (data.dsize > 0) {
442                 out->data.dptr = talloc_memdup(mem_ctx, data.dptr, data.dsize);
443                 if (out->data.dptr == NULL) {
444                         return ENOMEM;
445                 }
446         }
447
448         return 0;
449 }
450
451 static int ctdb_rec_data_pull_old(uint8_t *buf, size_t buflen,
452                                   TALLOC_CTX *mem_ctx,
453                                   struct ctdb_rec_data **out)
454 {
455         struct ctdb_rec_data *val;
456         int ret;
457
458         val = talloc(mem_ctx, struct ctdb_rec_data);
459         if (val == NULL) {
460                 return ENOMEM;
461         }
462
463         ret = ctdb_rec_data_pull_elems_old(buf, buflen, val, val);
464         if (ret != 0) {
465                 TALLOC_FREE(val);
466                 return ret;
467         }
468
469         *out = val;
470         return ret;
471 }
472
473 struct ctdb_rec_buffer_wire {
474         uint32_t db_id;
475         uint32_t count;
476         uint8_t data[1];
477 };
478
479 static size_t ctdb_rec_buffer_len_old(struct ctdb_rec_buffer *in)
480 {
481         return offsetof(struct ctdb_rec_buffer_wire, data) + in->buflen;
482 }
483
484 static void ctdb_rec_buffer_push_old(struct ctdb_rec_buffer *in, uint8_t *buf)
485 {
486         struct ctdb_rec_buffer_wire *wire = (struct ctdb_rec_buffer_wire *)buf;
487
488         wire->db_id = in->db_id;
489         wire->count = in->count;
490         if (in->buflen > 0) {
491                 memcpy(wire->data, in->buf, in->buflen);
492         }
493 }
494
495 static int ctdb_rec_buffer_pull_old(uint8_t *buf, size_t buflen,
496                                     TALLOC_CTX *mem_ctx,
497                                     struct ctdb_rec_buffer **out)
498 {
499         struct ctdb_rec_buffer *val;
500         struct ctdb_rec_buffer_wire *wire = (struct ctdb_rec_buffer_wire *)buf;
501         size_t offset;
502
503         if (buflen < offsetof(struct ctdb_rec_buffer_wire, data)) {
504                 return EMSGSIZE;
505         }
506
507         val = talloc(mem_ctx, struct ctdb_rec_buffer);
508         if (val == NULL) {
509                 return ENOMEM;
510         }
511
512         val->db_id = wire->db_id;
513         val->count = wire->count;
514
515         offset = offsetof(struct ctdb_rec_buffer_wire, data);
516         val->buflen = buflen - offset;
517         val->buf = talloc_memdup(val, wire->data, val->buflen);
518         if (val->buf == NULL) {
519                 talloc_free(val);
520                 return ENOMEM;
521         }
522
523         *out = val;
524         return 0;
525 }
526
527 static size_t ctdb_traverse_start_len_old(struct ctdb_traverse_start *in)
528 {
529         return sizeof(struct ctdb_traverse_start);
530 }
531
532 static void ctdb_traverse_start_push_old(struct ctdb_traverse_start *in,
533                                          uint8_t *buf)
534 {
535         memcpy(buf, in, sizeof(struct ctdb_traverse_start));
536 }
537
538 static int ctdb_traverse_start_pull_old(uint8_t *buf, size_t buflen,
539                                         TALLOC_CTX *mem_ctx,
540                                         struct ctdb_traverse_start **out)
541 {
542         struct ctdb_traverse_start *val;
543
544         if (buflen < sizeof(struct ctdb_traverse_start)) {
545                 return EMSGSIZE;
546         }
547
548         val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_traverse_start));
549         if (val == NULL) {
550                 return ENOMEM;
551         }
552
553         *out = val;
554         return 0;
555 }
556
557 static size_t ctdb_traverse_all_len_old(struct ctdb_traverse_all *in)
558 {
559         return sizeof(struct ctdb_traverse_all);
560 }
561
562 static void ctdb_traverse_all_push_old(struct ctdb_traverse_all *in,
563                                        uint8_t *buf)
564 {
565         memcpy(buf, in, sizeof(struct ctdb_traverse_all));
566 }
567
568 static int ctdb_traverse_all_pull_old(uint8_t *buf, size_t buflen,
569                                       TALLOC_CTX *mem_ctx,
570                                       struct ctdb_traverse_all **out)
571 {
572         struct ctdb_traverse_all *val;
573
574         if (buflen < sizeof(struct ctdb_traverse_all)) {
575                 return EMSGSIZE;
576         }
577
578         val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_traverse_all));
579         if (val == NULL) {
580                 return ENOMEM;
581         }
582
583         *out = val;
584         return 0;
585 }
586
587 static size_t ctdb_traverse_start_ext_len_old(
588                         struct ctdb_traverse_start_ext *in)
589 {
590         return sizeof(struct ctdb_traverse_start_ext);
591 }
592
593 static void ctdb_traverse_start_ext_push_old(
594                         struct ctdb_traverse_start_ext *in, uint8_t *buf)
595 {
596         memcpy(buf, in, sizeof(struct ctdb_traverse_start_ext));
597 }
598
599 static int ctdb_traverse_start_ext_pull_old(uint8_t *buf, size_t buflen,
600                                             TALLOC_CTX *mem_ctx,
601                                             struct ctdb_traverse_start_ext **out)
602 {
603         struct ctdb_traverse_start_ext *val;
604
605         if (buflen < sizeof(struct ctdb_traverse_start_ext)) {
606                 return EMSGSIZE;
607         }
608
609         val = talloc_memdup(mem_ctx, buf,
610                             sizeof(struct ctdb_traverse_start_ext));
611         if (val == NULL) {
612                 return ENOMEM;
613         }
614
615         *out = val;
616         return 0;
617 }
618
619 static size_t ctdb_traverse_all_ext_len_old(struct ctdb_traverse_all_ext *in)
620 {
621         return sizeof(struct ctdb_traverse_all_ext);
622 }
623
624 static void ctdb_traverse_all_ext_push_old(struct ctdb_traverse_all_ext *in,
625                                            uint8_t *buf)
626 {
627         memcpy(buf, in, sizeof(struct ctdb_traverse_all_ext));
628 }
629
630 static int ctdb_traverse_all_ext_pull_old(uint8_t *buf, size_t buflen,
631                                           TALLOC_CTX *mem_ctx,
632                                           struct ctdb_traverse_all_ext **out)
633 {
634         struct ctdb_traverse_all_ext *val;
635
636         if (buflen < sizeof(struct ctdb_traverse_all_ext)) {
637                 return EMSGSIZE;
638         }
639
640         val = talloc_memdup(mem_ctx, buf,
641                             sizeof(struct ctdb_traverse_all_ext));
642         if (val == NULL) {
643                 return ENOMEM;
644         }
645
646         *out = val;
647         return 0;
648 }
649
650 static size_t ctdb_sock_addr_len_old(ctdb_sock_addr *in)
651 {
652         return sizeof(ctdb_sock_addr);
653 }
654
655 static void ctdb_sock_addr_push_old(ctdb_sock_addr *in, uint8_t *buf)
656 {
657         memcpy(buf, in, sizeof(ctdb_sock_addr));
658 }
659
660 static int ctdb_sock_addr_pull_elems_old(uint8_t *buf, size_t buflen,
661                                          TALLOC_CTX *mem_ctx,
662                                          ctdb_sock_addr *out)
663 {
664         if (buflen < sizeof(ctdb_sock_addr)) {
665                 return EMSGSIZE;
666         }
667
668         memcpy(out, buf, sizeof(ctdb_sock_addr));
669
670         return 0;
671 }
672
673 static int ctdb_sock_addr_pull_old(uint8_t *buf, size_t buflen,
674                                    TALLOC_CTX *mem_ctx, ctdb_sock_addr **out)
675 {
676         ctdb_sock_addr *val;
677         int ret;
678
679         val = talloc(mem_ctx, ctdb_sock_addr);
680         if (val == NULL) {
681                 return ENOMEM;
682         }
683
684         ret = ctdb_sock_addr_pull_elems_old(buf, buflen, val, val);
685         if (ret != 0) {
686                 TALLOC_FREE(val);
687                 return ret;
688         }
689
690         *out = val;
691         return ret;
692 }
693
694 static size_t ctdb_connection_len_old(struct ctdb_connection *in)
695 {
696         return sizeof(struct ctdb_connection);
697 }
698
699 static void ctdb_connection_push_old(struct ctdb_connection *in, uint8_t *buf)
700 {
701         memcpy(buf, in, sizeof(struct ctdb_connection));
702 }
703
704 static int ctdb_connection_pull_elems_old(uint8_t *buf, size_t buflen,
705                                           TALLOC_CTX *mem_ctx,
706                                           struct ctdb_connection *out)
707 {
708         if (buflen < sizeof(struct ctdb_connection)) {
709                 return EMSGSIZE;
710         }
711
712         memcpy(out, buf, sizeof(struct ctdb_connection));
713
714         return 0;
715 }
716
717 static int ctdb_connection_pull_old(uint8_t *buf, size_t buflen,
718                                     TALLOC_CTX *mem_ctx,
719                                     struct ctdb_connection **out)
720 {
721         struct ctdb_connection *val;
722         int ret;
723
724         val = talloc(mem_ctx, struct ctdb_connection);
725         if (val == NULL) {
726                 return ENOMEM;
727         }
728
729         ret = ctdb_connection_pull_elems_old(buf, buflen, val, val);
730         if (ret != 0) {
731                 TALLOC_FREE(val);
732                 return ret;
733         }
734
735         *out = val;
736         return ret;
737 }
738
739 struct ctdb_tunable_wire {
740         uint32_t value;
741         uint32_t length;
742         uint8_t name[1];
743 };
744
745 static size_t ctdb_tunable_len_old(struct ctdb_tunable *in)
746 {
747         return offsetof(struct ctdb_tunable_wire, name) +
748                strlen(in->name) + 1;
749 }
750
751 static void ctdb_tunable_push_old(struct ctdb_tunable *in, uint8_t *buf)
752 {
753         struct ctdb_tunable_wire *wire = (struct ctdb_tunable_wire *)buf;
754
755         wire->value = in->value;
756         wire->length = strlen(in->name) + 1;
757         memcpy(wire->name, in->name, wire->length);
758 }
759
760 static int ctdb_tunable_pull_old(uint8_t *buf, size_t buflen,
761                                  TALLOC_CTX *mem_ctx,
762                                  struct ctdb_tunable **out)
763 {
764         struct ctdb_tunable *val;
765         struct ctdb_tunable_wire *wire = (struct ctdb_tunable_wire *)buf;
766
767         if (buflen < offsetof(struct ctdb_tunable_wire, name)) {
768                 return EMSGSIZE;
769         }
770         if (wire->length > buflen) {
771                 return EMSGSIZE;
772         }
773         if (offsetof(struct ctdb_tunable_wire, name) + wire->length <
774             offsetof(struct ctdb_tunable_wire, name)) {
775                 return EMSGSIZE;
776         }
777         if (buflen < offsetof(struct ctdb_tunable_wire, name) + wire->length) {
778                 return EMSGSIZE;
779         }
780
781         val = talloc(mem_ctx, struct ctdb_tunable);
782         if (val == NULL) {
783                 return ENOMEM;
784         }
785
786         val->value = wire->value;
787         val->name = talloc_memdup(val, wire->name, wire->length);
788         if (val->name == NULL) {
789                 talloc_free(val);
790                 return ENOMEM;
791         }
792
793         *out = val;
794         return 0;
795 }
796
797 static size_t ctdb_node_flag_change_len_old(struct ctdb_node_flag_change *in)
798 {
799         return sizeof(struct ctdb_node_flag_change);
800 }
801
802 static void ctdb_node_flag_change_push_old(struct ctdb_node_flag_change *in,
803                                            uint8_t *buf)
804 {
805         memcpy(buf, in, sizeof(struct ctdb_node_flag_change));
806 }
807
808 static int ctdb_node_flag_change_pull_old(uint8_t *buf, size_t buflen,
809                                           TALLOC_CTX *mem_ctx,
810                                           struct ctdb_node_flag_change **out)
811 {
812         struct ctdb_node_flag_change *val;
813
814         if (buflen < sizeof(struct ctdb_node_flag_change)) {
815                 return EMSGSIZE;
816         }
817
818         val = talloc_memdup(mem_ctx, buf,
819                             sizeof(struct ctdb_node_flag_change));
820         if (val == NULL) {
821                 return ENOMEM;
822         }
823
824         *out = val;
825         return 0;
826 }
827
828 struct ctdb_var_list_wire {
829         uint32_t length;
830         char list_str[1];
831 };
832
833 static size_t ctdb_var_list_len_old(struct ctdb_var_list *in)
834 {
835         int i;
836         size_t len = sizeof(uint32_t);
837
838         for (i=0; i<in->count; i++) {
839                 len += strlen(in->var[i]) + 1;
840         }
841         return len;
842 }
843
844 static void ctdb_var_list_push_old(struct ctdb_var_list *in, uint8_t *buf)
845 {
846         struct ctdb_var_list_wire *wire = (struct ctdb_var_list_wire *)buf;
847         int i, n;
848         size_t offset = 0;
849
850         if (in->count > 0) {
851                 n = sprintf(wire->list_str, "%s", in->var[0]);
852                 offset += n;
853         }
854         for (i=1; i<in->count; i++) {
855                 n = sprintf(&wire->list_str[offset], ":%s", in->var[i]);
856                 offset += n;
857         }
858         wire->length = offset + 1;
859 }
860
861 static int ctdb_var_list_pull_old(uint8_t *buf, size_t buflen,
862                                   TALLOC_CTX *mem_ctx,
863                                   struct ctdb_var_list **out)
864 {
865         struct ctdb_var_list *val = NULL;
866         struct ctdb_var_list_wire *wire = (struct ctdb_var_list_wire *)buf;
867         char *str, *s, *tok, *ptr;
868         const char **list;
869
870         if (buflen < sizeof(uint32_t)) {
871                 return EMSGSIZE;
872         }
873         if (wire->length > buflen) {
874                 return EMSGSIZE;
875         }
876         if (sizeof(uint32_t) + wire->length < sizeof(uint32_t)) {
877                 return EMSGSIZE;
878         }
879         if (buflen < sizeof(uint32_t) + wire->length) {
880                 return EMSGSIZE;
881         }
882
883         str = talloc_strndup(mem_ctx, (char *)wire->list_str, wire->length);
884         if (str == NULL) {
885                 return ENOMEM;
886         }
887
888         val = talloc_zero(mem_ctx, struct ctdb_var_list);
889         if (val == NULL) {
890                 goto fail;
891         }
892
893         s = str;
894         while ((tok = strtok_r(s, ":", &ptr)) != NULL) {
895                 s = NULL;
896                 list = talloc_realloc(val, val->var, const char *,
897                                       val->count+1);
898                 if (list == NULL) {
899                         goto fail;
900                 }
901
902                 val->var = list;
903                 val->var[val->count] = talloc_strdup(val, tok);
904                 if (val->var[val->count] == NULL) {
905                         goto fail;
906                 }
907                 val->count++;
908         }
909
910         talloc_free(str);
911         *out = val;
912         return 0;
913
914 fail:
915         talloc_free(str);
916         talloc_free(val);
917         return ENOMEM;
918 }
919
920 static size_t ctdb_tunable_list_len_old(struct ctdb_tunable_list *in)
921 {
922         return sizeof(struct ctdb_tunable_list);
923 }
924
925 static void ctdb_tunable_list_push_old(struct ctdb_tunable_list *in,
926                                        uint8_t *buf)
927 {
928         memcpy(buf, in, sizeof(struct ctdb_tunable_list));
929 }
930
931 static int ctdb_tunable_list_pull_old(uint8_t *buf, size_t buflen,
932                                       TALLOC_CTX *mem_ctx,
933                                       struct ctdb_tunable_list **out)
934 {
935         struct ctdb_tunable_list *val;
936
937         if (buflen < sizeof(struct ctdb_tunable_list)) {
938                 return EMSGSIZE;
939         }
940
941         val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_tunable_list));
942         if (val == NULL) {
943                 return ENOMEM;
944         }
945
946         *out = val;
947         return 0;
948 }
949
950 struct ctdb_tickle_list_wire {
951         ctdb_sock_addr addr;
952         uint32_t num;
953         struct ctdb_connection conn[1];
954 };
955
956 static size_t ctdb_tickle_list_len_old(struct ctdb_tickle_list *in)
957 {
958         return offsetof(struct ctdb_tickle_list, conn) +
959                in->num * sizeof(struct ctdb_connection);
960 }
961
962 static void ctdb_tickle_list_push_old(struct ctdb_tickle_list *in,
963                                       uint8_t *buf)
964 {
965         struct ctdb_tickle_list_wire *wire =
966                 (struct ctdb_tickle_list_wire *)buf;
967         size_t offset;
968         int i;
969
970         memcpy(&wire->addr, &in->addr, sizeof(ctdb_sock_addr));
971         wire->num = in->num;
972
973         offset = offsetof(struct ctdb_tickle_list_wire, conn);
974         for (i=0; i<in->num; i++) {
975                 ctdb_connection_push_old(&in->conn[i], &buf[offset]);
976                 offset += ctdb_connection_len_old(&in->conn[i]);
977         }
978 }
979
980 static int ctdb_tickle_list_pull_old(uint8_t *buf, size_t buflen,
981                                      TALLOC_CTX *mem_ctx,
982                                      struct ctdb_tickle_list **out)
983 {
984         struct ctdb_tickle_list *val;
985         struct ctdb_tickle_list_wire *wire =
986                 (struct ctdb_tickle_list_wire *)buf;
987         size_t offset;
988         int i, ret;
989
990         if (buflen < offsetof(struct ctdb_tickle_list_wire, conn)) {
991                 return EMSGSIZE;
992         }
993         if (wire->num > buflen / sizeof(struct ctdb_connection)) {
994                 return EMSGSIZE;
995         }
996         if (offsetof(struct ctdb_tickle_list_wire, conn) +
997             wire->num * sizeof(struct ctdb_connection) <
998             offsetof(struct ctdb_tickle_list_wire, conn)) {
999                 return EMSGSIZE;
1000         }
1001         if (buflen < offsetof(struct ctdb_tickle_list_wire, conn) +
1002                      wire->num * sizeof(struct ctdb_connection)) {
1003                 return EMSGSIZE;
1004         }
1005
1006         val = talloc(mem_ctx, struct ctdb_tickle_list);
1007         if (val == NULL) {
1008                 return ENOMEM;
1009         }
1010
1011         offset = offsetof(struct ctdb_tickle_list, conn);
1012         memcpy(val, wire, offset);
1013
1014         val->conn = talloc_array(val, struct ctdb_connection, wire->num);
1015         if (val->conn == NULL) {
1016                 talloc_free(val);
1017                 return ENOMEM;
1018         }
1019
1020         for (i=0; i<wire->num; i++) {
1021                 ret = ctdb_connection_pull_elems_old(&buf[offset],
1022                                                      buflen-offset,
1023                                                      val->conn,
1024                                                      &val->conn[i]);
1025                 if (ret != 0) {
1026                         talloc_free(val);
1027                         return ret;
1028                 }
1029                 offset += ctdb_connection_len_old(&val->conn[i]);
1030         }
1031
1032         *out = val;
1033         return 0;
1034 }
1035
1036 struct ctdb_addr_info_wire {
1037         ctdb_sock_addr addr;
1038         uint32_t mask;
1039         uint32_t len;
1040         char iface[1];
1041 };
1042
1043 static size_t ctdb_addr_info_len_old(struct ctdb_addr_info *in)
1044 {
1045         uint32_t len;
1046
1047         len = offsetof(struct ctdb_addr_info_wire, iface);
1048         if (in->iface != NULL) {
1049                len += strlen(in->iface)+1;
1050         }
1051
1052         return len;
1053 }
1054
1055 static void ctdb_addr_info_push_old(struct ctdb_addr_info *in, uint8_t *buf)
1056 {
1057         struct ctdb_addr_info_wire *wire = (struct ctdb_addr_info_wire *)buf;
1058
1059         wire->addr = in->addr;
1060         wire->mask = in->mask;
1061         if (in->iface == NULL) {
1062                 wire->len = 0;
1063         } else {
1064                 wire->len = strlen(in->iface)+1;
1065                 memcpy(wire->iface, in->iface, wire->len);
1066         }
1067 }
1068
1069 static int ctdb_addr_info_pull_old(uint8_t *buf, size_t buflen,
1070                                    TALLOC_CTX *mem_ctx,
1071                                    struct ctdb_addr_info **out)
1072 {
1073         struct ctdb_addr_info *val;
1074         struct ctdb_addr_info_wire *wire = (struct ctdb_addr_info_wire *)buf;
1075
1076         if (buflen < offsetof(struct ctdb_addr_info_wire, iface)) {
1077                 return EMSGSIZE;
1078         }
1079         if (wire->len > buflen) {
1080                 return EMSGSIZE;
1081         }
1082         if (offsetof(struct ctdb_addr_info_wire, iface) + wire->len <
1083             offsetof(struct ctdb_addr_info_wire, iface)) {
1084                 return EMSGSIZE;
1085         }
1086         if (buflen < offsetof(struct ctdb_addr_info_wire, iface) + wire->len) {
1087                 return EMSGSIZE;
1088         }
1089
1090         val = talloc(mem_ctx, struct ctdb_addr_info);
1091         if (val == NULL) {
1092                 return ENOMEM;
1093         }
1094
1095         val->addr = wire->addr;
1096         val->mask = wire->mask;
1097
1098         if (wire->len == 0) {
1099                 val->iface = NULL;
1100         } else {
1101                 val->iface = talloc_strndup(val, wire->iface, wire->len);
1102                 if (val->iface == NULL) {
1103                         talloc_free(val);
1104                         return ENOMEM;
1105                 }
1106         }
1107
1108         *out = val;
1109         return 0;
1110 }
1111
1112 static size_t ctdb_transdb_len_old(struct ctdb_transdb *in)
1113 {
1114         return sizeof(struct ctdb_transdb);
1115 }
1116
1117 static void ctdb_transdb_push_old(struct ctdb_transdb *in, uint8_t *buf)
1118 {
1119         memcpy(buf, in, sizeof(struct ctdb_transdb));
1120 }
1121
1122 static int ctdb_transdb_pull_old(uint8_t *buf, size_t buflen,
1123                                  TALLOC_CTX *mem_ctx,
1124                                  struct ctdb_transdb **out)
1125 {
1126         struct ctdb_transdb *val;
1127
1128         if (buflen < sizeof(struct ctdb_transdb)) {
1129                 return EMSGSIZE;
1130         }
1131
1132         val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_transdb));
1133         if (val == NULL) {
1134                 return ENOMEM;
1135         }
1136
1137         *out = val;
1138         return 0;
1139 }
1140
1141 static size_t ctdb_uptime_len_old(struct ctdb_uptime *in)
1142 {
1143         return sizeof(struct ctdb_uptime);
1144 }
1145
1146 static void ctdb_uptime_push_old(struct ctdb_uptime *in, uint8_t *buf)
1147 {
1148         memcpy(buf, in, sizeof(struct ctdb_uptime));
1149 }
1150
1151 static int ctdb_uptime_pull_old(uint8_t *buf, size_t buflen,
1152                                 TALLOC_CTX *mem_ctx, struct ctdb_uptime **out)
1153 {
1154         struct ctdb_uptime *val;
1155
1156         if (buflen < sizeof(struct ctdb_uptime)) {
1157                 return EMSGSIZE;
1158         }
1159
1160         val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_uptime));
1161         if (val == NULL) {
1162                 return ENOMEM;
1163         }
1164
1165         *out = val;
1166         return 0;
1167 }
1168
1169 static size_t ctdb_public_ip_len_old(struct ctdb_public_ip *in)
1170 {
1171         return sizeof(struct ctdb_public_ip);
1172 }
1173
1174 static void ctdb_public_ip_push_old(struct ctdb_public_ip *in, uint8_t *buf)
1175 {
1176         memcpy(buf, in, sizeof(struct ctdb_public_ip));
1177 }
1178
1179 static int ctdb_public_ip_pull_elems_old(uint8_t *buf, size_t buflen,
1180                                          TALLOC_CTX *mem_ctx,
1181                                          struct ctdb_public_ip *out)
1182 {
1183         if (buflen < sizeof(struct ctdb_public_ip)) {
1184                 return EMSGSIZE;
1185         }
1186
1187         memcpy(out, buf, sizeof(struct ctdb_public_ip));
1188
1189         return 0;
1190 }
1191
1192 static int ctdb_public_ip_pull_old(uint8_t *buf, size_t buflen,
1193                                    TALLOC_CTX *mem_ctx,
1194                                    struct ctdb_public_ip **out)
1195 {
1196         struct ctdb_public_ip *val;
1197         int ret;
1198
1199         val = talloc(mem_ctx, struct ctdb_public_ip);
1200         if (val == NULL) {
1201                 return ENOMEM;
1202         }
1203
1204         ret = ctdb_public_ip_pull_elems_old(buf, buflen, val, val);
1205         if (ret != 0) {
1206                 TALLOC_FREE(val);
1207                 return ret;
1208         }
1209
1210         *out = val;
1211         return ret;
1212 }
1213
1214 struct ctdb_public_ip_list_wire {
1215         uint32_t num;
1216         struct ctdb_public_ip ip[1];
1217 };
1218
1219 static size_t ctdb_public_ip_list_len_old(struct ctdb_public_ip_list *in)
1220 {
1221         int i;
1222         size_t len;
1223
1224         len = sizeof(uint32_t);
1225         for (i=0; i<in->num; i++) {
1226                 len += ctdb_public_ip_len_old(&in->ip[i]);
1227         }
1228         return len;
1229 }
1230
1231 static void ctdb_public_ip_list_push_old(struct ctdb_public_ip_list *in,
1232                                          uint8_t *buf)
1233 {
1234         struct ctdb_public_ip_list_wire *wire =
1235                 (struct ctdb_public_ip_list_wire *)buf;
1236         size_t offset;
1237         int i;
1238
1239         wire->num = in->num;
1240
1241         offset = offsetof(struct ctdb_public_ip_list_wire, ip);
1242         for (i=0; i<in->num; i++) {
1243                 ctdb_public_ip_push_old(&in->ip[i], &buf[offset]);
1244                 offset += ctdb_public_ip_len_old(&in->ip[i]);
1245         }
1246 }
1247
1248 static int ctdb_public_ip_list_pull_old(uint8_t *buf, size_t buflen,
1249                                         TALLOC_CTX *mem_ctx,
1250                                         struct ctdb_public_ip_list **out)
1251 {
1252         struct ctdb_public_ip_list *val;
1253         struct ctdb_public_ip_list_wire *wire =
1254                 (struct ctdb_public_ip_list_wire *)buf;
1255         size_t offset;
1256         int i;
1257         bool ret;
1258
1259         if (buflen < sizeof(uint32_t)) {
1260                 return EMSGSIZE;
1261         }
1262         if (wire->num > buflen / sizeof(struct ctdb_public_ip)) {
1263                 return EMSGSIZE;
1264         }
1265         if (sizeof(uint32_t) + wire->num * sizeof(struct ctdb_public_ip) <
1266             sizeof(uint32_t)) {
1267                 return EMSGSIZE;
1268         }
1269         if (buflen < sizeof(uint32_t) +
1270                      wire->num * sizeof(struct ctdb_public_ip)) {
1271                 return EMSGSIZE;
1272         }
1273
1274         val = talloc(mem_ctx, struct ctdb_public_ip_list);
1275         if (val == NULL) {
1276                 return ENOMEM;
1277         }
1278
1279         val->num = wire->num;
1280         if (wire->num == 0) {
1281                 val->ip = NULL;
1282                 *out = val;
1283                 return 0;
1284         }
1285         val->ip = talloc_array(val, struct ctdb_public_ip, wire->num);
1286         if (val->ip == NULL) {
1287                 talloc_free(val);
1288                 return ENOMEM;
1289         }
1290
1291         offset = offsetof(struct ctdb_public_ip_list_wire, ip);
1292         for (i=0; i<wire->num; i++) {
1293                 ret = ctdb_public_ip_pull_elems_old(&buf[offset],
1294                                                     buflen-offset,
1295                                                     val->ip,
1296                                                     &val->ip[i]);
1297                 if (ret != 0) {
1298                         talloc_free(val);
1299                         return ret;
1300                 }
1301                 offset += ctdb_public_ip_len_old(&val->ip[i]);
1302         }
1303
1304         *out = val;
1305         return 0;
1306 }
1307
1308 static size_t ctdb_node_and_flags_len_old(struct ctdb_node_and_flags *in)
1309 {
1310         return sizeof(struct ctdb_node_and_flags);
1311 }
1312
1313 static void ctdb_node_and_flags_push_old(struct ctdb_node_and_flags *in,
1314                                          uint8_t *buf)
1315 {
1316         memcpy(buf, in, sizeof(struct ctdb_node_and_flags));
1317 }
1318
1319 static int ctdb_node_and_flags_pull_elems_old(TALLOC_CTX *mem_ctx,
1320                                               uint8_t *buf, size_t buflen,
1321                                               struct ctdb_node_and_flags *out)
1322 {
1323         if (buflen < sizeof(struct ctdb_node_and_flags)) {
1324                 return EMSGSIZE;
1325         }
1326
1327         memcpy(out, buf, sizeof(struct ctdb_node_and_flags));
1328
1329         return 0;
1330 }
1331
1332 static int ctdb_node_and_flags_pull_old(uint8_t *buf, size_t buflen,
1333                                         TALLOC_CTX *mem_ctx,
1334                                         struct ctdb_node_and_flags **out)
1335 {
1336         struct ctdb_node_and_flags *val;
1337         int ret;
1338
1339         val = talloc(mem_ctx, struct ctdb_node_and_flags);
1340         if (val == NULL) {
1341                 return ENOMEM;
1342         }
1343
1344         ret = ctdb_node_and_flags_pull_elems_old(val, buf, buflen, val);
1345         if (ret != 0) {
1346                 TALLOC_FREE(val);
1347                 return ret;
1348         }
1349
1350         *out = val;
1351         return ret;
1352 }
1353
1354 struct ctdb_node_map_wire {
1355         uint32_t num;
1356         struct ctdb_node_and_flags node[1];
1357 };
1358
1359 static size_t ctdb_node_map_len_old(struct ctdb_node_map *in)
1360 {
1361         return sizeof(uint32_t) +
1362                in->num * sizeof(struct ctdb_node_and_flags);
1363 }
1364
1365 static void ctdb_node_map_push_old(struct ctdb_node_map *in, uint8_t *buf)
1366 {
1367         struct ctdb_node_map_wire *wire = (struct ctdb_node_map_wire *)buf;
1368         size_t offset;
1369         int i;
1370
1371         wire->num = in->num;
1372
1373         offset = offsetof(struct ctdb_node_map_wire, node);
1374         for (i=0; i<in->num; i++) {
1375                 ctdb_node_and_flags_push_old(&in->node[i], &buf[offset]);
1376                 offset += ctdb_node_and_flags_len_old(&in->node[i]);
1377         }
1378 }
1379
1380 static int ctdb_node_map_pull_old(uint8_t *buf, size_t buflen,
1381                                   TALLOC_CTX *mem_ctx,
1382                                   struct ctdb_node_map **out)
1383 {
1384         struct ctdb_node_map *val;
1385         struct ctdb_node_map_wire *wire = (struct ctdb_node_map_wire *)buf;
1386         size_t offset;
1387         int i;
1388         bool ret;
1389
1390         if (buflen < sizeof(uint32_t)) {
1391                 return EMSGSIZE;
1392         }
1393         if (wire->num > buflen / sizeof(struct ctdb_node_and_flags)) {
1394                 return EMSGSIZE;
1395         }
1396         if (sizeof(uint32_t) + wire->num * sizeof(struct ctdb_node_and_flags) <
1397             sizeof(uint32_t)) {
1398                 return EMSGSIZE;
1399         }
1400         if (buflen < sizeof(uint32_t) +
1401                      wire->num * sizeof(struct ctdb_node_and_flags)) {
1402                 return EMSGSIZE;
1403         }
1404
1405         val = talloc(mem_ctx, struct ctdb_node_map);
1406         if (val == NULL) {
1407                 return ENOMEM;
1408         }
1409
1410         val->num = wire->num;
1411         val->node = talloc_array(val, struct ctdb_node_and_flags, wire->num);
1412         if (val->node == NULL) {
1413                 talloc_free(val);
1414                 return ENOMEM;
1415         }
1416
1417         offset = offsetof(struct ctdb_node_map_wire, node);
1418         for (i=0; i<wire->num; i++) {
1419                 ret = ctdb_node_and_flags_pull_elems_old(val->node,
1420                                                          &buf[offset],
1421                                                          buflen-offset,
1422                                                          &val->node[i]);
1423                 if (ret != 0) {
1424                         talloc_free(val);
1425                         return ret;
1426                 }
1427                 offset += ctdb_node_and_flags_len_old(&val->node[i]);
1428         }
1429
1430         *out = val;
1431         return 0;
1432 }
1433
1434 static size_t ctdb_script_len_old(struct ctdb_script *in)
1435 {
1436         return sizeof(struct ctdb_script);
1437 }
1438
1439 static void ctdb_script_push_old(struct ctdb_script *in, uint8_t *buf)
1440 {
1441         memcpy(buf, in, sizeof(struct ctdb_script));
1442 }
1443
1444 static int ctdb_script_pull_elems_old(uint8_t *buf, size_t buflen,
1445                                       TALLOC_CTX *mem_ctx,
1446                                       struct ctdb_script *out)
1447 {
1448         if (buflen < sizeof(struct ctdb_script)) {
1449                 return EMSGSIZE;
1450         }
1451
1452         memcpy(out, buf, sizeof(struct ctdb_script));
1453
1454         return 0;
1455 }
1456
1457 static int ctdb_script_pull_old(uint8_t *buf, size_t buflen,
1458                                 TALLOC_CTX *mem_ctx, struct ctdb_script **out)
1459 {
1460         struct ctdb_script *val;
1461         int ret;
1462
1463         val = talloc(mem_ctx, struct ctdb_script);
1464         if (val == NULL) {
1465                 return ENOMEM;
1466         }
1467
1468         ret = ctdb_script_pull_elems_old(buf, buflen, val, val);
1469         if (ret != 0) {
1470                 TALLOC_FREE(val);
1471                 return ret;
1472         }
1473
1474         *out = val;
1475         return ret;
1476 }
1477
1478 struct ctdb_script_list_wire {
1479         uint32_t num_scripts;
1480         struct ctdb_script script[1];
1481 };
1482
1483 static size_t ctdb_script_list_len_old(struct ctdb_script_list *in)
1484 {
1485         int i;
1486         size_t len;
1487
1488         if (in == NULL) {
1489                 return 0;
1490         }
1491
1492         len = offsetof(struct ctdb_script_list_wire, script);
1493         for (i=0; i<in->num_scripts; i++) {
1494                 len += ctdb_script_len_old(&in->script[i]);
1495         }
1496         return len;
1497 }
1498
1499 static void ctdb_script_list_push_old(struct ctdb_script_list *in,
1500                                       uint8_t *buf)
1501 {
1502         struct ctdb_script_list_wire *wire =
1503                 (struct ctdb_script_list_wire *)buf;
1504         size_t offset;
1505         int i;
1506
1507         if (in == NULL) {
1508                 return;
1509         }
1510
1511         wire->num_scripts = in->num_scripts;
1512
1513         offset = offsetof(struct ctdb_script_list_wire, script);
1514         for (i=0; i<in->num_scripts; i++) {
1515                 ctdb_script_push_old(&in->script[i], &buf[offset]);
1516                 offset += ctdb_script_len_old(&in->script[i]);
1517         }
1518 }
1519
1520 static int ctdb_script_list_pull_old(uint8_t *buf, size_t buflen,
1521                                      TALLOC_CTX *mem_ctx,
1522                                      struct ctdb_script_list **out)
1523 {
1524         struct ctdb_script_list *val;
1525         struct ctdb_script_list_wire *wire =
1526                 (struct ctdb_script_list_wire *)buf;
1527         size_t offset;
1528         int i;
1529         bool ret;
1530
1531         /* If event scripts have never been run, the result will be NULL */
1532         if (buflen == 0) {
1533                 *out = NULL;
1534                 return 0;
1535         }
1536
1537         offset = offsetof(struct ctdb_script_list_wire, script);
1538
1539         if (buflen < offset) {
1540                 return EMSGSIZE;
1541         }
1542         if (wire->num_scripts > buflen / sizeof(struct ctdb_script)) {
1543                 return EMSGSIZE;
1544         }
1545         if (offset + wire->num_scripts * sizeof(struct ctdb_script) < offset) {
1546                 return EMSGSIZE;
1547         }
1548         if (buflen < offset + wire->num_scripts * sizeof(struct ctdb_script)) {
1549                 return EMSGSIZE;
1550         }
1551
1552         val = talloc(mem_ctx, struct ctdb_script_list);
1553         if (val == NULL) {
1554                 return ENOMEM;
1555
1556         }
1557
1558         val->num_scripts = wire->num_scripts;
1559         val->script = talloc_array(val, struct ctdb_script, wire->num_scripts);
1560         if (val->script == NULL) {
1561                 talloc_free(val);
1562                 return ENOMEM;
1563         }
1564
1565         for (i=0; i<wire->num_scripts; i++) {
1566                 ret = ctdb_script_pull_elems_old(&buf[offset], buflen-offset,
1567                                                  val->script,
1568                                                  &val->script[i]);
1569                 if (ret != 0) {
1570                         talloc_free(val);
1571                         return ret;
1572                 }
1573                 offset += ctdb_script_len_old(&val->script[i]);
1574         }
1575
1576         *out = val;
1577         return 0;
1578 }
1579
1580 static size_t ctdb_ban_state_len_old(struct ctdb_ban_state *in)
1581 {
1582         return sizeof(struct ctdb_ban_state);
1583 }
1584
1585 static void ctdb_ban_state_push_old(struct ctdb_ban_state *in, uint8_t *buf)
1586 {
1587         memcpy(buf, in, sizeof(struct ctdb_ban_state));
1588 }
1589
1590 static int ctdb_ban_state_pull_old(uint8_t *buf, size_t buflen,
1591                                    TALLOC_CTX *mem_ctx,
1592                                    struct ctdb_ban_state **out)
1593 {
1594         struct ctdb_ban_state *val;
1595
1596         if (buflen < sizeof(struct ctdb_ban_state)) {
1597                 return EMSGSIZE;
1598         }
1599
1600         val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_ban_state));
1601         if (val == NULL) {
1602                 return ENOMEM;
1603         }
1604
1605         *out = val;
1606         return 0;
1607 }
1608
1609 struct ctdb_notify_data_wire {
1610         uint64_t srvid;
1611         uint32_t len;
1612         uint8_t data[1];
1613 };
1614
1615 static size_t ctdb_notify_data_len_old(struct ctdb_notify_data *in)
1616 {
1617         return offsetof(struct ctdb_notify_data_wire, data) +
1618                in->data.dsize;
1619 }
1620
1621 static void ctdb_notify_data_push_old(struct ctdb_notify_data *in,
1622                                       uint8_t *buf)
1623 {
1624         struct ctdb_notify_data_wire *wire =
1625                 (struct ctdb_notify_data_wire *)buf;
1626
1627         wire->srvid = in->srvid;
1628         wire->len = in->data.dsize;
1629         memcpy(wire->data, in->data.dptr, in->data.dsize);
1630 }
1631
1632 static int ctdb_notify_data_pull_old(uint8_t *buf, size_t buflen,
1633                                      TALLOC_CTX *mem_ctx,
1634                                      struct ctdb_notify_data **out)
1635 {
1636         struct ctdb_notify_data *val;
1637         struct ctdb_notify_data_wire *wire =
1638                 (struct ctdb_notify_data_wire *)buf;
1639
1640         if (buflen < offsetof(struct ctdb_notify_data_wire, data)) {
1641                 return EMSGSIZE;
1642         }
1643         if (wire->len > buflen) {
1644                 return EMSGSIZE;
1645         }
1646         if (offsetof(struct ctdb_notify_data_wire, data) + wire->len <
1647             offsetof(struct ctdb_notify_data_wire, data)) {
1648                 return EMSGSIZE;
1649         }
1650         if (buflen < offsetof(struct ctdb_notify_data_wire, data) + wire->len) {
1651                 return EMSGSIZE;
1652         }
1653
1654         val = talloc(mem_ctx, struct ctdb_notify_data);
1655         if (val == NULL) {
1656                 return ENOMEM;
1657         }
1658
1659         val->srvid = wire->srvid;
1660         val->data.dsize = wire->len;
1661         val->data.dptr = talloc_memdup(val, wire->data, wire->len);
1662         if (val->data.dptr == NULL) {
1663                 talloc_free(val);
1664                 return ENOMEM;
1665         }
1666
1667         *out = val;
1668         return 0;
1669 }
1670
1671
1672 COMPAT_TYPE3_TEST(struct ctdb_statistics, ctdb_statistics);
1673 COMPAT_TYPE3_TEST(struct ctdb_vnn_map, ctdb_vnn_map);
1674 COMPAT_TYPE3_TEST(struct ctdb_dbid_map, ctdb_dbid_map);
1675 COMPAT_TYPE3_TEST(struct ctdb_pulldb, ctdb_pulldb);
1676 COMPAT_TYPE3_TEST(struct ctdb_pulldb_ext, ctdb_pulldb_ext);
1677
1678 COMPAT_TYPE1_TEST(struct ctdb_ltdb_header, ctdb_ltdb_header);
1679
1680 COMPAT_TYPE3_TEST(struct ctdb_rec_data, ctdb_rec_data);
1681 COMPAT_TYPE3_TEST(struct ctdb_rec_buffer, ctdb_rec_buffer);
1682 COMPAT_TYPE3_TEST(struct ctdb_traverse_start, ctdb_traverse_start);
1683 COMPAT_TYPE3_TEST(struct ctdb_traverse_all, ctdb_traverse_all);
1684 COMPAT_TYPE3_TEST(struct ctdb_traverse_start_ext, ctdb_traverse_start_ext);
1685 COMPAT_TYPE3_TEST(struct ctdb_traverse_all_ext, ctdb_traverse_all_ext);
1686 COMPAT_TYPE3_TEST(ctdb_sock_addr, ctdb_sock_addr);
1687 COMPAT_TYPE3_TEST(struct ctdb_connection, ctdb_connection);
1688 COMPAT_TYPE3_TEST(struct ctdb_tunable, ctdb_tunable);
1689 COMPAT_TYPE3_TEST(struct ctdb_node_flag_change, ctdb_node_flag_change);
1690 COMPAT_TYPE3_TEST(struct ctdb_var_list, ctdb_var_list);
1691 COMPAT_TYPE3_TEST(struct ctdb_tunable_list, ctdb_tunable_list);
1692 COMPAT_TYPE3_TEST(struct ctdb_tickle_list, ctdb_tickle_list);
1693 COMPAT_TYPE3_TEST(struct ctdb_addr_info, ctdb_addr_info);
1694 COMPAT_TYPE3_TEST(struct ctdb_transdb, ctdb_transdb);
1695 COMPAT_TYPE3_TEST(struct ctdb_uptime, ctdb_uptime);
1696 COMPAT_TYPE3_TEST(struct ctdb_public_ip, ctdb_public_ip);
1697 COMPAT_TYPE3_TEST(struct ctdb_public_ip_list, ctdb_public_ip_list);
1698 COMPAT_TYPE3_TEST(struct ctdb_node_and_flags, ctdb_node_and_flags);
1699 COMPAT_TYPE3_TEST(struct ctdb_node_map, ctdb_node_map);
1700 COMPAT_TYPE3_TEST(struct ctdb_script, ctdb_script);
1701 COMPAT_TYPE3_TEST(struct ctdb_script_list, ctdb_script_list);
1702 COMPAT_TYPE3_TEST(struct ctdb_ban_state, ctdb_ban_state);
1703 COMPAT_TYPE3_TEST(struct ctdb_notify_data, ctdb_notify_data);
1704
1705 int main(int argc, char *argv[])
1706 {
1707         if (argc == 2) {
1708                 int seed = atoi(argv[1]);
1709                 srandom(seed);
1710         }
1711
1712         COMPAT_TEST_FUNC(ctdb_statistics)();
1713         COMPAT_TEST_FUNC(ctdb_vnn_map)();
1714         COMPAT_TEST_FUNC(ctdb_dbid_map)();
1715         COMPAT_TEST_FUNC(ctdb_pulldb)();
1716         COMPAT_TEST_FUNC(ctdb_pulldb_ext)();
1717         COMPAT_TEST_FUNC(ctdb_ltdb_header)();
1718         COMPAT_TEST_FUNC(ctdb_rec_data)();
1719         COMPAT_TEST_FUNC(ctdb_rec_buffer)();
1720         COMPAT_TEST_FUNC(ctdb_traverse_start)();
1721         COMPAT_TEST_FUNC(ctdb_traverse_all)();
1722         COMPAT_TEST_FUNC(ctdb_traverse_start_ext)();
1723         COMPAT_TEST_FUNC(ctdb_traverse_all_ext)();
1724         COMPAT_TEST_FUNC(ctdb_sock_addr)();
1725         COMPAT_TEST_FUNC(ctdb_connection)();
1726         COMPAT_TEST_FUNC(ctdb_tunable)();
1727         COMPAT_TEST_FUNC(ctdb_node_flag_change)();
1728         COMPAT_TEST_FUNC(ctdb_var_list)();
1729         COMPAT_TEST_FUNC(ctdb_tunable_list)();
1730         COMPAT_TEST_FUNC(ctdb_tickle_list)();
1731         COMPAT_TEST_FUNC(ctdb_addr_info)();
1732         COMPAT_TEST_FUNC(ctdb_transdb)();
1733         COMPAT_TEST_FUNC(ctdb_uptime)();
1734         COMPAT_TEST_FUNC(ctdb_public_ip)();
1735         COMPAT_TEST_FUNC(ctdb_public_ip_list)();
1736         COMPAT_TEST_FUNC(ctdb_node_and_flags)();
1737         COMPAT_TEST_FUNC(ctdb_node_map)();
1738         COMPAT_TEST_FUNC(ctdb_script)();
1739         COMPAT_TEST_FUNC(ctdb_script_list)();
1740         COMPAT_TEST_FUNC(ctdb_ban_state)();
1741         COMPAT_TEST_FUNC(ctdb_notify_data)();
1742
1743         return 0;
1744 }