b0409e42070375c501201043470f73837db67548
[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 {
3224         struct ctdb_addr_info *val;
3225         size_t offset = 0, np;
3226         int ret;
3227
3228         val = talloc(mem_ctx, struct ctdb_addr_info);
3229         if (val == NULL) {
3230                 return ENOMEM;
3231         }
3232
3233         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset, val,
3234                                         &val->addr, &np);
3235         if (ret != 0) {
3236                 goto fail;
3237         }
3238         offset += np;
3239
3240         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->mask, &np);
3241         if (ret != 0) {
3242                 goto fail;
3243         }
3244         offset += np;
3245
3246         ret = ctdb_stringn_pull(buf+offset, buflen-offset, val, &val->iface,
3247                                 &np);
3248         if (ret != 0) {
3249                 goto fail;
3250         }
3251         offset += np;
3252
3253         *out = val;
3254         *npull = offset;
3255         return 0;
3256
3257 fail:
3258         talloc_free(val);
3259         return ret;
3260 }
3261
3262 size_t ctdb_transdb_len(struct ctdb_transdb *in)
3263 {
3264         return ctdb_uint32_len(&in->db_id) +
3265                 ctdb_uint32_len(&in->tid);
3266 }
3267
3268 void ctdb_transdb_push(struct ctdb_transdb *in, uint8_t *buf, size_t *npush)
3269 {
3270         size_t offset = 0, np;
3271
3272         ctdb_uint32_push(&in->db_id, buf+offset, &np);
3273         offset += np;
3274
3275         ctdb_uint32_push(&in->tid, buf+offset, &np);
3276         offset += np;
3277
3278         *npush = offset;
3279 }
3280
3281 int ctdb_transdb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3282                      struct ctdb_transdb **out, size_t *npull)
3283 {
3284         struct ctdb_transdb *val;
3285         size_t offset = 0, np;
3286         int ret;
3287
3288         val = talloc(mem_ctx, struct ctdb_transdb);
3289         if (val == NULL) {
3290                 return ENOMEM;
3291         }
3292
3293         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->db_id, &np);
3294         if (ret != 0) {
3295                 goto fail;
3296         }
3297         offset += np;
3298
3299         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->tid, &np);
3300         if (ret != 0) {
3301                 goto fail;
3302         }
3303         offset += np;
3304
3305         *out = val;
3306         *npull = offset;
3307         return 0;
3308
3309 fail:
3310         talloc_free(val);
3311         return ret;
3312 }
3313
3314 size_t ctdb_uptime_len(struct ctdb_uptime *in)
3315 {
3316         return ctdb_timeval_len(&in->current_time) +
3317                 ctdb_timeval_len(&in->ctdbd_start_time) +
3318                 ctdb_timeval_len(&in->last_recovery_started) +
3319                 ctdb_timeval_len(&in->last_recovery_finished);
3320 }
3321
3322 void ctdb_uptime_push(struct ctdb_uptime *in, uint8_t *buf, size_t *npush)
3323 {
3324         size_t offset = 0, np;
3325
3326         ctdb_timeval_push(&in->current_time, buf+offset, &np);
3327         offset += np;
3328
3329         ctdb_timeval_push(&in->ctdbd_start_time, buf+offset, &np);
3330         offset += np;
3331
3332         ctdb_timeval_push(&in->last_recovery_started, buf+offset, &np);
3333         offset += np;
3334
3335         ctdb_timeval_push(&in->last_recovery_finished, buf+offset, &np);
3336         offset += np;
3337
3338         *npush = offset;
3339 }
3340
3341 int ctdb_uptime_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3342                      struct ctdb_uptime **out, size_t *npull)
3343 {
3344         struct ctdb_uptime *val;
3345         size_t offset = 0, np;
3346         int ret;
3347
3348         val = talloc(mem_ctx, struct ctdb_uptime);
3349         if (val == NULL) {
3350                 return ENOMEM;
3351         }
3352
3353         ret = ctdb_timeval_pull(buf+offset, buflen-offset, &val->current_time,
3354                                 &np);
3355         if (ret != 0) {
3356                 goto fail;
3357         }
3358         offset += np;
3359
3360         ret = ctdb_timeval_pull(buf+offset, buflen-offset,
3361                                 &val->ctdbd_start_time, &np);
3362         if (ret != 0) {
3363                 goto fail;
3364         }
3365         offset += np;
3366
3367         ret = ctdb_timeval_pull(buf+offset, buflen-offset,
3368                                 &val->last_recovery_started, &np);
3369         if (ret != 0) {
3370                 goto fail;
3371         }
3372         offset += np;
3373
3374         ret = ctdb_timeval_pull(buf+offset, buflen-offset,
3375                                 &val->last_recovery_finished, &np);
3376         if (ret != 0) {
3377                 goto fail;
3378         }
3379         offset += np;
3380
3381         *out = val;
3382         *npull = offset;
3383         return 0;
3384
3385 fail:
3386         talloc_free(val);
3387         return ret;
3388 }
3389
3390 size_t ctdb_public_ip_len(struct ctdb_public_ip *in)
3391 {
3392         return ctdb_uint32_len(&in->pnn) +
3393                 ctdb_sock_addr_len(&in->addr);
3394 }
3395
3396 void ctdb_public_ip_push(struct ctdb_public_ip *in, uint8_t *buf,
3397                          size_t *npush)
3398 {
3399         size_t offset = 0, np;
3400
3401         ctdb_uint32_push(&in->pnn, buf+offset, &np);
3402         offset += np;
3403
3404         ctdb_sock_addr_push(&in->addr, buf+offset, &np);
3405         offset += np;
3406
3407         *npush = offset;
3408 }
3409
3410 static int ctdb_public_ip_pull_elems(uint8_t *buf, size_t buflen,
3411                                      TALLOC_CTX *mem_ctx,
3412                                      struct ctdb_public_ip *out, size_t *npull)
3413 {
3414         size_t offset = 0, np;
3415         int ret;
3416
3417         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->pnn, &np);
3418         if (ret != 0) {
3419                 return ret;
3420         }
3421         offset += np;
3422
3423         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset, mem_ctx,
3424                                         &out->addr, &np);
3425         if (ret != 0) {
3426                 return ret;
3427         }
3428         offset += np;
3429
3430         *npull = offset;
3431         return 0;
3432 }
3433
3434 int ctdb_public_ip_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3435                         struct ctdb_public_ip **out, size_t *npull)
3436 {
3437         struct ctdb_public_ip *val;
3438         size_t np;
3439         int ret;
3440
3441         val = talloc(mem_ctx, struct ctdb_public_ip);
3442         if (val == NULL) {
3443                 return ENOMEM;
3444         }
3445
3446         ret = ctdb_public_ip_pull_elems(buf, buflen, val, val, &np);
3447         if (ret != 0) {
3448                 TALLOC_FREE(val);
3449                 return ret;
3450         }
3451
3452         *out = val;
3453         *npull = np;
3454         return ret;
3455 }
3456
3457 size_t ctdb_public_ip_list_len(struct ctdb_public_ip_list *in)
3458 {
3459         size_t len;
3460
3461         len = ctdb_uint32_len(&in->num);
3462         if (in->num > 0) {
3463                 len += in->num * ctdb_public_ip_len(&in->ip[0]);
3464         }
3465
3466         return len;
3467 }
3468
3469 void ctdb_public_ip_list_push(struct ctdb_public_ip_list *in, uint8_t *buf,
3470                               size_t *npush)
3471 {
3472         size_t offset = 0, np;
3473         uint32_t i;
3474
3475         ctdb_uint32_push(&in->num, buf+offset, &np);
3476         offset += np;
3477
3478         for (i=0; i<in->num; i++) {
3479                 ctdb_public_ip_push(&in->ip[i], buf+offset, &np);
3480                 offset += np;
3481         }
3482
3483         *npush = offset;
3484 }
3485
3486 int ctdb_public_ip_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3487                              struct ctdb_public_ip_list **out, size_t *npull)
3488 {
3489         struct ctdb_public_ip_list *val;
3490         size_t offset = 0, np;
3491         uint32_t i;
3492         int ret;
3493
3494         val = talloc(mem_ctx, struct ctdb_public_ip_list);
3495         if (val == NULL) {
3496                 return ENOMEM;
3497         }
3498
3499         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num, &np);
3500         if (ret != 0) {
3501                 goto fail;
3502         }
3503         offset += np;
3504
3505         if (val->num == 0) {
3506                 val->ip = NULL;
3507                 goto done;
3508         }
3509
3510         val->ip = talloc_array(val, struct ctdb_public_ip, val->num);
3511         if (val->ip == NULL) {
3512                 ret = ENOMEM;
3513                 goto fail;
3514         }
3515
3516         for (i=0; i<val->num; i++) {
3517                 ret = ctdb_public_ip_pull_elems(buf+offset, buflen-offset,
3518                                                 val->ip, &val->ip[i], &np);
3519                 if (ret != 0) {
3520                         goto fail;
3521                 }
3522                 offset += np;
3523         }
3524
3525 done:
3526         *out = val;
3527         *npull = offset;
3528         return 0;
3529
3530 fail:
3531         talloc_free(val);
3532         return ret;
3533 }
3534
3535 size_t ctdb_node_and_flags_len(struct ctdb_node_and_flags *in)
3536 {
3537         return ctdb_uint32_len(&in->pnn) +
3538                 ctdb_uint32_len(&in->flags) +
3539                 ctdb_sock_addr_len(&in->addr);
3540 }
3541
3542 void ctdb_node_and_flags_push(struct ctdb_node_and_flags *in, uint8_t *buf,
3543                               size_t *npush)
3544 {
3545         size_t offset = 0, np;
3546
3547         ctdb_uint32_push(&in->pnn, buf+offset, &np);
3548         offset += np;
3549
3550         ctdb_uint32_push(&in->flags, buf+offset, &np);
3551         offset += np;
3552
3553         ctdb_sock_addr_push(&in->addr, buf+offset, &np);
3554         offset += np;
3555
3556         *npush = offset;
3557 }
3558
3559 static int ctdb_node_and_flags_pull_elems(uint8_t *buf, size_t buflen,
3560                                           TALLOC_CTX *mem_ctx,
3561                                           struct ctdb_node_and_flags *out,
3562                                           size_t *npull)
3563 {
3564         size_t offset = 0, np;
3565         int ret;
3566
3567         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->pnn, &np);
3568         if (ret != 0) {
3569                 return ret;
3570         }
3571         offset += np;
3572
3573         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &out->flags, &np);
3574         if (ret != 0) {
3575                 return ret;
3576         }
3577         offset += np;
3578
3579         ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset, mem_ctx,
3580                                         &out->addr, &np);
3581         if (ret != 0) {
3582                 return ret;
3583         }
3584         offset += np;
3585
3586         *npull = offset;
3587         return 0;
3588 }
3589
3590 int ctdb_node_and_flags_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3591                               struct ctdb_node_and_flags **out, size_t *npull)
3592 {
3593         struct ctdb_node_and_flags *val;
3594         size_t np;
3595         int ret;
3596
3597         val = talloc(mem_ctx, struct ctdb_node_and_flags);
3598         if (val == NULL) {
3599                 return ENOMEM;
3600         }
3601
3602         ret = ctdb_node_and_flags_pull_elems(buf, buflen, val, val, &np);
3603         if (ret != 0) {
3604                 TALLOC_FREE(val);
3605                 return ret;
3606         }
3607
3608         *out = val;
3609         *npull = np;
3610         return ret;
3611 }
3612
3613 size_t ctdb_node_map_len(struct ctdb_node_map *in)
3614 {
3615         size_t len;
3616
3617         len = ctdb_uint32_len(&in->num);
3618         if (in->num > 0) {
3619                 len += in->num * ctdb_node_and_flags_len(&in->node[0]);
3620         }
3621
3622         return len;
3623 }
3624
3625 void ctdb_node_map_push(struct ctdb_node_map *in, uint8_t *buf, size_t *npush)
3626 {
3627         size_t offset = 0, np;
3628         uint32_t i;
3629
3630         ctdb_uint32_push(&in->num, buf+offset, &np);
3631         offset += np;
3632
3633         for (i=0; i<in->num; i++) {
3634                 ctdb_node_and_flags_push(&in->node[i], buf+offset, &np);
3635                 offset += np;
3636         }
3637
3638         *npush = offset;
3639 }
3640
3641 int ctdb_node_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3642                        struct ctdb_node_map **out, size_t *npull)
3643 {
3644         struct ctdb_node_map *val;
3645         size_t offset = 0, np;
3646         uint32_t i;
3647         int ret;
3648
3649         val = talloc(mem_ctx, struct ctdb_node_map);
3650         if (val == NULL) {
3651                 return ENOMEM;
3652         }
3653
3654         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num, &np);
3655         if (ret != 0) {
3656                 goto fail;
3657         }
3658         offset += np;
3659
3660         if (val->num == 0) {
3661                 val->node = NULL;
3662                 goto done;
3663         }
3664
3665         val->node = talloc_array(val, struct ctdb_node_and_flags, val->num);
3666         if (val->node == NULL) {
3667                 ret = ENOMEM;
3668                 goto fail;
3669         }
3670
3671         for (i=0; i<val->num; i++) {
3672                 ret = ctdb_node_and_flags_pull_elems(buf+offset,
3673                                                      buflen-offset,
3674                                                      val->node, &val->node[i],
3675                                                      &np);
3676                 if (ret != 0) {
3677                         goto fail;
3678                 }
3679                 offset += np;
3680         }
3681
3682 done:
3683         *out = val;
3684         *npull = offset;
3685         return 0;
3686
3687 fail:
3688         talloc_free(val);
3689         return ret;
3690 }
3691
3692 size_t ctdb_script_len(struct ctdb_script *in)
3693 {
3694         return ctdb_chararray_len(in->name, MAX_SCRIPT_NAME+1) +
3695                 ctdb_timeval_len(&in->start) +
3696                 ctdb_timeval_len(&in->finished) +
3697                 ctdb_int32_len(&in->status) +
3698                 ctdb_chararray_len(in->output, MAX_SCRIPT_OUTPUT+1) +
3699                 ctdb_padding_len(4);
3700 }
3701
3702 void ctdb_script_push(struct ctdb_script *in, uint8_t *buf, size_t *npush)
3703 {
3704         size_t offset = 0, np;
3705
3706         ctdb_chararray_push(in->name, MAX_SCRIPT_NAME+1, buf+offset, &np);
3707         offset += np;
3708
3709         ctdb_timeval_push(&in->start, buf+offset, &np);
3710         offset += np;
3711
3712         ctdb_timeval_push(&in->finished, buf+offset, &np);
3713         offset += np;
3714
3715         ctdb_int32_push(&in->status, buf+offset, &np);
3716         offset += np;
3717
3718         ctdb_chararray_push(in->output, MAX_SCRIPT_OUTPUT+1, buf+offset, &np);
3719         offset += np;
3720
3721         ctdb_padding_push(4, buf+offset, &np);
3722         offset += np;
3723
3724         *npush = offset;
3725 }
3726
3727 static int ctdb_script_pull_elems(uint8_t *buf, size_t buflen,
3728                                   TALLOC_CTX *mem_ctx,
3729                                   struct ctdb_script *out, size_t *npull)
3730 {
3731         size_t offset = 0, np;
3732         int ret;
3733
3734         ret = ctdb_chararray_pull(buf+offset, buflen-offset,
3735                                   out->name, MAX_SCRIPT_NAME+1, &np);
3736         if (ret != 0) {
3737                 return ret;
3738         }
3739         offset += np;
3740
3741         ret = ctdb_timeval_pull(buf+offset, buflen-offset, &out->start, &np);
3742         if (ret != 0) {
3743                 return ret;
3744         }
3745         offset += np;
3746
3747         ret = ctdb_timeval_pull(buf+offset, buflen-offset, &out->finished,
3748                                 &np);
3749         if (ret != 0) {
3750                 return ret;
3751         }
3752         offset += np;
3753
3754         ret = ctdb_int32_pull(buf+offset, buflen-offset, &out->status, &np);
3755         if (ret != 0) {
3756                 return ret;
3757         }
3758         offset += np;
3759
3760         ret = ctdb_chararray_pull(buf+offset, buflen-offset,
3761                                   out->output, MAX_SCRIPT_OUTPUT+1, &np);
3762         if (ret != 0) {
3763                 return ret;
3764         }
3765         offset += np;
3766
3767         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
3768         if (ret != 0) {
3769                 return ret;
3770         }
3771         offset += np;
3772
3773         *npull = offset;
3774         return 0;
3775 }
3776
3777 int ctdb_script_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3778                      struct ctdb_script **out, size_t *npull)
3779 {
3780         struct ctdb_script *val;
3781         size_t np;
3782         int ret;
3783
3784         val = talloc(mem_ctx, struct ctdb_script);
3785         if (val == NULL) {
3786                 return ENOMEM;
3787         }
3788
3789         ret = ctdb_script_pull_elems(buf, buflen, val, val, &np);
3790         if (ret != 0) {
3791                 TALLOC_FREE(val);
3792                 return ret;
3793         }
3794
3795         *out = val;
3796         *npull = np;
3797         return ret;
3798 }
3799
3800 size_t ctdb_script_list_len(struct ctdb_script_list *in)
3801 {
3802         size_t len;
3803
3804         if (in == NULL) {
3805                 return 0;
3806         }
3807
3808         len = ctdb_uint32_len(&in->num_scripts) + ctdb_padding_len(4);
3809         if (in->num_scripts > 0) {
3810                 len += in->num_scripts * ctdb_script_len(&in->script[0]);
3811         }
3812
3813         return len;
3814 }
3815
3816 void ctdb_script_list_push(struct ctdb_script_list *in, uint8_t *buf,
3817                            size_t *npush)
3818 {
3819         size_t offset = 0, np;
3820         uint32_t i;
3821
3822         if (in == NULL) {
3823                 *npush = 0;
3824                 return;
3825         }
3826
3827         ctdb_uint32_push(&in->num_scripts, buf+offset, &np);
3828         offset += np;
3829
3830         ctdb_padding_push(4, buf+offset, &np);
3831         offset += np;
3832
3833         for (i=0; i<in->num_scripts; i++) {
3834                 ctdb_script_push(&in->script[i], buf+offset, &np);
3835                 offset += np;
3836         }
3837
3838         *npush = offset;
3839 }
3840
3841 int ctdb_script_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3842                           struct ctdb_script_list **out, size_t *npull)
3843 {
3844         struct ctdb_script_list *val;
3845         size_t offset = 0, np;
3846         uint32_t i;
3847         int ret;
3848
3849         /* If event scripts have never been run, the result will be NULL */
3850         if (buflen == 0) {
3851                 val = NULL;
3852                 goto done;
3853         }
3854
3855         val = talloc(mem_ctx, struct ctdb_script_list);
3856         if (val == NULL) {
3857                 return ENOMEM;
3858         }
3859
3860         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num_scripts,
3861                                &np);
3862         if (ret != 0) {
3863                 goto fail;
3864         }
3865         offset += np;
3866
3867         ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
3868         if (ret != 0) {
3869                 goto fail;
3870         }
3871         offset += np;
3872
3873         if (val->num_scripts == 0) {
3874                 goto done;
3875                 val->script = NULL;
3876         }
3877
3878         val->script = talloc_array(val, struct ctdb_script, val->num_scripts);
3879         if (val->script == NULL) {
3880                 ret = ENOMEM;
3881                 goto fail;
3882         }
3883
3884         for (i=0; i<val->num_scripts; i++) {
3885                 ret = ctdb_script_pull_elems(buf+offset, buflen-offset,
3886                                              val, &val->script[i], &np);
3887                 if (ret != 0) {
3888                         goto fail;
3889                 }
3890                 offset += np;
3891         }
3892
3893 done:
3894         *out = val;
3895         *npull = offset;
3896         return 0;
3897
3898 fail:
3899         talloc_free(val);
3900         return ret;
3901 }
3902
3903 size_t ctdb_ban_state_len(struct ctdb_ban_state *ban_state)
3904 {
3905         return sizeof(struct ctdb_ban_state);
3906 }
3907
3908 void ctdb_ban_state_push(struct ctdb_ban_state *ban_state, uint8_t *buf)
3909 {
3910         memcpy(buf, ban_state, sizeof(struct ctdb_ban_state));
3911 }
3912
3913 int ctdb_ban_state_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3914                         struct ctdb_ban_state **out)
3915 {
3916         struct ctdb_ban_state *ban_state;
3917
3918         if (buflen < sizeof(struct ctdb_ban_state)) {
3919                 return EMSGSIZE;
3920         }
3921
3922         ban_state = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_ban_state));
3923         if (ban_state == NULL) {
3924                 return ENOMEM;
3925         }
3926
3927         *out = ban_state;
3928         return 0;
3929 }
3930
3931 struct ctdb_notify_data_wire {
3932         uint64_t srvid;
3933         uint32_t len;
3934         uint8_t data[1];
3935 };
3936
3937 size_t ctdb_notify_data_len(struct ctdb_notify_data *notify)
3938 {
3939         return offsetof(struct ctdb_notify_data_wire, data) +
3940                notify->data.dsize;
3941 }
3942
3943 void ctdb_notify_data_push(struct ctdb_notify_data *notify, uint8_t *buf)
3944 {
3945         struct ctdb_notify_data_wire *wire =
3946                 (struct ctdb_notify_data_wire *)buf;
3947
3948         wire->srvid = notify->srvid;
3949         wire->len = notify->data.dsize;
3950         memcpy(wire->data, notify->data.dptr, notify->data.dsize);
3951 }
3952
3953 int ctdb_notify_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
3954                           struct ctdb_notify_data **out)
3955 {
3956         struct ctdb_notify_data *notify;
3957         struct ctdb_notify_data_wire *wire =
3958                 (struct ctdb_notify_data_wire *)buf;
3959
3960         if (buflen < offsetof(struct ctdb_notify_data_wire, data)) {
3961                 return EMSGSIZE;
3962         }
3963         if (wire->len > buflen) {
3964                 return EMSGSIZE;
3965         }
3966         if (offsetof(struct ctdb_notify_data_wire, data) + wire->len <
3967             offsetof(struct ctdb_notify_data_wire, data)) {
3968                 return EMSGSIZE;
3969         }
3970         if (buflen < offsetof(struct ctdb_notify_data_wire, data) + wire->len) {
3971                 return EMSGSIZE;
3972         }
3973
3974         notify = talloc(mem_ctx, struct ctdb_notify_data);
3975         if (notify == NULL) {
3976                 return ENOMEM;
3977         }
3978
3979         notify->srvid = wire->srvid;
3980         notify->data.dsize = wire->len;
3981         notify->data.dptr = talloc_memdup(notify, wire->data, wire->len);
3982         if (notify->data.dptr == NULL) {
3983                 talloc_free(notify);
3984                 return ENOMEM;
3985         }
3986
3987         *out = notify;
3988         return 0;
3989 }
3990
3991 size_t ctdb_iface_len(struct ctdb_iface *iface)
3992 {
3993         return sizeof(struct ctdb_iface);
3994 }
3995
3996 void ctdb_iface_push(struct ctdb_iface *iface, uint8_t *buf)
3997 {
3998         memcpy(buf, iface, sizeof(struct ctdb_iface));
3999 }
4000
4001 static int ctdb_iface_pull_elems(uint8_t *buf, size_t buflen,
4002                                  TALLOC_CTX *mem_ctx,
4003                                  struct ctdb_iface *out)
4004 {
4005         if (buflen < sizeof(struct ctdb_iface)) {
4006                 return EMSGSIZE;
4007         }
4008
4009         memcpy(out, buf, sizeof(struct ctdb_iface));
4010
4011         return 0;
4012 }
4013
4014 int ctdb_iface_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4015                     struct ctdb_iface **out)
4016 {
4017         struct ctdb_iface *iface;
4018         int ret;
4019
4020         iface = talloc(mem_ctx, struct ctdb_iface);
4021         if (iface == NULL) {
4022                 return ENOMEM;
4023         }
4024
4025         ret = ctdb_iface_pull_elems(buf, buflen, iface, iface);
4026         if (ret != 0) {
4027                 TALLOC_FREE(iface);
4028         }
4029
4030         *out = iface;
4031         return ret;
4032 }
4033
4034 struct ctdb_iface_list_wire {
4035         uint32_t num;
4036         struct ctdb_iface iface[1];
4037 };
4038
4039 size_t ctdb_iface_list_len(struct ctdb_iface_list *iface_list)
4040 {
4041         return sizeof(uint32_t) +
4042                iface_list->num * sizeof(struct ctdb_iface);
4043 }
4044
4045 void ctdb_iface_list_push(struct ctdb_iface_list *iface_list, uint8_t *buf)
4046 {
4047         struct ctdb_iface_list_wire *wire =
4048                 (struct ctdb_iface_list_wire *)buf;
4049
4050         wire->num = iface_list->num;
4051         memcpy(wire->iface, iface_list->iface,
4052                iface_list->num * sizeof(struct ctdb_iface));
4053 }
4054
4055 int ctdb_iface_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4056                          struct ctdb_iface_list **out)
4057 {
4058         struct ctdb_iface_list *iface_list;
4059         struct ctdb_iface_list_wire *wire =
4060                 (struct ctdb_iface_list_wire *)buf;
4061
4062         if (buflen < sizeof(uint32_t)) {
4063                 return EMSGSIZE;
4064         }
4065         if (wire->num > buflen / sizeof(struct ctdb_iface)) {
4066                 return EMSGSIZE;
4067         }
4068         if (sizeof(uint32_t) + wire->num * sizeof(struct ctdb_iface) <
4069             sizeof(uint32_t)) {
4070                 return EMSGSIZE;
4071         }
4072         if (buflen < sizeof(uint32_t) + wire->num * sizeof(struct ctdb_iface)) {
4073                 return EMSGSIZE;
4074         }
4075
4076         iface_list = talloc(mem_ctx, struct ctdb_iface_list);
4077         if (iface_list == NULL) {
4078                 return ENOMEM;
4079         }
4080
4081         iface_list->num = wire->num;
4082         iface_list->iface = talloc_array(iface_list, struct ctdb_iface,
4083                                          wire->num);
4084         if (iface_list->iface == NULL) {
4085                 talloc_free(iface_list);
4086                 return ENOMEM;
4087         }
4088
4089         memcpy(iface_list->iface, wire->iface,
4090                wire->num * sizeof(struct ctdb_iface));
4091
4092         *out = iface_list;
4093         return 0;
4094 }
4095
4096 struct ctdb_public_ip_info_wire {
4097         struct ctdb_public_ip ip;
4098         uint32_t active_idx;
4099         uint32_t num;
4100         struct ctdb_iface ifaces[1];
4101 };
4102
4103 size_t ctdb_public_ip_info_len(struct ctdb_public_ip_info *ipinfo)
4104 {
4105         return offsetof(struct ctdb_public_ip_info_wire, num) +
4106                ctdb_iface_list_len(ipinfo->ifaces);
4107 }
4108
4109 void ctdb_public_ip_info_push(struct ctdb_public_ip_info *ipinfo, uint8_t *buf)
4110 {
4111         struct ctdb_public_ip_info_wire *wire =
4112                 (struct ctdb_public_ip_info_wire *)buf;
4113         size_t offset;
4114
4115         offset = offsetof(struct ctdb_public_ip_info_wire, num);
4116         memcpy(wire, ipinfo, offset);
4117         wire->num = ipinfo->ifaces->num;
4118         memcpy(wire->ifaces, ipinfo->ifaces->iface,
4119                ipinfo->ifaces->num * sizeof(struct ctdb_iface));
4120 }
4121
4122 int ctdb_public_ip_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4123                              struct ctdb_public_ip_info **out)
4124 {
4125         struct ctdb_public_ip_info *ipinfo;
4126         struct ctdb_public_ip_info_wire *wire =
4127                 (struct ctdb_public_ip_info_wire *)buf;
4128
4129         if (buflen < offsetof(struct ctdb_public_ip_info_wire, ifaces)) {
4130                 return EMSGSIZE;
4131         }
4132         if (wire->num > buflen / sizeof(struct ctdb_iface)) {
4133                 return EMSGSIZE;
4134         }
4135         if (offsetof(struct ctdb_public_ip_info_wire, ifaces) +
4136             wire->num * sizeof(struct ctdb_iface) <
4137             offsetof(struct ctdb_public_ip_info_wire, ifaces)) {
4138                 return EMSGSIZE;
4139         }
4140         if (buflen < offsetof(struct ctdb_public_ip_info_wire, ifaces) +
4141                      wire->num * sizeof(struct ctdb_iface)) {
4142                 return EMSGSIZE;
4143         }
4144
4145         ipinfo = talloc(mem_ctx, struct ctdb_public_ip_info);
4146         if (ipinfo == NULL) {
4147                 return ENOMEM;
4148         }
4149
4150         memcpy(ipinfo, wire, offsetof(struct ctdb_public_ip_info_wire, num));
4151
4152         ipinfo->ifaces = talloc(ipinfo, struct ctdb_iface_list);
4153         if (ipinfo->ifaces == NULL) {
4154                 talloc_free(ipinfo);
4155                 return ENOMEM;
4156         }
4157
4158         ipinfo->ifaces->num = wire->num;
4159         ipinfo->ifaces->iface = talloc_array(ipinfo->ifaces, struct ctdb_iface,
4160                                              wire->num);
4161         if (ipinfo->ifaces->iface == NULL) {
4162                 talloc_free(ipinfo);
4163                 return ENOMEM;
4164         }
4165
4166         memcpy(ipinfo->ifaces->iface, wire->ifaces,
4167                wire->num * sizeof(struct ctdb_iface));
4168
4169         *out = ipinfo;
4170         return 0;
4171 }
4172
4173 struct ctdb_key_data_wire {
4174         uint32_t db_id;
4175         struct ctdb_ltdb_header header;
4176         uint32_t keylen;
4177         uint8_t key[1];
4178 };
4179
4180 size_t ctdb_key_data_len(struct ctdb_key_data *key)
4181 {
4182         return offsetof(struct ctdb_key_data_wire, key) + key->key.dsize;
4183 }
4184
4185 void ctdb_key_data_push(struct ctdb_key_data *key, uint8_t *buf)
4186 {
4187         struct ctdb_key_data_wire *wire = (struct ctdb_key_data_wire *)buf;
4188
4189         memcpy(wire, key, offsetof(struct ctdb_key_data, key));
4190         wire->keylen = key->key.dsize;
4191         memcpy(wire->key, key->key.dptr, key->key.dsize);
4192 }
4193
4194 int ctdb_key_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4195                        struct ctdb_key_data **out)
4196 {
4197         struct ctdb_key_data *key_data;
4198         struct ctdb_key_data_wire *wire = (struct ctdb_key_data_wire *)buf;
4199
4200         if (buflen < offsetof(struct ctdb_key_data_wire, key)) {
4201                 return EMSGSIZE;
4202         }
4203         if (wire->keylen > buflen) {
4204                 return EMSGSIZE;
4205         }
4206         if (offsetof(struct ctdb_key_data_wire, key) + wire->keylen <
4207             offsetof(struct ctdb_key_data_wire, key)) {
4208                 return EMSGSIZE;
4209         }
4210         if (buflen < offsetof(struct ctdb_key_data_wire, key) + wire->keylen) {
4211                 return EMSGSIZE;
4212         }
4213
4214         key_data = talloc(mem_ctx, struct ctdb_key_data);
4215         if (key_data == NULL) {
4216                 return ENOMEM;
4217         }
4218
4219         memcpy(key_data, wire, offsetof(struct ctdb_key_data, key));
4220
4221         key_data->key.dsize = wire->keylen;
4222         key_data->key.dptr = talloc_memdup(key_data, wire->key, wire->keylen);
4223         if (key_data->key.dptr == NULL) {
4224                 talloc_free(key_data);
4225                 return ENOMEM;
4226         }
4227
4228         *out = key_data;
4229         return 0;
4230 }
4231
4232 struct ctdb_db_statistics_wire {
4233         struct ctdb_db_statistics dbstats;
4234         char hot_keys_wire[1];
4235 };
4236
4237 size_t ctdb_db_statistics_len(struct ctdb_db_statistics *dbstats)
4238 {
4239         size_t len;
4240         int i;
4241
4242         len = sizeof(struct ctdb_db_statistics);
4243         for (i=0; i<MAX_HOT_KEYS; i++) {
4244                 len += dbstats->hot_keys[i].key.dsize;
4245         }
4246         return len;
4247 }
4248
4249 void ctdb_db_statistics_push(struct ctdb_db_statistics *dbstats, void *buf)
4250 {
4251         struct ctdb_db_statistics_wire *wire =
4252                 (struct ctdb_db_statistics_wire *)buf;
4253         size_t offset;
4254         int i;
4255
4256         dbstats->num_hot_keys = MAX_HOT_KEYS;
4257         memcpy(wire, dbstats, sizeof(struct ctdb_db_statistics));
4258
4259         offset = 0;
4260         for (i=0; i<MAX_HOT_KEYS; i++) {
4261                 memcpy(&wire->hot_keys_wire[offset],
4262                        dbstats->hot_keys[i].key.dptr,
4263                        dbstats->hot_keys[i].key.dsize);
4264                 offset += dbstats->hot_keys[i].key.dsize;
4265         }
4266 }
4267
4268 int ctdb_db_statistics_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4269                             struct ctdb_db_statistics **out)
4270 {
4271         struct ctdb_db_statistics *dbstats;
4272         struct ctdb_db_statistics_wire *wire =
4273                 (struct ctdb_db_statistics_wire *)buf;
4274         size_t offset;
4275         int i;
4276
4277         if (buflen < sizeof(struct ctdb_db_statistics)) {
4278                 return EMSGSIZE;
4279         }
4280
4281         offset = 0;
4282         for (i=0; i<wire->dbstats.num_hot_keys; i++) {
4283                 if (wire->dbstats.hot_keys[i].key.dsize > buflen) {
4284                         return EMSGSIZE;
4285                 }
4286                 if (offset + wire->dbstats.hot_keys[i].key.dsize < offset) {
4287                         return EMSGSIZE;
4288                 }
4289                 offset += wire->dbstats.hot_keys[i].key.dsize;
4290                 if (offset > buflen) {
4291                         return EMSGSIZE;
4292                 }
4293         }
4294         if (sizeof(struct ctdb_db_statistics) + offset <
4295             sizeof(struct ctdb_db_statistics)) {
4296                 return EMSGSIZE;
4297         }
4298         if (buflen < sizeof(struct ctdb_db_statistics) + offset) {
4299                 return EMSGSIZE;
4300         }
4301
4302         dbstats = talloc(mem_ctx, struct ctdb_db_statistics);
4303         if (dbstats == NULL) {
4304                 return ENOMEM;
4305         }
4306
4307         memcpy(dbstats, wire, sizeof(struct ctdb_db_statistics));
4308
4309         offset = 0;
4310         for (i=0; i<wire->dbstats.num_hot_keys; i++) {
4311                 uint8_t *ptr;
4312                 size_t key_size;
4313
4314                 key_size = dbstats->hot_keys[i].key.dsize;
4315                 ptr = talloc_memdup(mem_ctx, &wire->hot_keys_wire[offset],
4316                                     key_size);
4317                 if (ptr == NULL) {
4318                         talloc_free(dbstats);
4319                         return ENOMEM;
4320                 }
4321                 dbstats->hot_keys[i].key.dptr = ptr;
4322                 offset += key_size;
4323         }
4324
4325         *out = dbstats;
4326         return 0;
4327 }
4328
4329 size_t ctdb_election_message_len(struct ctdb_election_message *election)
4330 {
4331         return sizeof(struct ctdb_election_message);
4332 }
4333
4334 void ctdb_election_message_push(struct ctdb_election_message *election,
4335                                 uint8_t *buf)
4336 {
4337         memcpy(buf, election, sizeof(struct ctdb_election_message));
4338 }
4339
4340 int ctdb_election_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4341                                struct ctdb_election_message **out)
4342 {
4343         struct ctdb_election_message *election;
4344
4345         if (buflen < sizeof(struct ctdb_election_message)) {
4346                 return EMSGSIZE;
4347         }
4348
4349         election = talloc_memdup(mem_ctx, buf,
4350                                  sizeof(struct ctdb_election_message));
4351         if (election == NULL) {
4352                 return ENOMEM;
4353         }
4354
4355         *out = election;
4356         return 0;
4357 }
4358
4359 size_t ctdb_srvid_message_len(struct ctdb_srvid_message *msg)
4360 {
4361         return sizeof(struct ctdb_srvid_message);
4362 }
4363
4364 void ctdb_srvid_message_push(struct ctdb_srvid_message *msg, uint8_t *buf)
4365 {
4366         memcpy(buf, msg, sizeof(struct ctdb_srvid_message));
4367 }
4368
4369 int ctdb_srvid_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4370                             struct ctdb_srvid_message **out)
4371 {
4372         struct ctdb_srvid_message *msg;
4373
4374         if (buflen < sizeof(struct ctdb_srvid_message)) {
4375                 return EMSGSIZE;
4376         }
4377
4378         msg = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_srvid_message));
4379         if (msg == NULL) {
4380                 return ENOMEM;
4381         }
4382
4383         *out = msg;
4384         return 0;
4385 }
4386
4387 size_t ctdb_disable_message_len(struct ctdb_disable_message *disable)
4388 {
4389         return sizeof(struct ctdb_disable_message);
4390 }
4391
4392 void ctdb_disable_message_push(struct ctdb_disable_message *disable,
4393                                uint8_t *buf)
4394 {
4395         memcpy(buf, disable, sizeof(struct ctdb_disable_message));
4396 }
4397
4398 int ctdb_disable_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4399                               struct ctdb_disable_message **out)
4400 {
4401         struct ctdb_disable_message *disable;
4402
4403         if (buflen < sizeof(struct ctdb_disable_message)) {
4404                 return EMSGSIZE;
4405         }
4406
4407         disable = talloc_memdup(mem_ctx, buf,
4408                                 sizeof(struct ctdb_disable_message));
4409         if (disable == NULL) {
4410                 return ENOMEM;
4411         }
4412
4413         *out = disable;
4414         return 0;
4415 }
4416
4417 size_t ctdb_server_id_len(struct ctdb_server_id *sid)
4418 {
4419         return sizeof(struct ctdb_server_id);
4420 }
4421
4422 void ctdb_server_id_push(struct ctdb_server_id *sid, uint8_t *buf)
4423 {
4424         memcpy(buf, sid, sizeof(struct ctdb_server_id));
4425 }
4426
4427 int ctdb_server_id_pull(uint8_t *buf, size_t buflen,
4428                         struct ctdb_server_id *sid)
4429 {
4430         if (buflen < sizeof(struct ctdb_server_id)) {
4431                 return EMSGSIZE;
4432         }
4433
4434         memcpy(sid, buf, sizeof(struct ctdb_server_id));
4435         return 0;
4436 }
4437
4438 size_t ctdb_g_lock_len(struct ctdb_g_lock *lock)
4439 {
4440         return sizeof(struct ctdb_g_lock);
4441 }
4442
4443 void ctdb_g_lock_push(struct ctdb_g_lock *lock, uint8_t *buf)
4444 {
4445         memcpy(buf, lock, sizeof(struct ctdb_g_lock));
4446 }
4447
4448 int ctdb_g_lock_pull(uint8_t *buf, size_t buflen, struct ctdb_g_lock *lock)
4449 {
4450         if (buflen < sizeof(struct ctdb_g_lock)) {
4451                 return EMSGSIZE;
4452         }
4453
4454         memcpy(lock, buf, sizeof(struct ctdb_g_lock));
4455         return 0;
4456 }
4457
4458 size_t ctdb_g_lock_list_len(struct ctdb_g_lock_list *lock_list)
4459 {
4460         return lock_list->num * sizeof(struct ctdb_g_lock);
4461 }
4462
4463 void ctdb_g_lock_list_push(struct ctdb_g_lock_list *lock_list, uint8_t *buf)
4464 {
4465         size_t offset = 0;
4466         int i;
4467
4468         for (i=0; i<lock_list->num; i++) {
4469                 ctdb_g_lock_push(&lock_list->lock[i], &buf[offset]);
4470                 offset += sizeof(struct ctdb_g_lock);
4471         }
4472 }
4473
4474 int ctdb_g_lock_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
4475                           struct ctdb_g_lock_list **out)
4476 {
4477         struct ctdb_g_lock_list *lock_list;
4478         unsigned count;
4479         size_t offset;
4480         int ret, i;
4481
4482         lock_list = talloc_zero(mem_ctx, struct ctdb_g_lock_list);
4483         if (lock_list == NULL) {
4484                 return ENOMEM;
4485         }
4486
4487         count = buflen / sizeof(struct ctdb_g_lock);
4488         lock_list->lock = talloc_array(lock_list, struct ctdb_g_lock, count);
4489         if (lock_list->lock == NULL) {
4490                 talloc_free(lock_list);
4491                 return ENOMEM;
4492         }
4493
4494         offset = 0;
4495         for (i=0; i<count; i++) {
4496                 ret = ctdb_g_lock_pull(&buf[offset], buflen-offset,
4497                                        &lock_list->lock[i]);
4498                 if (ret != 0) {
4499                         talloc_free(lock_list);
4500                         return ret;
4501                 }
4502                 offset += sizeof(struct ctdb_g_lock);
4503         }
4504
4505         lock_list->num = count;
4506
4507         *out = lock_list;
4508         return 0;
4509 }