ctdb-protocol: Fix marshalling for ctdb_notify_data
[vlendec/samba-autobuild/.git] / ctdb / protocol / protocol_types.c
1 /*
2    CTDB protocol marshalling
3
4    Copyright (C) Amitay Isaacs  2015-2017
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_tdb_data_len(TDB_DATA *in)
31 {
32         return in->dsize > UINT32_MAX ? UINT32_MAX : in->dsize;
33 }
34
35 void ctdb_tdb_data_push(TDB_DATA *in, uint8_t *buf, size_t *npush)
36 {
37         size_t len = ctdb_tdb_data_len(in);
38
39         if (len > 0) {
40                 memcpy(buf, in->dptr, len);
41         }
42
43         *npush = len;
44 }
45
46 int ctdb_tdb_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
47                        TDB_DATA *out, size_t *npull)
48 {
49         TDB_DATA val;
50
51         if (buflen > UINT32_MAX) {
52                 return EMSGSIZE;
53         }
54
55         val.dsize = buflen;
56         if (val.dsize > 0) {
57                 val.dptr = talloc_memdup(mem_ctx, buf, buflen);
58                 if (val.dptr == NULL) {
59                         return ENOMEM;
60                 }
61         } else {
62                 val.dptr = NULL;
63         }
64
65         *out = val;
66         *npull = buflen;
67         return 0;
68 }
69
70 size_t ctdb_tdb_datan_len(TDB_DATA *in)
71 {
72         uint32_t u32 = ctdb_tdb_data_len(in);
73
74         return ctdb_uint32_len(&u32) + u32;
75 }
76
77 void ctdb_tdb_datan_push(TDB_DATA *in, uint8_t *buf, size_t *npush)
78 {
79         size_t offset = 0, np;
80         uint32_t u32 = ctdb_tdb_data_len(in);
81
82         ctdb_uint32_push(&u32, buf+offset, &np);
83         offset += np;
84
85         ctdb_tdb_data_push(in, buf+offset, &np);
86         offset += np;
87
88         *npush = offset;
89 }
90
91 int ctdb_tdb_datan_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
92                         TDB_DATA *out, size_t *npull)
93 {
94         size_t offset = 0, np;
95         uint32_t u32;
96         int ret;
97
98         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
99         if (ret != 0) {
100                 return ret;
101         }
102         offset += np;
103
104         if (buflen-offset < u32) {
105                 return EMSGSIZE;
106         }
107
108         ret = ctdb_tdb_data_pull(buf+offset, u32, mem_ctx, out, &np);
109         if (ret != 0) {
110                 return ret;
111         }
112         offset += np;
113
114         *npull = offset;
115         return 0;
116 }
117
118 size_t ctdb_latency_counter_len(struct ctdb_latency_counter *in)
119 {
120         return ctdb_int32_len(&in->num) +
121                 ctdb_padding_len(4) +
122                 ctdb_double_len(&in->min) +
123                 ctdb_double_len(&in->max) +
124                 ctdb_double_len(&in->total);
125 }
126
127 void ctdb_latency_counter_push(struct ctdb_latency_counter *in, uint8_t *buf,
128                                size_t *npush)
129 {
130         size_t offset = 0, np;
131
132         ctdb_int32_push(&in->num, buf+offset, &np);
133         offset += np;
134
135         ctdb_padding_push(4, buf+offset, &np);
136         offset += np;
137
138         ctdb_double_push(&in->min, buf+offset, &np);
139         offset += np;
140
141         ctdb_double_push(&in->max, buf+offset, &np);
142         offset += np;
143
144         ctdb_double_push(&in->total, buf+offset, &np);
145         offset += np;
146
147         *npush = offset;
148 }
149
150 int ctdb_latency_counter_pull(uint8_t *buf, size_t buflen,
151                               struct ctdb_latency_counter *out, size_t *npull)
152 {
153         size_t offset = 0, np;
154         int ret;
155
156         ret = ctdb_int32_pull(buf+offset, buflen-offset, &out->num, &np);
157         if (ret != 0) {
158                 return ret;
159         }
160         offset += np;
161
162         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
163         if (ret != 0) {
164                 return ret;
165         }
166         offset += np;
167
168         ret = ctdb_double_pull(buf+offset, buflen-offset, &out->min, &np);
169         if (ret != 0) {
170                 return ret;
171         }
172         offset += np;
173
174         ret = ctdb_double_pull(buf+offset, buflen-offset, &out->max, &np);
175         if (ret != 0) {
176                 return ret;
177         }
178         offset += np;
179
180         ret = ctdb_double_pull(buf+offset, buflen-offset, &out->total, &np);
181         if (ret != 0) {
182                 return ret;
183         }
184         offset += np;
185
186         *npull = offset;
187         return 0;
188 }
189
190 size_t ctdb_statistics_len(struct ctdb_statistics *in)
191 {
192         return ctdb_uint32_len(&in->num_clients) +
193                 ctdb_uint32_len(&in->frozen) +
194                 ctdb_uint32_len(&in->recovering) +
195                 ctdb_uint32_len(&in->client_packets_sent) +
196                 ctdb_uint32_len(&in->client_packets_recv) +
197                 ctdb_uint32_len(&in->node_packets_sent) +
198                 ctdb_uint32_len(&in->node_packets_recv) +
199                 ctdb_uint32_len(&in->keepalive_packets_sent) +
200                 ctdb_uint32_len(&in->keepalive_packets_recv) +
201                 ctdb_uint32_len(&in->node.req_call) +
202                 ctdb_uint32_len(&in->node.reply_call) +
203                 ctdb_uint32_len(&in->node.req_dmaster) +
204                 ctdb_uint32_len(&in->node.reply_dmaster) +
205                 ctdb_uint32_len(&in->node.reply_error) +
206                 ctdb_uint32_len(&in->node.req_message) +
207                 ctdb_uint32_len(&in->node.req_control) +
208                 ctdb_uint32_len(&in->node.reply_control) +
209                 ctdb_uint32_len(&in->client.req_call) +
210                 ctdb_uint32_len(&in->client.req_message) +
211                 ctdb_uint32_len(&in->client.req_control) +
212                 ctdb_uint32_len(&in->timeouts.call) +
213                 ctdb_uint32_len(&in->timeouts.control) +
214                 ctdb_uint32_len(&in->timeouts.traverse) +
215                 ctdb_padding_len(4) +
216                 ctdb_latency_counter_len(&in->reclock.ctdbd) +
217                 ctdb_latency_counter_len(&in->reclock.recd) +
218                 ctdb_uint32_len(&in->locks.num_calls) +
219                 ctdb_uint32_len(&in->locks.num_current) +
220                 ctdb_uint32_len(&in->locks.num_pending) +
221                 ctdb_uint32_len(&in->locks.num_failed) +
222                 ctdb_latency_counter_len(&in->locks.latency) +
223                 MAX_COUNT_BUCKETS * ctdb_uint32_len(&in->locks.buckets[0]) +
224                 ctdb_uint32_len(&in->total_calls) +
225                 ctdb_uint32_len(&in->pending_calls) +
226                 ctdb_uint32_len(&in->childwrite_calls) +
227                 ctdb_uint32_len(&in->pending_childwrite_calls) +
228                 ctdb_uint32_len(&in->memory_used) +
229                 ctdb_uint32_len(&in->__last_counter) +
230                 ctdb_uint32_len(&in->max_hop_count) +
231                 MAX_COUNT_BUCKETS *
232                         ctdb_uint32_len(&in->hop_count_bucket[0]) +
233                 ctdb_padding_len(4) +
234                 ctdb_latency_counter_len(&in->call_latency) +
235                 ctdb_latency_counter_len(&in->childwrite_latency) +
236                 ctdb_uint32_len(&in->num_recoveries) +
237                 ctdb_padding_len(4) +
238                 ctdb_timeval_len(&in->statistics_start_time) +
239                 ctdb_timeval_len(&in->statistics_current_time) +
240                 ctdb_uint32_len(&in->total_ro_delegations) +
241                 ctdb_uint32_len(&in->total_ro_revokes);
242 }
243
244 void ctdb_statistics_push(struct ctdb_statistics *in, uint8_t *buf,
245                           size_t *npush)
246 {
247         size_t offset = 0, np;
248         int i;
249
250         ctdb_uint32_push(&in->num_clients, buf+offset, &np);
251         offset += np;
252
253         ctdb_uint32_push(&in->frozen, buf+offset, &np);
254         offset += np;
255
256         ctdb_uint32_push(&in->recovering, buf+offset, &np);
257         offset += np;
258
259         ctdb_uint32_push(&in->client_packets_sent, buf+offset, &np);
260         offset += np;
261
262         ctdb_uint32_push(&in->client_packets_recv, buf+offset, &np);
263         offset += np;
264
265         ctdb_uint32_push(&in->node_packets_sent, buf+offset, &np);
266         offset += np;
267
268         ctdb_uint32_push(&in->node_packets_recv, buf+offset, &np);
269         offset += np;
270
271         ctdb_uint32_push(&in->keepalive_packets_sent, buf+offset, &np);
272         offset += np;
273
274         ctdb_uint32_push(&in->keepalive_packets_recv, buf+offset, &np);
275         offset += np;
276
277         ctdb_uint32_push(&in->node.req_call, buf+offset, &np);
278         offset += np;
279
280         ctdb_uint32_push(&in->node.reply_call, buf+offset, &np);
281         offset += np;
282
283         ctdb_uint32_push(&in->node.req_dmaster, buf+offset, &np);
284         offset += np;
285
286         ctdb_uint32_push(&in->node.reply_dmaster, buf+offset, &np);
287         offset += np;
288
289         ctdb_uint32_push(&in->node.reply_error, buf+offset, &np);
290         offset += np;
291
292         ctdb_uint32_push(&in->node.req_message, buf+offset, &np);
293         offset += np;
294
295         ctdb_uint32_push(&in->node.req_control, buf+offset, &np);
296         offset += np;
297
298         ctdb_uint32_push(&in->node.reply_control, buf+offset, &np);
299         offset += np;
300
301         ctdb_uint32_push(&in->client.req_call, buf+offset, &np);
302         offset += np;
303
304         ctdb_uint32_push(&in->client.req_message, buf+offset, &np);
305         offset += np;
306
307         ctdb_uint32_push(&in->client.req_control, buf+offset, &np);
308         offset += np;
309
310         ctdb_uint32_push(&in->timeouts.call, buf+offset, &np);
311         offset += np;
312
313         ctdb_uint32_push(&in->timeouts.control, buf+offset, &np);
314         offset += np;
315
316         ctdb_uint32_push(&in->timeouts.traverse, buf+offset, &np);
317         offset += np;
318
319         ctdb_padding_push(4, buf+offset, &np);
320         offset += np;
321
322         ctdb_latency_counter_push(&in->reclock.ctdbd, buf+offset, &np);
323         offset += np;
324
325         ctdb_latency_counter_push(&in->reclock.recd, buf+offset, &np);
326         offset += np;
327
328         ctdb_uint32_push(&in->locks.num_calls, buf+offset, &np);
329         offset += np;
330
331         ctdb_uint32_push(&in->locks.num_current, buf+offset, &np);
332         offset += np;
333
334         ctdb_uint32_push(&in->locks.num_pending, buf+offset, &np);
335         offset += np;
336
337         ctdb_uint32_push(&in->locks.num_failed, buf+offset, &np);
338         offset += np;
339
340         ctdb_latency_counter_push(&in->locks.latency, buf+offset, &np);
341         offset += np;
342
343         for (i=0; i<MAX_COUNT_BUCKETS; i++) {
344                 ctdb_uint32_push(&in->locks.buckets[i], buf+offset, &np);
345                 offset += np;
346         }
347
348         ctdb_uint32_push(&in->total_calls, buf+offset, &np);
349         offset += np;
350
351         ctdb_uint32_push(&in->pending_calls, buf+offset, &np);
352         offset += np;
353
354         ctdb_uint32_push(&in->childwrite_calls, buf+offset, &np);
355         offset += np;
356
357         ctdb_uint32_push(&in->pending_childwrite_calls, buf+offset, &np);
358         offset += np;
359
360         ctdb_uint32_push(&in->memory_used, buf+offset, &np);
361         offset += np;
362
363         ctdb_uint32_push(&in->__last_counter, buf+offset, &np);
364         offset += np;
365
366         ctdb_uint32_push(&in->max_hop_count, buf+offset, &np);
367         offset += np;
368
369         for (i=0; i<MAX_COUNT_BUCKETS; i++) {
370                 ctdb_uint32_push(&in->hop_count_bucket[i], buf+offset, &np);
371                 offset += np;
372         }
373
374         ctdb_padding_push(4, buf+offset, &np);
375         offset += np;
376
377         ctdb_latency_counter_push(&in->call_latency, buf+offset, &np);
378         offset += np;
379
380         ctdb_latency_counter_push(&in->childwrite_latency, buf+offset, &np);
381         offset += np;
382
383         ctdb_uint32_push(&in->num_recoveries, buf+offset, &np);
384         offset += np;
385
386         ctdb_padding_push(4, buf+offset, &np);
387         offset += np;
388
389         ctdb_timeval_push(&in->statistics_start_time, buf+offset, &np);
390         offset += np;
391
392         ctdb_timeval_push(&in->statistics_current_time, buf+offset, &np);
393         offset += np;
394
395         ctdb_uint32_push(&in->total_ro_delegations, buf+offset, &np);
396         offset += np;
397
398         ctdb_uint32_push(&in->total_ro_revokes, buf+offset, &np);
399         offset += np;
400
401         *npush = offset;
402 }
403
404 static int ctdb_statistics_pull_elems(uint8_t *buf, size_t buflen,
405                                       TALLOC_CTX *mem_ctx,
406                                       struct ctdb_statistics *out,
407                                       size_t *npull)
408 {
409         size_t offset = 0, np;
410         int ret, i;
411
412         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->num_clients,
413                                &np);
414         if (ret != 0) {
415                 return ret;
416         }
417         offset += np;
418
419         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->frozen, &np);
420         if (ret != 0) {
421                 return ret;
422         }
423         offset += np;
424
425         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->recovering,
426                                &np);
427         if (ret != 0) {
428                 return ret;
429         }
430         offset += np;
431
432         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
433                                &out->client_packets_sent, &np);
434         if (ret != 0) {
435                 return ret;
436         }
437         offset += np;
438
439         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
440                                &out->client_packets_recv, &np);
441         if (ret != 0) {
442                 return ret;
443         }
444         offset += np;
445
446         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
447                                &out->node_packets_sent, &np);
448         if (ret != 0) {
449                 return ret;
450         }
451         offset += np;
452
453         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
454                                &out->node_packets_recv, &np);
455         if (ret != 0) {
456                 return ret;
457         }
458         offset += np;
459
460         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
461                                &out->keepalive_packets_sent, &np);
462         if (ret != 0) {
463                 return ret;
464         }
465         offset += np;
466
467         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
468                                &out->keepalive_packets_recv, &np);
469         if (ret != 0) {
470                 return ret;
471         }
472         offset += np;
473
474         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
475                                &out->node.req_call, &np);
476         if (ret != 0) {
477                 return ret;
478         }
479         offset += np;
480
481         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
482                                &out->node.reply_call, &np);
483         if (ret != 0) {
484                 return ret;
485         }
486         offset += np;
487
488         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
489                                &out->node.req_dmaster, &np);
490         if (ret != 0) {
491                 return ret;
492         }
493         offset += np;
494
495         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
496                                &out->node.reply_dmaster, &np);
497         if (ret != 0) {
498                 return ret;
499         }
500         offset += np;
501
502         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
503                                &out->node.reply_error, &np);
504         if (ret != 0) {
505                 return ret;
506         }
507         offset += np;
508
509         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
510                                &out->node.req_message, &np);
511         if (ret != 0) {
512                 return ret;
513         }
514         offset += np;
515
516         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
517                                &out->node.req_control, &np);
518         if (ret != 0) {
519                 return ret;
520         }
521         offset += np;
522
523         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
524                                &out->node.reply_control, &np);
525         if (ret != 0) {
526                 return ret;
527         }
528         offset += np;
529
530         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
531                                &out->client.req_call, &np);
532         if (ret != 0) {
533                 return ret;
534         }
535         offset += np;
536
537         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
538                                &out->client.req_message, &np);
539         if (ret != 0) {
540                 return ret;
541         }
542         offset += np;
543
544         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
545                                &out->client.req_control, &np);
546         if (ret != 0) {
547                 return ret;
548         }
549         offset += np;
550
551         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
552                                &out->timeouts.call, &np);
553         if (ret != 0) {
554                 return ret;
555         }
556         offset += np;
557
558         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
559                                &out->timeouts.control, &np);
560         if (ret != 0) {
561                 return ret;
562         }
563         offset += np;
564
565         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
566                                &out->timeouts.traverse, &np);
567         if (ret != 0) {
568                 return ret;
569         }
570         offset += np;
571
572         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
573         if (ret != 0) {
574                 return ret;
575         }
576         offset += np;
577
578         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
579                                         &out->reclock.ctdbd, &np);
580         if (ret != 0) {
581                 return ret;
582         }
583         offset += np;
584
585         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
586                                         &out->reclock.recd, &np);
587         if (ret != 0) {
588                 return ret;
589         }
590         offset += np;
591
592         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
593                                &out->locks.num_calls, &np);
594         if (ret != 0) {
595                 return ret;
596         }
597         offset += np;
598
599         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
600                                &out->locks.num_current, &np);
601         if (ret != 0) {
602                 return ret;
603         }
604         offset += np;
605
606         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
607                                &out->locks.num_pending, &np);
608         if (ret != 0) {
609                 return ret;
610         }
611         offset += np;
612
613         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
614                                &out->locks.num_failed, &np);
615         if (ret != 0) {
616                 return ret;
617         }
618         offset += np;
619
620         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
621                                         &out->locks.latency, &np);
622         if (ret != 0) {
623                 return ret;
624         }
625         offset += np;
626
627         for (i=0;  i<MAX_COUNT_BUCKETS; i++) {
628                 ret = ctdb_uint32_pull(buf+offset, buflen-offset,
629                                        &out->locks.buckets[i], &np);
630                 if (ret != 0) {
631                         return ret;
632                 }
633                 offset += np;
634         }
635
636         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
637                                &out->total_calls, &np);
638         if (ret != 0) {
639                 return ret;
640         }
641         offset += np;
642
643         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
644                                &out->pending_calls, &np);
645         if (ret != 0) {
646                 return ret;
647         }
648         offset += np;
649
650         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
651                                &out->childwrite_calls, &np);
652         if (ret != 0) {
653                 return ret;
654         }
655         offset += np;
656
657         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
658                                &out->pending_childwrite_calls, &np);
659         if (ret != 0) {
660                 return ret;
661         }
662         offset += np;
663
664         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->memory_used,
665                                &np);
666         if (ret != 0) {
667                 return ret;
668         }
669         offset += np;
670
671         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
672                                &out->__last_counter, &np);
673         if (ret != 0) {
674                 return ret;
675         }
676         offset += np;
677
678         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
679                                &out->max_hop_count, &np);
680         if (ret != 0) {
681                 return ret;
682         }
683         offset += np;
684
685         for (i=0;  i<MAX_COUNT_BUCKETS; i++) {
686                 ret = ctdb_uint32_pull(buf+offset, buflen-offset,
687                                        &out->hop_count_bucket[i], &np);
688                 if (ret != 0) {
689                         return ret;
690                 }
691                 offset += np;
692         }
693
694         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
695         if (ret != 0) {
696                 return ret;
697         }
698         offset += np;
699
700         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
701                                         &out->call_latency, &np);
702         if (ret != 0) {
703                 return ret;
704         }
705         offset += np;
706
707         ret = ctdb_latency_counter_pull(buf+offset, buflen-offset,
708                                         &out->childwrite_latency, &np);
709         if (ret != 0) {
710                 return ret;
711         }
712         offset += np;
713
714         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
715                                &out->num_recoveries, &np);
716         if (ret != 0) {
717                 return ret;
718         }
719         offset += np;
720
721         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
722         if (ret != 0) {
723                 return ret;
724         }
725         offset += np;
726
727         ret = ctdb_timeval_pull(buf+offset, buflen-offset,
728                                 &out->statistics_start_time, &np);
729         if (ret != 0) {
730                 return ret;
731         }
732         offset += np;
733
734         ret = ctdb_timeval_pull(buf+offset, buflen-offset,
735                                 &out->statistics_current_time, &np);
736         if (ret != 0) {
737                 return ret;
738         }
739         offset += np;
740
741         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
742                                &out->total_ro_delegations, &np);
743         if (ret != 0) {
744                 return ret;
745         }
746         offset += np;
747
748         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
749                                &out->total_ro_revokes, &np);
750         if (ret != 0) {
751                 return ret;
752         }
753         offset += np;
754
755         *npull = offset;
756         return 0;
757 }
758
759 int ctdb_statistics_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
760                          struct ctdb_statistics **out, size_t *npull)
761 {
762         struct ctdb_statistics *val;
763         size_t np;
764         int ret;
765
766         val = talloc(mem_ctx, struct ctdb_statistics);
767         if (val == NULL) {
768                 return ENOMEM;
769         }
770
771         ret = ctdb_statistics_pull_elems(buf, buflen, val, val, &np);
772         if (ret != 0) {
773                 talloc_free(val);
774                 return ret;
775         }
776
777         *out = val;
778         *npull = np;
779         return 0;
780 }
781
782 struct ctdb_statistics_list_wire {
783         uint32_t num;
784         struct ctdb_statistics stats[1];
785 };
786
787 size_t ctdb_statistics_list_len(struct ctdb_statistics_list *stats_list)
788 {
789         return offsetof(struct ctdb_statistics_list_wire, stats) +
790                stats_list->num * sizeof(struct ctdb_statistics);
791 }
792
793 void ctdb_statistics_list_push(struct ctdb_statistics_list *stats_list,
794                                uint8_t *buf)
795 {
796         struct ctdb_statistics_list_wire *wire =
797                 (struct ctdb_statistics_list_wire *)buf;
798
799         wire->num = stats_list->num;
800         memcpy(wire->stats, stats_list->stats,
801                stats_list->num * sizeof(struct ctdb_statistics));
802 }
803
804 int ctdb_statistics_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
805                               struct ctdb_statistics_list **out)
806 {
807         struct ctdb_statistics_list *stats_list;
808         struct ctdb_statistics_list_wire *wire =
809                 (struct ctdb_statistics_list_wire *)buf;
810
811         if (buflen < offsetof(struct ctdb_statistics_list_wire, stats)) {
812                 return EMSGSIZE;
813         }
814         if (wire->num > buflen / sizeof(struct ctdb_statistics)) {
815                 return EMSGSIZE;
816         }
817         if (offsetof(struct ctdb_statistics_list_wire, stats) +
818             wire->num * sizeof(struct ctdb_statistics) <
819             offsetof(struct ctdb_statistics_list_wire, stats)) {
820                 return EMSGSIZE;
821         }
822         if (buflen < offsetof(struct ctdb_statistics_list_wire, stats) +
823                      wire->num * sizeof(struct ctdb_statistics)) {
824                 return EMSGSIZE;
825         }
826
827         stats_list = talloc(mem_ctx, struct ctdb_statistics_list);
828         if (stats_list == NULL) {
829                 return ENOMEM;
830         }
831
832         stats_list->num = wire->num;
833
834         stats_list->stats = talloc_array(stats_list, struct ctdb_statistics,
835                                          wire->num);
836         if (stats_list->stats == NULL) {
837                 talloc_free(stats_list);
838                 return ENOMEM;
839         }
840
841         memcpy(stats_list->stats, wire->stats,
842                wire->num * sizeof(struct ctdb_statistics));
843
844         *out = stats_list;
845         return 0;
846 }
847
848 size_t ctdb_vnn_map_len(struct ctdb_vnn_map *in)
849 {
850         size_t len;
851
852         len = ctdb_uint32_len(&in->generation) + ctdb_uint32_len(&in->size);
853         if (in->size > 0) {
854                 len += in->size * ctdb_uint32_len(&in->map[0]);
855         }
856
857         return len;
858 }
859
860 void ctdb_vnn_map_push(struct ctdb_vnn_map *in, uint8_t *buf, size_t *npush)
861 {
862         size_t offset = 0, np;
863         uint32_t i;
864
865         ctdb_uint32_push(&in->generation, buf+offset, &np);
866         offset += np;
867
868         ctdb_uint32_push(&in->size, buf+offset, &np);
869         offset += np;
870
871         for (i=0; i<in->size; i++) {
872                 ctdb_uint32_push(&in->map[i], buf+offset, &np);
873                 offset += np;
874         }
875
876         *npush = offset;
877 }
878
879 int ctdb_vnn_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
880                       struct ctdb_vnn_map **out, size_t *npull)
881 {
882         struct ctdb_vnn_map *val;
883         size_t offset = 0, np;
884         uint32_t i;
885         int ret;
886
887         val = talloc(mem_ctx, struct ctdb_vnn_map);
888         if (val == NULL) {
889                 return ENOMEM;
890         }
891
892         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->generation,
893                                &np);
894         if (ret != 0) {
895                 goto fail;
896         }
897         offset += np;
898
899         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->size, &np);
900         if (ret != 0) {
901                 goto fail;
902         }
903         offset += np;
904
905         if (val->size == 0) {
906                 val->map = NULL;
907                 goto done;
908         }
909
910         val->map = talloc_array(val, uint32_t, val->size);
911         if (val->map == NULL) {
912                 ret = ENOMEM;
913                 goto fail;
914         }
915
916         for (i=0; i<val->size; i++) {
917                 ret = ctdb_uint32_pull(buf+offset, buflen-offset,
918                                        &val->map[i], &np);
919                 if (ret != 0) {
920                         goto fail;
921                 }
922                 offset += np;
923         }
924
925 done:
926         *out = val;
927         *npull = offset;
928         return 0;
929
930 fail:
931         talloc_free(val);
932         return ret;
933 }
934
935 size_t ctdb_dbid_len(struct ctdb_dbid *in)
936 {
937         return ctdb_uint32_len(&in->db_id) +
938                 ctdb_uint8_len(&in->flags) +
939                 ctdb_padding_len(3);
940 }
941
942 void ctdb_dbid_push(struct ctdb_dbid *in, uint8_t *buf, size_t *npush)
943 {
944         size_t offset = 0, np;
945
946         ctdb_uint32_push(&in->db_id, buf+offset, &np);
947         offset += np;
948
949         ctdb_uint8_push(&in->flags, buf+offset, &np);
950         offset += np;
951
952         ctdb_padding_push(3, buf+offset, &np);
953         offset += np;
954
955         *npush = offset;
956 }
957
958 static int ctdb_dbid_pull_elems(uint8_t *buf, size_t buflen,
959                                 TALLOC_CTX *mem_ctx, struct ctdb_dbid *out,
960                                 size_t *npull)
961 {
962         size_t offset = 0, np;
963         int ret;
964
965         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->db_id, &np);
966         if (ret != 0) {
967                 return ret;
968         }
969         offset += np;
970
971         ret = ctdb_uint8_pull(buf+offset, buflen-offset, &out->flags, &np);
972         if (ret != 0) {
973                 return ret;
974         }
975         offset += np;
976
977         ret = ctdb_padding_pull(buf+offset, buflen-offset, 3, &np);
978         if (ret != 0) {
979                 return ret;
980         }
981         offset += np;
982
983         *npull = offset;
984         return 0;
985 }
986
987 int ctdb_dbid_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
988                    struct ctdb_dbid **out, size_t *npull)
989 {
990         struct ctdb_dbid *val;
991         size_t np;
992         int ret;
993
994         val = talloc(mem_ctx, struct ctdb_dbid);
995         if (val == NULL) {
996                 return ENOMEM;
997         }
998
999         ret = ctdb_dbid_pull_elems(buf, buflen, val, val, &np);
1000         if (ret != 0) {
1001                 talloc_free(val);
1002                 return ret;
1003         }
1004
1005         *out = val;
1006         *npull = np;
1007         return 0;
1008 }
1009
1010 size_t ctdb_dbid_map_len(struct ctdb_dbid_map *in)
1011 {
1012         size_t len;
1013
1014         len = ctdb_uint32_len(&in->num);
1015         if (in->num > 0) {
1016                 len += in->num * ctdb_dbid_len(&in->dbs[0]);
1017         }
1018
1019         return len;
1020 }
1021
1022 void ctdb_dbid_map_push(struct ctdb_dbid_map *in, uint8_t *buf, size_t *npush)
1023 {
1024         size_t offset = 0, np;
1025         uint32_t i;
1026
1027         ctdb_uint32_push(&in->num, buf+offset, &np);
1028         offset += np;
1029
1030         for (i=0; i<in->num; i++) {
1031                 ctdb_dbid_push(&in->dbs[i], buf+offset, &np);
1032                 offset += np;
1033         }
1034
1035         *npush = offset;
1036 }
1037
1038 int ctdb_dbid_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1039                        struct ctdb_dbid_map **out, size_t *npull)
1040 {
1041         struct ctdb_dbid_map *val;
1042         size_t offset = 0, np;
1043         uint32_t i;
1044         int ret;
1045
1046         val = talloc(mem_ctx, struct ctdb_dbid_map);
1047         if (val == NULL) {
1048                 return ENOMEM;
1049         }
1050
1051         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num, &np);
1052         if (ret != 0) {
1053                 goto fail;
1054         }
1055         offset += np;
1056
1057         if (val->num == 0) {
1058                 val->dbs = NULL;
1059                 goto done;
1060         }
1061
1062         val->dbs = talloc_array(val, struct ctdb_dbid, val->num);
1063         if (val->dbs == NULL) {
1064                 ret = ENOMEM;
1065                 goto fail;
1066         }
1067
1068         for (i=0; i<val->num; i++) {
1069                 ret = ctdb_dbid_pull_elems(buf+offset, buflen-offset, val,
1070                                            &val->dbs[i], &np);
1071                 if (ret != 0) {
1072                         goto fail;
1073                 }
1074                 offset += np;
1075         }
1076
1077 done:
1078         *out = val;
1079         *npull = offset;
1080         return 0;
1081
1082 fail:
1083         talloc_free(val);
1084         return ret;
1085 }
1086
1087 size_t ctdb_pulldb_len(struct ctdb_pulldb *in)
1088 {
1089         return ctdb_uint32_len(&in->db_id) +
1090                 ctdb_uint32_len(&in->lmaster);
1091 }
1092
1093 void ctdb_pulldb_push(struct ctdb_pulldb *in, uint8_t *buf, size_t *npush)
1094 {
1095         size_t offset = 0, np;
1096
1097         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1098         offset += np;
1099
1100         ctdb_uint32_push(&in->lmaster, buf+offset, &np);
1101         offset += np;
1102
1103         *npush = offset;
1104 }
1105
1106 int ctdb_pulldb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1107                      struct ctdb_pulldb **out, size_t *npull)
1108 {
1109         struct ctdb_pulldb *val;
1110         size_t offset = 0, np;
1111         int ret;
1112
1113         val = talloc(mem_ctx, struct ctdb_pulldb);
1114         if (val == NULL) {
1115                 return ENOMEM;
1116         }
1117
1118         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1119         if (ret != 0) {
1120                 talloc_free(val);
1121                 return ret;
1122         }
1123         offset += np;
1124
1125         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->lmaster, &np);
1126         if (ret != 0) {
1127                 talloc_free(val);
1128                 return ret;
1129         }
1130         offset += np;
1131
1132         *out = val;
1133         *npull = offset;
1134         return 0;
1135 }
1136
1137 size_t ctdb_pulldb_ext_len(struct ctdb_pulldb_ext *in)
1138 {
1139         return ctdb_uint32_len(&in->db_id) +
1140                 ctdb_uint32_len(&in->lmaster) +
1141                 ctdb_uint64_len(&in->srvid);
1142 }
1143
1144 void ctdb_pulldb_ext_push(struct ctdb_pulldb_ext *in, uint8_t *buf,
1145                           size_t *npush)
1146 {
1147         size_t offset = 0, np;
1148
1149         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1150         offset += np;
1151
1152         ctdb_uint32_push(&in->lmaster, buf+offset, &np);
1153         offset += np;
1154
1155         ctdb_uint64_push(&in->srvid, buf+offset, &np);
1156         offset += np;
1157
1158         *npush = offset;
1159 }
1160
1161 int ctdb_pulldb_ext_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1162                          struct ctdb_pulldb_ext **out, size_t *npull)
1163 {
1164         struct ctdb_pulldb_ext *val;
1165         size_t offset = 0, np;
1166         int ret;
1167
1168         val = talloc(mem_ctx, struct ctdb_pulldb_ext);
1169         if (val == NULL) {
1170                 return ENOMEM;
1171         }
1172
1173         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1174         if (ret != 0) {
1175                 goto fail;
1176         }
1177         offset += np;
1178
1179         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->lmaster, &np);
1180         if (ret != 0) {
1181                 goto fail;
1182         }
1183         offset += np;
1184
1185         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
1186         if (ret != 0) {
1187                 goto fail;
1188         }
1189         offset += np;
1190
1191         *out = val;
1192         *npull = offset;
1193         return 0;
1194
1195 fail:
1196         talloc_free(val);
1197         return ret;
1198 }
1199
1200 size_t ctdb_ltdb_header_len(struct ctdb_ltdb_header *in)
1201 {
1202         return ctdb_uint64_len(&in->rsn) +
1203                 ctdb_uint32_len(&in->dmaster) +
1204                 ctdb_uint32_len(&in->reserved1) +
1205                 ctdb_uint32_len(&in->flags) +
1206                 ctdb_padding_len(4);
1207 }
1208
1209 void ctdb_ltdb_header_push(struct ctdb_ltdb_header *in, uint8_t *buf,
1210                            size_t *npush)
1211 {
1212         size_t offset = 0, np;
1213
1214         ctdb_uint64_push(&in->rsn, buf+offset, &np);
1215         offset += np;
1216
1217         ctdb_uint32_push(&in->dmaster, buf+offset, &np);
1218         offset += np;
1219
1220         ctdb_uint32_push(&in->reserved1, buf+offset, &np);
1221         offset += np;
1222
1223         ctdb_uint32_push(&in->flags, buf+offset, &np);
1224         offset += np;
1225
1226         ctdb_padding_push(4, buf+offset, &np);
1227         offset += np;
1228
1229         *npush = offset;
1230 }
1231
1232 int ctdb_ltdb_header_pull(uint8_t *buf, size_t buflen,
1233                           struct ctdb_ltdb_header *out, size_t *npull)
1234 {
1235         size_t offset = 0, np;
1236         int ret;
1237
1238         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &out->rsn, &np);
1239         if (ret != 0) {
1240                 return ret;
1241         }
1242         offset += np;
1243
1244         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->dmaster, &np);
1245         if (ret != 0) {
1246                 return ret;
1247         }
1248         offset += np;
1249
1250         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->reserved1,
1251                                &np);
1252         if (ret != 0) {
1253                 return ret;
1254         }
1255         offset += np;
1256
1257         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->flags, &np);
1258         if (ret != 0) {
1259                 return ret;
1260         }
1261         offset += np;
1262
1263         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
1264         if (ret != 0) {
1265                 return ret;
1266         }
1267         offset += np;
1268
1269         *npull = offset;
1270         return 0;
1271 }
1272
1273 int ctdb_ltdb_header_extract(TDB_DATA *data, struct ctdb_ltdb_header *header)
1274 {
1275         size_t np;
1276         int ret;
1277
1278         ret = ctdb_ltdb_header_pull(data->dptr, data->dsize, header, &np);
1279         if (ret != 0) {
1280                 return ret;
1281         }
1282
1283         data->dptr += np;
1284         data->dsize -= np;
1285
1286         return 0;
1287 }
1288
1289 size_t ctdb_rec_data_len(struct ctdb_rec_data *in)
1290 {
1291         uint32_t u32;
1292
1293         u32 = ctdb_uint32_len(&in->reqid) +
1294                 ctdb_tdb_datan_len(&in->key) +
1295                 ctdb_tdb_datan_len(&in->data);
1296
1297         if (in->header != NULL) {
1298                 u32 += ctdb_ltdb_header_len(in->header);
1299         }
1300
1301         return ctdb_uint32_len(&u32) + u32;
1302 }
1303
1304 void ctdb_rec_data_push(struct ctdb_rec_data *in, uint8_t *buf, size_t *npush)
1305 {
1306         size_t offset = 0, np;
1307         uint32_t u32;
1308
1309         u32 = ctdb_rec_data_len(in);
1310         ctdb_uint32_push(&u32, buf+offset, &np);
1311         offset += np;
1312
1313         ctdb_uint32_push(&in->reqid, buf+offset, &np);
1314         offset += np;
1315
1316         u32 = ctdb_tdb_data_len(&in->key);
1317         ctdb_uint32_push(&u32, buf+offset, &np);
1318         offset += np;
1319
1320         u32 = ctdb_tdb_data_len(&in->data);
1321         if (in->header != NULL) {
1322                 u32 += ctdb_ltdb_header_len(in->header);
1323         }
1324
1325         ctdb_uint32_push(&u32, buf+offset, &np);
1326         offset += np;
1327
1328         ctdb_tdb_data_push(&in->key, buf+offset, &np);
1329         offset += np;
1330
1331         /* If ltdb header is not NULL, then it is pushed as part of the data */
1332         if (in->header != NULL) {
1333                 ctdb_ltdb_header_push(in->header, buf+offset, &np);
1334                 offset += np;
1335         }
1336         ctdb_tdb_data_push(&in->data, buf+offset, &np);
1337         offset += np;
1338
1339         *npush = offset;
1340 }
1341
1342 static int ctdb_rec_data_pull_data(uint8_t *buf, size_t buflen,
1343                                    uint32_t *reqid,
1344                                    TDB_DATA *key, TDB_DATA *data,
1345                                    size_t *npull)
1346 {
1347         size_t offset = 0, np;
1348         size_t len;
1349         uint32_t u32;
1350         int ret;
1351
1352         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
1353         if (ret != 0) {
1354                 return ret;
1355         }
1356         offset += np;
1357
1358         if (buflen < u32) {
1359                 return EMSGSIZE;
1360         }
1361         len = u32;
1362
1363         ret = ctdb_uint32_pull(buf+offset, len-offset, reqid, &np);
1364         if (ret != 0) {
1365                 return ret;
1366         }
1367         offset += np;
1368
1369         ret = ctdb_uint32_pull(buf+offset, len-offset, &u32, &np);
1370         if (ret != 0) {
1371                 return ret;
1372         }
1373         offset += np;
1374         key->dsize = u32;
1375
1376         ret = ctdb_uint32_pull(buf+offset, len-offset, &u32, &np);
1377         if (ret != 0) {
1378                 return ret;
1379         }
1380         offset += np;
1381         data->dsize = u32;
1382
1383         if (len-offset < key->dsize) {
1384                 return EMSGSIZE;
1385         }
1386
1387         key->dptr = buf+offset;
1388         offset += key->dsize;
1389
1390         if (len-offset < data->dsize) {
1391                 return EMSGSIZE;
1392         }
1393
1394         data->dptr = buf+offset;
1395         offset += data->dsize;
1396
1397         *npull = offset;
1398         return 0;
1399 }
1400
1401 static int ctdb_rec_data_pull_elems(uint8_t *buf, size_t buflen,
1402                                     TALLOC_CTX *mem_ctx,
1403                                     struct ctdb_rec_data *out,
1404                                     size_t *npull)
1405 {
1406         uint32_t reqid;
1407         TDB_DATA key, data;
1408         size_t np;
1409         int ret;
1410
1411         ret = ctdb_rec_data_pull_data(buf, buflen, &reqid, &key, &data, &np);
1412         if (ret != 0) {
1413                 return ret;
1414         }
1415
1416         out->reqid = reqid;
1417
1418         /* Always set header to NULL.  If it is required, extract it using
1419          * ctdb_rec_data_extract_header()
1420          */
1421         out->header = NULL;
1422
1423         out->key.dsize = key.dsize;
1424         if (key.dsize > 0) {
1425                 out->key.dptr = talloc_memdup(mem_ctx, key.dptr, key.dsize);
1426                 if (out->key.dptr == NULL) {
1427                         return ENOMEM;
1428                 }
1429         }
1430
1431         out->data.dsize = data.dsize;
1432         if (data.dsize > 0) {
1433                 out->data.dptr = talloc_memdup(mem_ctx, data.dptr, data.dsize);
1434                 if (out->data.dptr == NULL) {
1435                         return ENOMEM;
1436                 }
1437         }
1438
1439         *npull = np;
1440         return 0;
1441 }
1442
1443 int ctdb_rec_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1444                        struct ctdb_rec_data **out, size_t *npull)
1445 {
1446         struct ctdb_rec_data *val;
1447         size_t np;
1448         int ret;
1449
1450         val = talloc(mem_ctx, struct ctdb_rec_data);
1451         if (val == NULL) {
1452                 return ENOMEM;
1453         }
1454
1455         ret = ctdb_rec_data_pull_elems(buf, buflen, val, val, &np);
1456         if (ret != 0) {
1457                 TALLOC_FREE(val);
1458                 return ret;
1459         }
1460
1461         *out = val;
1462         *npull = np;
1463         return ret;
1464 }
1465
1466 size_t ctdb_rec_buffer_len(struct ctdb_rec_buffer *in)
1467 {
1468         return ctdb_uint32_len(&in->db_id) +
1469                 ctdb_uint32_len(&in->count) +
1470                 in->buflen;
1471 }
1472
1473 void ctdb_rec_buffer_push(struct ctdb_rec_buffer *in, uint8_t *buf,
1474                           size_t *npush)
1475 {
1476         size_t offset = 0, np;
1477
1478         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1479         offset += np;
1480
1481         ctdb_uint32_push(&in->count, buf+offset, &np);
1482         offset += np;
1483
1484         memcpy(buf+offset, in->buf, in->buflen);
1485         offset += in->buflen;
1486
1487         *npush = offset;
1488 }
1489
1490 int ctdb_rec_buffer_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1491                          struct ctdb_rec_buffer **out, size_t *npull)
1492 {
1493         struct ctdb_rec_buffer *val;
1494         size_t offset = 0, np;
1495         size_t length;
1496         int ret;
1497
1498         val = talloc(mem_ctx, struct ctdb_rec_buffer);
1499         if (val == NULL) {
1500                 return ENOMEM;
1501         }
1502
1503         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1504         if (ret != 0) {
1505                 goto fail;
1506         }
1507         offset += np;
1508
1509         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->count, &np);
1510         if (ret != 0) {
1511                 goto fail;
1512         }
1513         offset += np;
1514
1515         /* Since there is no buflen provided, walk the records to
1516          * validate the length of the buffer.
1517          */
1518         val->buf = buf+offset;
1519         val->buflen = buflen-offset;
1520
1521         length = 0;
1522         ret = ctdb_rec_buffer_traverse(val, NULL, &length);
1523         if (ret != 0) {
1524                 goto fail;
1525         }
1526
1527         if (length > buflen-offset) {
1528                 ret = EMSGSIZE;
1529                 goto fail;
1530         }
1531
1532         val->buf = talloc_memdup(val, buf+offset, length);
1533         if (val->buf == NULL) {
1534                 ret = ENOMEM;
1535                 goto fail;
1536         }
1537         val->buflen = length;
1538         offset += length;
1539
1540         *out = val;
1541         *npull = offset;
1542         return 0;
1543
1544 fail:
1545         talloc_free(val);
1546         return ret;
1547 }
1548
1549 struct ctdb_rec_buffer *ctdb_rec_buffer_init(TALLOC_CTX *mem_ctx,
1550                                              uint32_t db_id)
1551 {
1552         struct ctdb_rec_buffer *recbuf;
1553
1554         recbuf = talloc_zero(mem_ctx, struct ctdb_rec_buffer);
1555         if (recbuf == NULL) {
1556                 return recbuf;
1557         }
1558
1559         recbuf->db_id = db_id;
1560
1561         return recbuf;
1562 }
1563
1564 int ctdb_rec_buffer_add(TALLOC_CTX *mem_ctx, struct ctdb_rec_buffer *recbuf,
1565                         uint32_t reqid, struct ctdb_ltdb_header *header,
1566                         TDB_DATA key, TDB_DATA data)
1567 {
1568         struct ctdb_rec_data recdata;
1569         size_t len, np;
1570         uint8_t *ptr;
1571
1572         recdata.reqid = reqid;
1573         recdata.header = header;
1574         recdata.key = key;
1575         recdata.data = data;
1576
1577         len = ctdb_rec_data_len(&recdata);
1578
1579         ptr = talloc_realloc(mem_ctx, recbuf->buf, uint8_t,
1580                              recbuf->buflen + len);
1581         if (ptr == NULL) {
1582                 return ENOMEM;
1583         }
1584
1585         ctdb_rec_data_push(&recdata, &ptr[recbuf->buflen], &np);
1586
1587         recbuf->count++;
1588         recbuf->buf = ptr;
1589         recbuf->buflen += np;
1590         return 0;
1591 }
1592
1593 int ctdb_rec_buffer_traverse(struct ctdb_rec_buffer *recbuf,
1594                              ctdb_rec_parser_func_t func,
1595                              void *private_data)
1596 {
1597         TDB_DATA key, data;
1598         uint32_t reqid;
1599         size_t offset, reclen;
1600         int ret = 0, i;
1601
1602         offset = 0;
1603         for (i=0; i<recbuf->count; i++) {
1604                 ret = ctdb_rec_data_pull_data(&recbuf->buf[offset],
1605                                               recbuf->buflen - offset,
1606                                               &reqid, &key, &data, &reclen);
1607                 if (ret != 0) {
1608                         return ret;
1609                 }
1610
1611                 if (func != NULL) {
1612                         ret = func(reqid, NULL, key, data, private_data);
1613                         if (ret != 0) {
1614                                 break;
1615                         }
1616                 }
1617
1618                 offset += reclen;
1619         }
1620
1621         if (ret != 0) {
1622                 return ret;
1623         }
1624
1625         if (func == NULL) {
1626                 size_t *length = (size_t *)private_data;
1627
1628                 *length = offset;
1629         }
1630
1631         return 0;
1632 }
1633
1634 int ctdb_rec_buffer_write(struct ctdb_rec_buffer *recbuf, int fd)
1635 {
1636         ssize_t n;
1637
1638         n = write(fd, &recbuf->db_id, sizeof(uint32_t));
1639         if (n == -1 || n != sizeof(uint32_t)) {
1640                 return (errno != 0 ? errno : EIO);
1641         }
1642         n = write(fd, &recbuf->count, sizeof(uint32_t));
1643         if (n == -1 || n != sizeof(uint32_t)) {
1644                 return (errno != 0 ? errno : EIO);
1645         }
1646         n = write(fd, &recbuf->buflen, sizeof(size_t));
1647         if (n == -1 || n != sizeof(size_t)) {
1648                 return (errno != 0 ? errno : EIO);
1649         }
1650         n = write(fd, recbuf->buf, recbuf->buflen);
1651         if (n == -1 || n != recbuf->buflen) {
1652                 return (errno != 0 ? errno : EIO);
1653         }
1654
1655         return 0;
1656 }
1657
1658 int ctdb_rec_buffer_read(int fd, TALLOC_CTX *mem_ctx,
1659                          struct ctdb_rec_buffer **out)
1660 {
1661         struct ctdb_rec_buffer *recbuf;
1662         ssize_t n;
1663
1664         recbuf = talloc(mem_ctx, struct ctdb_rec_buffer);
1665         if (recbuf == NULL) {
1666                 return ENOMEM;
1667         }
1668
1669         n = read(fd, &recbuf->db_id, sizeof(uint32_t));
1670         if (n == -1 || n != sizeof(uint32_t)) {
1671                 return (errno != 0 ? errno : EIO);
1672         }
1673         n = read(fd, &recbuf->count, sizeof(uint32_t));
1674         if (n == -1 || n != sizeof(uint32_t)) {
1675                 return (errno != 0 ? errno : EIO);
1676         }
1677         n = read(fd, &recbuf->buflen, sizeof(size_t));
1678         if (n == -1 || n != sizeof(size_t)) {
1679                 return (errno != 0 ? errno : EIO);
1680         }
1681
1682         recbuf->buf = talloc_size(recbuf, recbuf->buflen);
1683         if (recbuf->buf == NULL) {
1684                 return ENOMEM;
1685         }
1686
1687         n = read(fd, recbuf->buf, recbuf->buflen);
1688         if (n == -1 || n != recbuf->buflen) {
1689                 return (errno != 0 ? errno : EIO);
1690         }
1691
1692         *out = recbuf;
1693         return 0;
1694 }
1695
1696 size_t ctdb_traverse_start_len(struct ctdb_traverse_start *in)
1697 {
1698         return ctdb_uint32_len(&in->db_id) +
1699                 ctdb_uint32_len(&in->reqid) +
1700                 ctdb_uint64_len(&in->srvid);
1701 }
1702
1703 void ctdb_traverse_start_push(struct ctdb_traverse_start *in, uint8_t *buf,
1704                               size_t *npush)
1705 {
1706         size_t offset = 0, np;
1707
1708         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1709         offset += np;
1710
1711         ctdb_uint32_push(&in->reqid, buf+offset, &np);
1712         offset += np;
1713
1714         ctdb_uint64_push(&in->srvid, buf+offset, &np);
1715         offset += np;
1716
1717         *npush = offset;
1718 }
1719
1720 int ctdb_traverse_start_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1721                              struct ctdb_traverse_start **out, size_t *npull)
1722 {
1723         struct ctdb_traverse_start *val;
1724         size_t offset = 0, np;
1725         int ret;
1726
1727         val = talloc(mem_ctx, struct ctdb_traverse_start);
1728         if (val == NULL) {
1729                 return ENOMEM;
1730         }
1731
1732         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1733         if (ret != 0) {
1734                 goto fail;
1735         }
1736         offset += np;
1737
1738         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->reqid, &np);
1739         if (ret != 0) {
1740                 goto fail;
1741         }
1742         offset += np;
1743
1744         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
1745         if (ret != 0) {
1746                 goto fail;
1747         }
1748         offset += np;
1749
1750         *out = val;
1751         *npull = offset;
1752         return 0;
1753
1754 fail:
1755         talloc_free(val);
1756         return ret;
1757 }
1758
1759 size_t ctdb_traverse_all_len(struct ctdb_traverse_all *in)
1760 {
1761         return ctdb_uint32_len(&in->db_id) +
1762                 ctdb_uint32_len(&in->reqid) +
1763                 ctdb_uint32_len(&in->pnn) +
1764                 ctdb_uint32_len(&in->client_reqid) +
1765                 ctdb_uint64_len(&in->srvid);
1766 }
1767
1768 void ctdb_traverse_all_push(struct ctdb_traverse_all *in, uint8_t *buf,
1769                             size_t *npush)
1770 {
1771         size_t offset = 0, np;
1772
1773         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1774         offset += np;
1775
1776         ctdb_uint32_push(&in->reqid, buf+offset, &np);
1777         offset += np;
1778
1779         ctdb_uint32_push(&in->pnn, buf+offset, &np);
1780         offset += np;
1781
1782         ctdb_uint32_push(&in->client_reqid, buf+offset, &np);
1783         offset += np;
1784
1785         ctdb_uint64_push(&in->srvid, buf+offset, &np);
1786         offset += np;
1787
1788         *npush = offset;
1789 }
1790
1791 int ctdb_traverse_all_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1792                            struct ctdb_traverse_all **out, size_t *npull)
1793 {
1794         struct ctdb_traverse_all *val;
1795         size_t offset = 0, np;
1796         int ret;
1797
1798         val = talloc(mem_ctx, struct ctdb_traverse_all);
1799         if (val == NULL) {
1800                 return ENOMEM;
1801         }
1802
1803         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1804         if (ret != 0) {
1805                 goto fail;
1806         }
1807         offset += np;
1808
1809         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->reqid, &np);
1810         if (ret != 0) {
1811                 goto fail;
1812         }
1813         offset += np;
1814
1815         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->pnn, &np);
1816         if (ret != 0) {
1817                 goto fail;
1818         }
1819         offset += np;
1820
1821         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->client_reqid,
1822                                &np);
1823         if (ret != 0) {
1824                 goto fail;
1825         }
1826         offset += np;
1827
1828         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
1829         if (ret != 0) {
1830                 goto fail;
1831         }
1832         offset += np;
1833
1834         *out = val;
1835         *npull = offset;
1836         return 0;
1837
1838 fail:
1839         talloc_free(val);
1840         return ret;
1841 }
1842
1843 size_t ctdb_traverse_start_ext_len(struct ctdb_traverse_start_ext *in)
1844 {
1845         return ctdb_uint32_len(&in->db_id) +
1846                 ctdb_uint32_len(&in->reqid) +
1847                 ctdb_uint64_len(&in->srvid) +
1848                 ctdb_bool_len(&in->withemptyrecords) +
1849                 ctdb_padding_len(7);
1850 }
1851
1852 void ctdb_traverse_start_ext_push(struct ctdb_traverse_start_ext *in,
1853                                   uint8_t *buf, size_t *npush)
1854 {
1855         size_t offset = 0, np;
1856
1857         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1858         offset += np;
1859
1860         ctdb_uint32_push(&in->reqid, buf+offset, &np);
1861         offset += np;
1862
1863         ctdb_uint64_push(&in->srvid, buf+offset, &np);
1864         offset += np;
1865
1866         ctdb_bool_push(&in->withemptyrecords, buf+offset, &np);
1867         offset += np;
1868
1869         ctdb_padding_push(7, buf+offset, &np);
1870         offset += np;
1871
1872         *npush = offset;
1873 }
1874
1875 int ctdb_traverse_start_ext_pull(uint8_t *buf, size_t buflen,
1876                                  TALLOC_CTX *mem_ctx,
1877                                  struct ctdb_traverse_start_ext **out,
1878                                  size_t *npull)
1879 {
1880         struct ctdb_traverse_start_ext *val;
1881         size_t offset = 0, np;
1882         int ret;
1883
1884         val = talloc(mem_ctx, struct ctdb_traverse_start_ext);
1885         if (val == NULL) {
1886                 return ENOMEM;
1887         }
1888
1889         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1890         if (ret != 0) {
1891                 goto fail;
1892         }
1893         offset += np;
1894
1895         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->reqid, &np);
1896         if (ret != 0) {
1897                 goto fail;
1898         }
1899         offset += np;
1900
1901         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
1902         if (ret != 0) {
1903                 goto fail;
1904         }
1905         offset += np;
1906
1907         ret = ctdb_bool_pull(buf+offset, buflen-offset,
1908                              &val->withemptyrecords, &np);
1909         if (ret != 0) {
1910                 goto fail;
1911         }
1912         offset += np;
1913
1914         ret = ctdb_padding_pull(buf+offset, buflen-offset, 7, &np);
1915         if (ret != 0) {
1916                 goto fail;
1917         }
1918         offset += np;
1919
1920         *out = val;
1921         *npull = offset;
1922         return 0;
1923
1924 fail:
1925         talloc_free(val);
1926         return ret;
1927 }
1928
1929 size_t ctdb_traverse_all_ext_len(struct ctdb_traverse_all_ext *in)
1930 {
1931         return ctdb_uint32_len(&in->db_id) +
1932                 ctdb_uint32_len(&in->reqid) +
1933                 ctdb_uint32_len(&in->pnn) +
1934                 ctdb_uint32_len(&in->client_reqid) +
1935                 ctdb_uint64_len(&in->srvid) +
1936                 ctdb_bool_len(&in->withemptyrecords) +
1937                 ctdb_padding_len(7);
1938 }
1939
1940 void ctdb_traverse_all_ext_push(struct ctdb_traverse_all_ext *in,
1941                                 uint8_t *buf, size_t *npush)
1942 {
1943         size_t offset = 0, np;
1944
1945         ctdb_uint32_push(&in->db_id, buf+offset, &np);
1946         offset += np;
1947
1948         ctdb_uint32_push(&in->reqid, buf+offset, &np);
1949         offset += np;
1950
1951         ctdb_uint32_push(&in->pnn, buf+offset, &np);
1952         offset += np;
1953
1954         ctdb_uint32_push(&in->client_reqid, buf+offset, &np);
1955         offset += np;
1956
1957         ctdb_uint64_push(&in->srvid, buf+offset, &np);
1958         offset += np;
1959
1960         ctdb_bool_push(&in->withemptyrecords, buf+offset, &np);
1961         offset += np;
1962
1963         ctdb_padding_push(7, buf+offset, &np);
1964         offset += np;
1965
1966         *npush = offset;
1967 }
1968
1969 int ctdb_traverse_all_ext_pull(uint8_t *buf, size_t buflen,
1970                                TALLOC_CTX *mem_ctx,
1971                                struct ctdb_traverse_all_ext **out,
1972                                size_t *npull)
1973 {
1974         struct ctdb_traverse_all_ext *val;
1975         size_t offset = 0, np;
1976         int ret;
1977
1978         val = talloc(mem_ctx, struct ctdb_traverse_all_ext);
1979         if (val == NULL) {
1980                 return ENOMEM;
1981         }
1982
1983         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
1984         if (ret != 0) {
1985                 goto fail;
1986         }
1987         offset += np;
1988
1989         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->reqid, &np);
1990         if (ret != 0) {
1991                 goto fail;
1992         }
1993         offset += np;
1994
1995         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->pnn, &np);
1996         if (ret != 0) {
1997                 goto fail;
1998         }
1999         offset += np;
2000
2001         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->client_reqid,
2002                                &np);
2003         if (ret != 0) {
2004                 goto fail;
2005         }
2006         offset += np;
2007
2008         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &val->srvid, &np);
2009         if (ret != 0) {
2010                 goto fail;
2011         }
2012         offset += np;
2013
2014         ret = ctdb_bool_pull(buf+offset, buflen-offset,
2015                              &val->withemptyrecords, &np);
2016         if (ret != 0) {
2017                 goto fail;
2018         }
2019         offset += np;
2020
2021         ret = ctdb_padding_pull(buf+offset, buflen-offset, 7, &np);
2022         if (ret != 0) {
2023                 goto fail;
2024         }
2025         offset += np;
2026
2027         *out = val;
2028         *npull = offset;
2029         return 0;
2030
2031 fail:
2032         talloc_free(val);
2033         return ret;
2034 }
2035
2036 size_t ctdb_sock_addr_len(ctdb_sock_addr *in)
2037 {
2038         return sizeof(ctdb_sock_addr);
2039 }
2040
2041 void ctdb_sock_addr_push(ctdb_sock_addr *in, uint8_t *buf, size_t *npush)
2042 {
2043         memcpy(buf, in, sizeof(ctdb_sock_addr));
2044         *npush = sizeof(ctdb_sock_addr);
2045 }
2046
2047 int ctdb_sock_addr_pull_elems(uint8_t *buf, size_t buflen,
2048                               TALLOC_CTX *mem_ctx, ctdb_sock_addr *out,
2049                               size_t *npull)
2050 {
2051         if (buflen < sizeof(ctdb_sock_addr)) {
2052                 return EMSGSIZE;
2053         }
2054
2055         memcpy(out, buf, sizeof(ctdb_sock_addr));
2056         *npull = sizeof(ctdb_sock_addr);
2057
2058         return 0;
2059 }
2060
2061 int ctdb_sock_addr_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2062                         ctdb_sock_addr **out, size_t *npull)
2063 {
2064         ctdb_sock_addr *val;
2065         size_t np;
2066         int ret;
2067
2068         val = talloc(mem_ctx, ctdb_sock_addr);
2069         if (val == NULL) {
2070                 return ENOMEM;
2071         }
2072
2073         ret = ctdb_sock_addr_pull_elems(buf, buflen, val, val, &np);
2074         if (ret != 0) {
2075                 talloc_free(val);
2076                 return ret;
2077         }
2078
2079         *out = val;
2080         *npull = np;
2081         return ret;
2082 }
2083
2084 size_t ctdb_connection_len(struct ctdb_connection *in)
2085 {
2086         return ctdb_sock_addr_len(&in->src) +
2087                 ctdb_sock_addr_len(&in->dst);
2088 }
2089
2090 void ctdb_connection_push(struct ctdb_connection *in, uint8_t *buf,
2091                           size_t *npush)
2092 {
2093         size_t offset = 0, np;
2094
2095         ctdb_sock_addr_push(&in->src, buf+offset, &np);
2096         offset += np;
2097
2098         ctdb_sock_addr_push(&in->dst, buf+offset, &np);
2099         offset += np;
2100
2101         *npush = offset;
2102 }
2103
2104 static int ctdb_connection_pull_elems(uint8_t *buf, size_t buflen,
2105                                       TALLOC_CTX *mem_ctx,
2106                                       struct ctdb_connection *out,
2107                                       size_t *npull)
2108 {
2109         size_t offset = 0, np;
2110         int ret;
2111
2112         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset,
2113                                         mem_ctx, &out->src, &np);
2114         if (ret != 0) {
2115                 return ret;
2116         }
2117         offset += np;
2118
2119         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset,
2120                                         mem_ctx, &out->dst, &np);
2121         if (ret != 0) {
2122                 return ret;
2123         }
2124         offset += np;
2125
2126         *npull = offset;
2127         return 0;
2128 }
2129
2130 int ctdb_connection_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2131                          struct ctdb_connection **out, size_t *npull)
2132 {
2133         struct ctdb_connection *val;
2134         size_t np;
2135         int ret;
2136
2137         val = talloc(mem_ctx, struct ctdb_connection);
2138         if (val == NULL) {
2139                 return ENOMEM;
2140         }
2141
2142         ret = ctdb_connection_pull_elems(buf, buflen, val, val, &np);
2143         if (ret != 0) {
2144                 talloc_free(val);
2145                 return ret;
2146         }
2147
2148         *out = val;
2149         *npull = np;
2150         return ret;
2151 }
2152
2153 size_t ctdb_tunable_len(struct ctdb_tunable *in)
2154 {
2155         return ctdb_uint32_len(&in->value) +
2156                 ctdb_stringn_len(&in->name);
2157 }
2158
2159 void ctdb_tunable_push(struct ctdb_tunable *in, uint8_t *buf, size_t *npush)
2160 {
2161         size_t offset = 0, np;
2162
2163         ctdb_uint32_push(&in->value, buf+offset, &np);
2164         offset += np;
2165
2166         ctdb_stringn_push(&in->name, buf+offset, &np);
2167         offset += np;
2168
2169         *npush = offset;
2170 }
2171
2172 int ctdb_tunable_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2173                       struct ctdb_tunable **out, size_t *npull)
2174 {
2175         struct ctdb_tunable *val;
2176         size_t offset = 0, np;
2177         int ret;
2178
2179         val = talloc(mem_ctx, struct ctdb_tunable);
2180         if (val == NULL) {
2181                 return ENOMEM;
2182         }
2183
2184         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->value, &np);
2185         if (ret != 0) {
2186                 goto fail;
2187         }
2188         offset += np;
2189
2190         ret = ctdb_stringn_pull(buf+offset, buflen-offset, mem_ctx,
2191                                 &val->name, &np);
2192         if (ret != 0) {
2193                 goto fail;
2194         }
2195         offset += np;
2196
2197         *out = val;
2198         *npull = offset;
2199         return 0;
2200
2201 fail:
2202         talloc_free(val);
2203         return ret;
2204 }
2205
2206 size_t ctdb_node_flag_change_len(struct ctdb_node_flag_change *in)
2207 {
2208         return ctdb_uint32_len(&in->pnn) +
2209                 ctdb_uint32_len(&in->new_flags) +
2210                 ctdb_uint32_len(&in->old_flags);
2211 }
2212
2213 void ctdb_node_flag_change_push(struct ctdb_node_flag_change *in,
2214                                 uint8_t *buf, size_t *npush)
2215 {
2216         size_t offset = 0, np;
2217
2218         ctdb_uint32_push(&in->pnn, buf+offset, &np);
2219         offset += np;
2220
2221         ctdb_uint32_push(&in->new_flags, buf+offset, &np);
2222         offset += np;
2223
2224         ctdb_uint32_push(&in->old_flags, buf+offset, &np);
2225         offset += np;
2226
2227         *npush = offset;
2228 }
2229
2230 int ctdb_node_flag_change_pull(uint8_t *buf, size_t buflen,
2231                                TALLOC_CTX *mem_ctx,
2232                                struct ctdb_node_flag_change **out,
2233                                size_t *npull)
2234 {
2235         struct ctdb_node_flag_change *val;
2236         size_t offset = 0, np;
2237         int ret;
2238
2239         val = talloc(mem_ctx, struct ctdb_node_flag_change);
2240         if (val == NULL) {
2241                 return ENOMEM;
2242         }
2243
2244         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->pnn, &np);
2245         if (ret != 0) {
2246                 goto fail;
2247         }
2248         offset += np;
2249
2250         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->new_flags,
2251                                &np);
2252         if (ret != 0) {
2253                 goto fail;
2254         }
2255         offset += np;
2256
2257         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->old_flags,
2258                                &np);
2259         if (ret != 0) {
2260                 goto fail;
2261         }
2262         offset += np;
2263
2264         *out = val;
2265         *npull = offset;
2266         return 0;
2267
2268 fail:
2269         talloc_free(val);
2270         return ret;
2271 }
2272
2273 size_t ctdb_var_list_len(struct ctdb_var_list *in)
2274 {
2275         uint32_t u32 = 0;
2276         int i;
2277
2278         for (i=0; i<in->count; i++) {
2279                 u32 += ctdb_string_len(&in->var[i]);
2280         }
2281
2282         return ctdb_uint32_len(&u32) + u32;
2283 }
2284
2285 void ctdb_var_list_push(struct ctdb_var_list *in, uint8_t *buf, size_t *npush)
2286 {
2287         size_t offset = 0, np;
2288         uint32_t u32;
2289         int i;
2290         uint8_t sep = ':';
2291
2292         /* The length only corresponds to the payload size */
2293         u32 = ctdb_var_list_len(in);
2294         u32 -= ctdb_uint32_len(&u32);
2295
2296         ctdb_uint32_push(&u32, buf+offset, &np);
2297         offset += np;
2298
2299         /* The variables are separated by ':' and the complete string is null
2300          * terminated.
2301          */
2302         for (i=0; i<in->count; i++) {
2303                 ctdb_string_push(&in->var[i], buf+offset, &np);
2304                 offset += np;
2305
2306                 if (i < in->count - 1) {
2307                         /* Replace '\0' with ':' */
2308                         ctdb_uint8_push(&sep, buf+offset-1, &np);
2309                 }
2310         }
2311
2312         *npush = offset;
2313 }
2314
2315 int ctdb_var_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2316                        struct ctdb_var_list **out, size_t *npull)
2317 {
2318         struct ctdb_var_list *val;
2319         const char *str, **list;
2320         char *s, *tok, *ptr = NULL;
2321         size_t offset = 0, np;
2322         uint32_t u32;
2323         int ret;
2324
2325         val = talloc_zero(mem_ctx, struct ctdb_var_list);
2326         if (val == NULL) {
2327                 return ENOMEM;
2328         }
2329
2330         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
2331         if (ret != 0) {
2332                 goto fail;
2333         }
2334         offset += np;
2335
2336         if (buflen-offset < u32) {
2337                 ret = EMSGSIZE;
2338                 goto fail;
2339         }
2340
2341         ret = ctdb_string_pull(buf+offset, u32, val, &str, &np);
2342         if (ret != 0) {
2343                 goto fail;
2344         }
2345         offset += np;
2346
2347         s = discard_const(str);
2348         while ((tok = strtok_r(s, ":", &ptr)) != NULL) {
2349                 list = talloc_realloc(val, val->var, const char *,
2350                                       val->count+1);
2351                 if (list == NULL) {
2352                         ret = ENOMEM;
2353                         goto fail;
2354                 }
2355
2356                 val->var = list;
2357
2358                 s = talloc_strdup(val, tok);
2359                 if (s == NULL) {
2360                         ret = ENOMEM;
2361                         goto fail;
2362                 }
2363
2364                 val->var[val->count] = s;
2365                 val->count += 1;
2366                 s = NULL;
2367         }
2368
2369         talloc_free(discard_const(str));
2370         *out = val;
2371         *npull = offset;
2372         return 0;
2373
2374 fail:
2375         talloc_free(val);
2376         return ret;
2377 }
2378
2379 size_t ctdb_tunable_list_len(struct ctdb_tunable_list *in)
2380 {
2381         return ctdb_uint32_len(&in->max_redirect_count) +
2382                 ctdb_uint32_len(&in->seqnum_interval) +
2383                 ctdb_uint32_len(&in->control_timeout) +
2384                 ctdb_uint32_len(&in->traverse_timeout) +
2385                 ctdb_uint32_len(&in->keepalive_interval) +
2386                 ctdb_uint32_len(&in->keepalive_limit) +
2387                 ctdb_uint32_len(&in->recover_timeout) +
2388                 ctdb_uint32_len(&in->recover_interval) +
2389                 ctdb_uint32_len(&in->election_timeout) +
2390                 ctdb_uint32_len(&in->takeover_timeout) +
2391                 ctdb_uint32_len(&in->monitor_interval) +
2392                 ctdb_uint32_len(&in->tickle_update_interval) +
2393                 ctdb_uint32_len(&in->script_timeout) +
2394                 ctdb_uint32_len(&in->monitor_timeout_count) +
2395                 ctdb_uint32_len(&in->script_unhealthy_on_timeout) +
2396                 ctdb_uint32_len(&in->recovery_grace_period) +
2397                 ctdb_uint32_len(&in->recovery_ban_period) +
2398                 ctdb_uint32_len(&in->database_hash_size) +
2399                 ctdb_uint32_len(&in->database_max_dead) +
2400                 ctdb_uint32_len(&in->rerecovery_timeout) +
2401                 ctdb_uint32_len(&in->enable_bans) +
2402                 ctdb_uint32_len(&in->deterministic_public_ips) +
2403                 ctdb_uint32_len(&in->reclock_ping_period) +
2404                 ctdb_uint32_len(&in->no_ip_failback) +
2405                 ctdb_uint32_len(&in->disable_ip_failover) +
2406                 ctdb_uint32_len(&in->verbose_memory_names) +
2407                 ctdb_uint32_len(&in->recd_ping_timeout) +
2408                 ctdb_uint32_len(&in->recd_ping_failcount) +
2409                 ctdb_uint32_len(&in->log_latency_ms) +
2410                 ctdb_uint32_len(&in->reclock_latency_ms) +
2411                 ctdb_uint32_len(&in->recovery_drop_all_ips) +
2412                 ctdb_uint32_len(&in->verify_recovery_lock) +
2413                 ctdb_uint32_len(&in->vacuum_interval) +
2414                 ctdb_uint32_len(&in->vacuum_max_run_time) +
2415                 ctdb_uint32_len(&in->repack_limit) +
2416                 ctdb_uint32_len(&in->vacuum_limit) +
2417                 ctdb_uint32_len(&in->max_queue_depth_drop_msg) +
2418                 ctdb_uint32_len(&in->allow_unhealthy_db_read) +
2419                 ctdb_uint32_len(&in->stat_history_interval) +
2420                 ctdb_uint32_len(&in->deferred_attach_timeout) +
2421                 ctdb_uint32_len(&in->vacuum_fast_path_count) +
2422                 ctdb_uint32_len(&in->lcp2_public_ip_assignment) +
2423                 ctdb_uint32_len(&in->allow_client_db_attach) +
2424                 ctdb_uint32_len(&in->recover_pdb_by_seqnum) +
2425                 ctdb_uint32_len(&in->deferred_rebalance_on_node_add) +
2426                 ctdb_uint32_len(&in->fetch_collapse) +
2427                 ctdb_uint32_len(&in->hopcount_make_sticky) +
2428                 ctdb_uint32_len(&in->sticky_duration) +
2429                 ctdb_uint32_len(&in->sticky_pindown) +
2430                 ctdb_uint32_len(&in->no_ip_takeover) +
2431                 ctdb_uint32_len(&in->db_record_count_warn) +
2432                 ctdb_uint32_len(&in->db_record_size_warn) +
2433                 ctdb_uint32_len(&in->db_size_warn) +
2434                 ctdb_uint32_len(&in->pulldb_preallocation_size) +
2435                 ctdb_uint32_len(&in->no_ip_host_on_all_disabled) +
2436                 ctdb_uint32_len(&in->samba3_hack) +
2437                 ctdb_uint32_len(&in->mutex_enabled) +
2438                 ctdb_uint32_len(&in->lock_processes_per_db) +
2439                 ctdb_uint32_len(&in->rec_buffer_size_limit) +
2440                 ctdb_uint32_len(&in->queue_buffer_size) +
2441                 ctdb_uint32_len(&in->ip_alloc_algorithm) +
2442                 ctdb_uint32_len(&in->allow_mixed_versions);
2443 }
2444
2445 void ctdb_tunable_list_push(struct ctdb_tunable_list *in, uint8_t *buf,
2446                             size_t *npush)
2447 {
2448         size_t offset = 0, np;
2449
2450         ctdb_uint32_push(&in->max_redirect_count, buf+offset, &np);
2451         offset += np;
2452
2453         ctdb_uint32_push(&in->seqnum_interval, buf+offset, &np);
2454         offset += np;
2455
2456         ctdb_uint32_push(&in->control_timeout, buf+offset, &np);
2457         offset += np;
2458
2459         ctdb_uint32_push(&in->traverse_timeout, buf+offset, &np);
2460         offset += np;
2461
2462         ctdb_uint32_push(&in->keepalive_interval, buf+offset, &np);
2463         offset += np;
2464
2465         ctdb_uint32_push(&in->keepalive_limit, buf+offset, &np);
2466         offset += np;
2467
2468         ctdb_uint32_push(&in->recover_timeout, buf+offset, &np);
2469         offset += np;
2470
2471         ctdb_uint32_push(&in->recover_interval, buf+offset, &np);
2472         offset += np;
2473
2474         ctdb_uint32_push(&in->election_timeout, buf+offset, &np);
2475         offset += np;
2476
2477         ctdb_uint32_push(&in->takeover_timeout, buf+offset, &np);
2478         offset += np;
2479
2480         ctdb_uint32_push(&in->monitor_interval, buf+offset, &np);
2481         offset += np;
2482
2483         ctdb_uint32_push(&in->tickle_update_interval, buf+offset, &np);
2484         offset += np;
2485
2486         ctdb_uint32_push(&in->script_timeout, buf+offset, &np);
2487         offset += np;
2488
2489         ctdb_uint32_push(&in->monitor_timeout_count, buf+offset, &np);
2490         offset += np;
2491
2492         ctdb_uint32_push(&in->script_unhealthy_on_timeout, buf+offset, &np);
2493         offset += np;
2494
2495         ctdb_uint32_push(&in->recovery_grace_period, buf+offset, &np);
2496         offset += np;
2497
2498         ctdb_uint32_push(&in->recovery_ban_period, buf+offset, &np);
2499         offset += np;
2500
2501         ctdb_uint32_push(&in->database_hash_size, buf+offset, &np);
2502         offset += np;
2503
2504         ctdb_uint32_push(&in->database_max_dead, buf+offset, &np);
2505         offset += np;
2506
2507         ctdb_uint32_push(&in->rerecovery_timeout, buf+offset, &np);
2508         offset += np;
2509
2510         ctdb_uint32_push(&in->enable_bans, buf+offset, &np);
2511         offset += np;
2512
2513         ctdb_uint32_push(&in->deterministic_public_ips, buf+offset, &np);
2514         offset += np;
2515
2516         ctdb_uint32_push(&in->reclock_ping_period, buf+offset, &np);
2517         offset += np;
2518
2519         ctdb_uint32_push(&in->no_ip_failback, buf+offset, &np);
2520         offset += np;
2521
2522         ctdb_uint32_push(&in->disable_ip_failover, buf+offset, &np);
2523         offset += np;
2524
2525         ctdb_uint32_push(&in->verbose_memory_names, buf+offset, &np);
2526         offset += np;
2527
2528         ctdb_uint32_push(&in->recd_ping_timeout, buf+offset, &np);
2529         offset += np;
2530
2531         ctdb_uint32_push(&in->recd_ping_failcount, buf+offset, &np);
2532         offset += np;
2533
2534         ctdb_uint32_push(&in->log_latency_ms, buf+offset, &np);
2535         offset += np;
2536
2537         ctdb_uint32_push(&in->reclock_latency_ms, buf+offset, &np);
2538         offset += np;
2539
2540         ctdb_uint32_push(&in->recovery_drop_all_ips, buf+offset, &np);
2541         offset += np;
2542
2543         ctdb_uint32_push(&in->verify_recovery_lock, buf+offset, &np);
2544         offset += np;
2545
2546         ctdb_uint32_push(&in->vacuum_interval, buf+offset, &np);
2547         offset += np;
2548
2549         ctdb_uint32_push(&in->vacuum_max_run_time, buf+offset, &np);
2550         offset += np;
2551
2552         ctdb_uint32_push(&in->repack_limit, buf+offset, &np);
2553         offset += np;
2554
2555         ctdb_uint32_push(&in->vacuum_limit, buf+offset, &np);
2556         offset += np;
2557
2558         ctdb_uint32_push(&in->max_queue_depth_drop_msg, buf+offset, &np);
2559         offset += np;
2560
2561         ctdb_uint32_push(&in->allow_unhealthy_db_read, buf+offset, &np);
2562         offset += np;
2563
2564         ctdb_uint32_push(&in->stat_history_interval, buf+offset, &np);
2565         offset += np;
2566
2567         ctdb_uint32_push(&in->deferred_attach_timeout, buf+offset, &np);
2568         offset += np;
2569
2570         ctdb_uint32_push(&in->vacuum_fast_path_count, buf+offset, &np);
2571         offset += np;
2572
2573         ctdb_uint32_push(&in->lcp2_public_ip_assignment, buf+offset, &np);
2574         offset += np;
2575
2576         ctdb_uint32_push(&in->allow_client_db_attach, buf+offset, &np);
2577         offset += np;
2578
2579         ctdb_uint32_push(&in->recover_pdb_by_seqnum, buf+offset, &np);
2580         offset += np;
2581
2582         ctdb_uint32_push(&in->deferred_rebalance_on_node_add, buf+offset, &np);
2583         offset += np;
2584
2585         ctdb_uint32_push(&in->fetch_collapse, buf+offset, &np);
2586         offset += np;
2587
2588         ctdb_uint32_push(&in->hopcount_make_sticky, buf+offset, &np);
2589         offset += np;
2590
2591         ctdb_uint32_push(&in->sticky_duration, buf+offset, &np);
2592         offset += np;
2593
2594         ctdb_uint32_push(&in->sticky_pindown, buf+offset, &np);
2595         offset += np;
2596
2597         ctdb_uint32_push(&in->no_ip_takeover, buf+offset, &np);
2598         offset += np;
2599
2600         ctdb_uint32_push(&in->db_record_count_warn, buf+offset, &np);
2601         offset += np;
2602
2603         ctdb_uint32_push(&in->db_record_size_warn, buf+offset, &np);
2604         offset += np;
2605
2606         ctdb_uint32_push(&in->db_size_warn, buf+offset, &np);
2607         offset += np;
2608
2609         ctdb_uint32_push(&in->pulldb_preallocation_size, buf+offset, &np);
2610         offset += np;
2611
2612         ctdb_uint32_push(&in->no_ip_host_on_all_disabled, buf+offset, &np);
2613         offset += np;
2614
2615         ctdb_uint32_push(&in->samba3_hack, buf+offset, &np);
2616         offset += np;
2617
2618         ctdb_uint32_push(&in->mutex_enabled, buf+offset, &np);
2619         offset += np;
2620
2621         ctdb_uint32_push(&in->lock_processes_per_db, buf+offset, &np);
2622         offset += np;
2623
2624         ctdb_uint32_push(&in->rec_buffer_size_limit, buf+offset, &np);
2625         offset += np;
2626
2627         ctdb_uint32_push(&in->queue_buffer_size, buf+offset, &np);
2628         offset += np;
2629
2630         ctdb_uint32_push(&in->ip_alloc_algorithm, buf+offset, &np);
2631         offset += np;
2632
2633         ctdb_uint32_push(&in->allow_mixed_versions, buf+offset, &np);
2634         offset += np;
2635
2636         *npush = offset;
2637 }
2638
2639 static int ctdb_tunable_list_pull_elems(uint8_t *buf, size_t buflen,
2640                                         TALLOC_CTX *mem_ctx,
2641                                         struct ctdb_tunable_list *out,
2642                                         size_t *npull)
2643 {
2644         size_t offset = 0, np;
2645         int ret;
2646
2647         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2648                                &out->max_redirect_count, &np);
2649         if (ret != 0) {
2650                 return ret;
2651         }
2652         offset += np;
2653
2654         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2655                                &out->seqnum_interval, &np);
2656         if (ret != 0) {
2657                 return ret;
2658         }
2659         offset += np;
2660
2661         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2662                                &out->control_timeout, &np);
2663         if (ret != 0) {
2664                 return ret;
2665         }
2666         offset += np;
2667
2668         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2669                                &out->traverse_timeout, &np);
2670         if (ret != 0) {
2671                 return ret;
2672         }
2673         offset += np;
2674
2675         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2676                                &out->keepalive_interval, &np);
2677         if (ret != 0) {
2678                 return ret;
2679         }
2680         offset += np;
2681
2682         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2683                                &out->keepalive_limit, &np);
2684         if (ret != 0) {
2685                 return ret;
2686         }
2687         offset += np;
2688
2689         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2690                                &out->recover_timeout, &np);
2691         if (ret != 0) {
2692                 return ret;
2693         }
2694         offset += np;
2695
2696         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2697                                &out->recover_interval, &np);
2698         if (ret != 0) {
2699                 return ret;
2700         }
2701         offset += np;
2702
2703         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2704                                &out->election_timeout, &np);
2705         if (ret != 0) {
2706                 return ret;
2707         }
2708         offset += np;
2709
2710         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2711                                &out->takeover_timeout, &np);
2712         if (ret != 0) {
2713                 return ret;
2714         }
2715         offset += np;
2716
2717         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2718                                &out->monitor_interval, &np);
2719         if (ret != 0) {
2720                 return ret;
2721         }
2722         offset += np;
2723
2724         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2725                                &out->tickle_update_interval, &np);
2726         if (ret != 0) {
2727                 return ret;
2728         }
2729         offset += np;
2730
2731         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2732                                &out->script_timeout, &np);
2733         if (ret != 0) {
2734                 return ret;
2735         }
2736         offset += np;
2737
2738         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2739                                &out->monitor_timeout_count, &np);
2740         if (ret != 0) {
2741                 return ret;
2742         }
2743         offset += np;
2744
2745         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2746                                &out->script_unhealthy_on_timeout, &np);
2747         if (ret != 0) {
2748                 return ret;
2749         }
2750         offset += np;
2751
2752         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2753                                &out->recovery_grace_period, &np);
2754         if (ret != 0) {
2755                 return ret;
2756         }
2757         offset += np;
2758
2759         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2760                                &out->recovery_ban_period, &np);
2761         if (ret != 0) {
2762                 return ret;
2763         }
2764         offset += np;
2765
2766         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2767                                &out->database_hash_size, &np);
2768         if (ret != 0) {
2769                 return ret;
2770         }
2771         offset += np;
2772
2773         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2774                                &out->database_max_dead, &np);
2775         if (ret != 0) {
2776                 return ret;
2777         }
2778         offset += np;
2779
2780         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2781                                &out->rerecovery_timeout, &np);
2782         if (ret != 0) {
2783                 return ret;
2784         }
2785         offset += np;
2786
2787         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2788                                &out->enable_bans, &np);
2789         if (ret != 0) {
2790                 return ret;
2791         }
2792         offset += np;
2793
2794         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2795                                &out->deterministic_public_ips, &np);
2796         if (ret != 0) {
2797                 return ret;
2798         }
2799         offset += np;
2800
2801         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2802                                &out->reclock_ping_period, &np);
2803         if (ret != 0) {
2804                 return ret;
2805         }
2806         offset += np;
2807
2808         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2809                                &out->no_ip_failback, &np);
2810         if (ret != 0) {
2811                 return ret;
2812         }
2813         offset += np;
2814
2815         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2816                                &out->disable_ip_failover, &np);
2817         if (ret != 0) {
2818                 return ret;
2819         }
2820         offset += np;
2821
2822         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2823                                &out->verbose_memory_names, &np);
2824         if (ret != 0) {
2825                 return ret;
2826         }
2827         offset += np;
2828
2829         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2830                                &out->recd_ping_timeout, &np);
2831         if (ret != 0) {
2832                 return ret;
2833         }
2834         offset += np;
2835
2836         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2837                                &out->recd_ping_failcount, &np);
2838         if (ret != 0) {
2839                 return ret;
2840         }
2841         offset += np;
2842
2843         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2844                                &out->log_latency_ms, &np);
2845         if (ret != 0) {
2846                 return ret;
2847         }
2848         offset += np;
2849
2850         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2851                                &out->reclock_latency_ms, &np);
2852         if (ret != 0) {
2853                 return ret;
2854         }
2855         offset += np;
2856
2857         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2858                                &out->recovery_drop_all_ips, &np);
2859         if (ret != 0) {
2860                 return ret;
2861         }
2862         offset += np;
2863
2864         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2865                                &out->verify_recovery_lock, &np);
2866         if (ret != 0) {
2867                 return ret;
2868         }
2869         offset += np;
2870
2871         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2872                                &out->vacuum_interval, &np);
2873         if (ret != 0) {
2874                 return ret;
2875         }
2876         offset += np;
2877
2878         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2879                                &out->vacuum_max_run_time, &np);
2880         if (ret != 0) {
2881                 return ret;
2882         }
2883         offset += np;
2884
2885         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2886                                &out->repack_limit, &np);
2887         if (ret != 0) {
2888                 return ret;
2889         }
2890         offset += np;
2891
2892         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2893                                &out->vacuum_limit, &np);
2894         if (ret != 0) {
2895                 return ret;
2896         }
2897         offset += np;
2898
2899         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2900                                &out->max_queue_depth_drop_msg, &np);
2901         if (ret != 0) {
2902                 return ret;
2903         }
2904         offset += np;
2905
2906         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2907                                &out->allow_unhealthy_db_read, &np);
2908         if (ret != 0) {
2909                 return ret;
2910         }
2911         offset += np;
2912
2913         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2914                                &out->stat_history_interval, &np);
2915         if (ret != 0) {
2916                 return ret;
2917         }
2918         offset += np;
2919
2920         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2921                                &out->deferred_attach_timeout, &np);
2922         if (ret != 0) {
2923                 return ret;
2924         }
2925         offset += np;
2926
2927         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2928                                &out->vacuum_fast_path_count, &np);
2929         if (ret != 0) {
2930                 return ret;
2931         }
2932         offset += np;
2933
2934         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2935                                &out->lcp2_public_ip_assignment, &np);
2936         if (ret != 0) {
2937                 return ret;
2938         }
2939         offset += np;
2940
2941         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2942                                &out->allow_client_db_attach, &np);
2943         if (ret != 0) {
2944                 return ret;
2945         }
2946         offset += np;
2947
2948         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2949                                &out->recover_pdb_by_seqnum, &np);
2950         if (ret != 0) {
2951                 return ret;
2952         }
2953         offset += np;
2954
2955         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2956                                &out->deferred_rebalance_on_node_add, &np);
2957         if (ret != 0) {
2958                 return ret;
2959         }
2960         offset += np;
2961
2962         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2963                                &out->fetch_collapse, &np);
2964         if (ret != 0) {
2965                 return ret;
2966         }
2967         offset += np;
2968
2969         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2970                                &out->hopcount_make_sticky, &np);
2971         if (ret != 0) {
2972                 return ret;
2973         }
2974         offset += np;
2975
2976         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2977                                &out->sticky_duration, &np);
2978         if (ret != 0) {
2979                 return ret;
2980         }
2981         offset += np;
2982
2983         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2984                                &out->sticky_pindown, &np);
2985         if (ret != 0) {
2986                 return ret;
2987         }
2988         offset += np;
2989
2990         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2991                                &out->no_ip_takeover, &np);
2992         if (ret != 0) {
2993                 return ret;
2994         }
2995         offset += np;
2996
2997         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
2998                                &out->db_record_count_warn, &np);
2999         if (ret != 0) {
3000                 return ret;
3001         }
3002         offset += np;
3003
3004         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3005                                &out->db_record_size_warn, &np);
3006         if (ret != 0) {
3007                 return ret;
3008         }
3009         offset += np;
3010
3011         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3012                                &out->db_size_warn, &np);
3013         if (ret != 0) {
3014                 return ret;
3015         }
3016         offset += np;
3017
3018         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3019                                &out->pulldb_preallocation_size, &np);
3020         if (ret != 0) {
3021                 return ret;
3022         }
3023         offset += np;
3024
3025         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3026                                &out->no_ip_host_on_all_disabled, &np);
3027         if (ret != 0) {
3028                 return ret;
3029         }
3030         offset += np;
3031
3032         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3033                                &out->samba3_hack, &np);
3034         if (ret != 0) {
3035                 return ret;
3036         }
3037         offset += np;
3038
3039         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3040                                &out->mutex_enabled, &np);
3041         if (ret != 0) {
3042                 return ret;
3043         }
3044         offset += np;
3045
3046         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3047                                &out->lock_processes_per_db, &np);
3048         if (ret != 0) {
3049                 return ret;
3050         }
3051         offset += np;
3052
3053         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3054                                &out->rec_buffer_size_limit, &np);
3055         if (ret != 0) {
3056                 return ret;
3057         }
3058         offset += np;
3059
3060         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3061                                &out->queue_buffer_size, &np);
3062         if (ret != 0) {
3063                 return ret;
3064         }
3065         offset += np;
3066
3067         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3068                                &out->ip_alloc_algorithm, &np);
3069         if (ret != 0) {
3070                 return ret;
3071         }
3072         offset += np;
3073
3074         ret = ctdb_uint32_pull(buf+offset, buflen-offset,
3075                                &out->allow_mixed_versions, &np);
3076         if (ret != 0) {
3077                 return ret;
3078         }
3079         offset += np;
3080
3081         *npull = offset;
3082         return 0;
3083 }
3084
3085 int ctdb_tunable_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3086                            struct ctdb_tunable_list **out, size_t *npull)
3087 {
3088         struct ctdb_tunable_list *val;
3089         size_t np;
3090         int ret;
3091
3092         val = talloc(mem_ctx, struct ctdb_tunable_list);
3093         if (val == NULL) {
3094                 return ENOMEM;
3095         }
3096
3097         ret = ctdb_tunable_list_pull_elems(buf, buflen, val, val, &np);
3098         if (ret != 0) {
3099                 talloc_free(val);
3100                 return ret;
3101         }
3102
3103         *out = val;
3104         *npull = np;
3105         return 0;
3106 }
3107
3108 size_t ctdb_tickle_list_len(struct ctdb_tickle_list *in)
3109 {
3110         size_t len;
3111
3112         len = ctdb_sock_addr_len(&in->addr) +
3113                 ctdb_uint32_len(&in->num);
3114         if (in->num > 0) {
3115                 len += in->num * ctdb_connection_len(&in->conn[0]);
3116         }
3117
3118         return len;
3119 }
3120
3121 void ctdb_tickle_list_push(struct ctdb_tickle_list *in, uint8_t *buf,
3122                            size_t *npush)
3123 {
3124         size_t offset = 0, np;
3125         uint32_t i;
3126
3127         ctdb_sock_addr_push(&in->addr, buf+offset, &np);
3128         offset += np;
3129
3130         ctdb_uint32_push(&in->num, buf+offset, &np);
3131         offset += np;
3132
3133         for (i=0; i<in->num; i++) {
3134                 ctdb_connection_push(&in->conn[i], buf+offset, &np);
3135                 offset += np;
3136         }
3137
3138         *npush = offset;
3139 }
3140
3141 int ctdb_tickle_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3142                            struct ctdb_tickle_list **out, size_t *npull)
3143 {
3144         struct ctdb_tickle_list *val;
3145         size_t offset = 0, np;
3146         uint32_t i;
3147         int ret;
3148
3149         val = talloc(mem_ctx, struct ctdb_tickle_list);
3150         if (val == NULL) {
3151                 return ENOMEM;
3152         }
3153
3154         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset, val,
3155                                         &val->addr, &np);
3156         if (ret != 0) {
3157                 goto fail;
3158         }
3159         offset += np;
3160
3161         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num, &np);
3162         if (ret != 0) {
3163                 goto fail;
3164         }
3165         offset += np;
3166
3167         if (val->num == 0) {
3168                 val->conn = NULL;
3169                 goto done;
3170         }
3171
3172         val->conn = talloc_array(val, struct ctdb_connection, val->num);
3173         if (val->conn == NULL) {
3174                 ret = ENOMEM;
3175                 goto fail;
3176         }
3177
3178         for (i=0; i<val->num; i++) {
3179                 ret = ctdb_connection_pull_elems(buf+offset, buflen-offset,
3180                                                  val, &val->conn[i], &np);
3181                 if (ret != 0) {
3182                         goto fail;
3183                 }
3184                 offset += np;
3185         }
3186
3187 done:
3188         *out = val;
3189         *npull = offset;
3190         return 0;
3191
3192 fail:
3193         talloc_free(val);
3194         return ret;
3195 }
3196
3197 size_t ctdb_addr_info_len(struct ctdb_addr_info *in)
3198 {
3199         return ctdb_sock_addr_len(&in->addr) +
3200                 ctdb_uint32_len(&in->mask) +
3201                 ctdb_stringn_len(&in->iface);
3202 }
3203
3204 void ctdb_addr_info_push(struct ctdb_addr_info *in, uint8_t *buf,
3205                          size_t *npush)
3206 {
3207         size_t offset = 0, np;
3208
3209         ctdb_sock_addr_push(&in->addr, buf+offset, &np);
3210         offset += np;
3211
3212         ctdb_uint32_push(&in->mask, buf+offset, &np);
3213         offset += np;
3214
3215         ctdb_stringn_push(&in->iface, buf+offset, &np);
3216         offset += np;
3217
3218         *npush = offset;
3219 }
3220
3221 int ctdb_addr_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3222                         struct ctdb_addr_info **out, size_t *npull)
3223 {