ctdb-protocol: Fix marshalling for ctdb_statistics
[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 struct ctdb_vnn_map_wire {
849         uint32_t generation;
850         uint32_t size;
851         uint32_t map[1];
852 };
853
854 size_t ctdb_vnn_map_len(struct ctdb_vnn_map *vnnmap)
855 {
856         return offsetof(struct ctdb_vnn_map, map) +
857                vnnmap->size * sizeof(uint32_t);
858 }
859
860 void ctdb_vnn_map_push(struct ctdb_vnn_map *vnnmap, uint8_t *buf)
861 {
862         struct ctdb_vnn_map_wire *wire = (struct ctdb_vnn_map_wire *)buf;
863
864         memcpy(wire, vnnmap, offsetof(struct ctdb_vnn_map, map));
865         memcpy(wire->map, vnnmap->map, vnnmap->size * sizeof(uint32_t));
866 }
867
868 int ctdb_vnn_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
869                       struct ctdb_vnn_map **out)
870 {
871         struct ctdb_vnn_map *vnnmap;
872         struct ctdb_vnn_map_wire *wire = (struct ctdb_vnn_map_wire *)buf;
873
874         if (buflen < offsetof(struct ctdb_vnn_map_wire, map)) {
875                 return EMSGSIZE;
876         }
877         if (wire->size > buflen / sizeof(uint32_t)) {
878                 return EMSGSIZE;
879         }
880         if (offsetof(struct ctdb_vnn_map_wire, map) +
881             wire->size * sizeof(uint32_t) <
882             offsetof(struct ctdb_vnn_map_wire, map)) {
883                     return EMSGSIZE;
884         }
885         if (buflen < offsetof(struct ctdb_vnn_map_wire, map) +
886                      wire->size * sizeof(uint32_t)) {
887                 return EMSGSIZE;
888         }
889
890         vnnmap = talloc(mem_ctx, struct ctdb_vnn_map);
891         if (vnnmap == NULL) {
892                 return ENOMEM;
893         }
894
895         memcpy(vnnmap, wire, offsetof(struct ctdb_vnn_map, map));
896
897         vnnmap->map = talloc_memdup(vnnmap, wire->map,
898                                     wire->size * sizeof(uint32_t));
899         if (vnnmap->map == NULL) {
900                 talloc_free(vnnmap);
901                 return ENOMEM;
902         }
903
904         *out = vnnmap;
905         return 0;
906 }
907
908 struct ctdb_dbid_map_wire {
909         uint32_t num;
910         struct ctdb_dbid dbs[1];
911 };
912
913 size_t ctdb_dbid_map_len(struct ctdb_dbid_map *dbmap)
914 {
915         return sizeof(uint32_t) + dbmap->num * sizeof(struct ctdb_dbid);
916 }
917
918 void ctdb_dbid_map_push(struct ctdb_dbid_map *dbmap, uint8_t *buf)
919 {
920         struct ctdb_dbid_map_wire *wire = (struct ctdb_dbid_map_wire *)buf;
921
922         wire->num = dbmap->num;
923         memcpy(wire->dbs, dbmap->dbs, dbmap->num * sizeof(struct ctdb_dbid));
924 }
925
926 int ctdb_dbid_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
927                        struct ctdb_dbid_map **out)
928 {
929         struct ctdb_dbid_map *dbmap;
930         struct ctdb_dbid_map_wire *wire = (struct ctdb_dbid_map_wire *)buf;
931
932         if (buflen < sizeof(uint32_t)) {
933                 return EMSGSIZE;
934         }
935         if (wire->num > buflen / sizeof(struct ctdb_dbid)) {
936                 return EMSGSIZE;
937         }
938         if (sizeof(uint32_t) + wire->num * sizeof(struct ctdb_dbid) <
939             sizeof(uint32_t)) {
940                 return EMSGSIZE;
941         }
942         if (buflen < sizeof(uint32_t) + wire->num * sizeof(struct ctdb_dbid)) {
943                 return EMSGSIZE;
944         }
945
946         dbmap = talloc(mem_ctx, struct ctdb_dbid_map);
947         if (dbmap == NULL) {
948                 return ENOMEM;
949         }
950
951         dbmap->num = wire->num;
952
953         dbmap->dbs = talloc_memdup(dbmap, wire->dbs,
954                                    wire->num * sizeof(struct ctdb_dbid));
955         if (dbmap->dbs == NULL) {
956                 talloc_free(dbmap);
957                 return ENOMEM;
958         }
959
960         *out = dbmap;
961         return 0;
962 }
963
964 size_t ctdb_pulldb_len(struct ctdb_pulldb *pulldb)
965 {
966         return sizeof(struct ctdb_pulldb);
967 }
968
969 void ctdb_pulldb_push(struct ctdb_pulldb *pulldb, uint8_t *buf)
970 {
971         memcpy(buf, pulldb, sizeof(struct ctdb_pulldb));
972 }
973
974 int ctdb_pulldb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
975                      struct ctdb_pulldb **out)
976 {
977         struct ctdb_pulldb *pulldb;
978
979         if (buflen < sizeof(struct ctdb_pulldb)) {
980                 return EMSGSIZE;
981         }
982
983         pulldb = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_pulldb));
984         if (pulldb == NULL) {
985                 return ENOMEM;
986         }
987
988         *out = pulldb;
989         return 0;
990 }
991
992 size_t ctdb_pulldb_ext_len(struct ctdb_pulldb_ext *pulldb)
993 {
994         return sizeof(struct ctdb_pulldb_ext);
995 }
996
997 void ctdb_pulldb_ext_push(struct ctdb_pulldb_ext *pulldb, uint8_t *buf)
998 {
999         memcpy(buf, pulldb, sizeof(struct ctdb_pulldb_ext));
1000 }
1001
1002 int ctdb_pulldb_ext_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1003                          struct ctdb_pulldb_ext **out)
1004 {
1005         struct ctdb_pulldb_ext *pulldb;
1006
1007         if (buflen < sizeof(struct ctdb_pulldb_ext)) {
1008                 return EMSGSIZE;
1009         }
1010
1011         pulldb = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_pulldb_ext));
1012         if (pulldb == NULL) {
1013                 return ENOMEM;
1014         }
1015
1016         *out = pulldb;
1017         return 0;
1018 }
1019
1020 size_t ctdb_ltdb_header_len(struct ctdb_ltdb_header *header)
1021 {
1022         return sizeof(struct ctdb_ltdb_header);
1023 }
1024
1025 void ctdb_ltdb_header_push(struct ctdb_ltdb_header *header, uint8_t *buf)
1026 {
1027         memcpy(buf, header, sizeof(struct ctdb_ltdb_header));
1028 }
1029
1030 int ctdb_ltdb_header_pull(uint8_t *buf, size_t buflen,
1031                           struct ctdb_ltdb_header *header)
1032 {
1033         if (buflen < sizeof(struct ctdb_ltdb_header)) {
1034                 return EMSGSIZE;
1035         }
1036
1037         memcpy(header, buf, sizeof(struct ctdb_ltdb_header));
1038         return 0;
1039 }
1040
1041 int ctdb_ltdb_header_extract(TDB_DATA *data, struct ctdb_ltdb_header *header)
1042 {
1043         int ret;
1044
1045         ret = ctdb_ltdb_header_pull(data->dptr, data->dsize, header);
1046         if (ret != 0) {
1047                 return ret;
1048         }
1049
1050         data->dptr += sizeof(struct ctdb_ltdb_header);
1051         data->dsize -= sizeof(struct ctdb_ltdb_header);
1052
1053         return 0;
1054 }
1055
1056 struct ctdb_rec_data_wire {
1057         uint32_t length;
1058         uint32_t reqid;
1059         uint32_t keylen;
1060         uint32_t datalen;
1061         uint8_t data[1];
1062 };
1063
1064 size_t ctdb_rec_data_len(struct ctdb_rec_data *rec)
1065 {
1066         return offsetof(struct ctdb_rec_data_wire, data) +
1067                rec->key.dsize + rec->data.dsize +
1068                (rec->header == NULL ? 0 : sizeof(struct ctdb_ltdb_header));
1069 }
1070
1071 void ctdb_rec_data_push(struct ctdb_rec_data *rec, uint8_t *buf)
1072 {
1073         struct ctdb_rec_data_wire *wire = (struct ctdb_rec_data_wire *)buf;
1074         size_t offset;
1075
1076         wire->length = ctdb_rec_data_len(rec);
1077         wire->reqid = rec->reqid;
1078         wire->keylen = rec->key.dsize;
1079         wire->datalen = rec->data.dsize;
1080         if (rec->header != NULL) {
1081                 wire->datalen += sizeof(struct ctdb_ltdb_header);
1082         }
1083
1084         memcpy(wire->data, rec->key.dptr, rec->key.dsize);
1085         offset = rec->key.dsize;
1086         if (rec->header != NULL) {
1087                 memcpy(&wire->data[offset], rec->header,
1088                        sizeof(struct ctdb_ltdb_header));
1089                 offset += sizeof(struct ctdb_ltdb_header);
1090         }
1091         if (rec->data.dsize > 0) {
1092                 memcpy(&wire->data[offset], rec->data.dptr, rec->data.dsize);
1093         }
1094 }
1095
1096 static int ctdb_rec_data_pull_data(uint8_t *buf, size_t buflen,
1097                                    uint32_t *reqid,
1098                                    struct ctdb_ltdb_header **header,
1099                                    TDB_DATA *key, TDB_DATA *data,
1100                                    size_t *reclen)
1101 {
1102         struct ctdb_rec_data_wire *wire = (struct ctdb_rec_data_wire *)buf;
1103         size_t offset;
1104
1105         if (buflen < offsetof(struct ctdb_rec_data_wire, data)) {
1106                 return EMSGSIZE;
1107         }
1108         if (wire->keylen > buflen || wire->datalen > buflen) {
1109                 return EMSGSIZE;
1110         }
1111         if (offsetof(struct ctdb_rec_data_wire, data) + wire->keylen <
1112             offsetof(struct ctdb_rec_data_wire, data)) {
1113                 return EMSGSIZE;
1114         }
1115         if (offsetof(struct ctdb_rec_data_wire, data) +
1116                 wire->keylen + wire->datalen <
1117             offsetof(struct ctdb_rec_data_wire, data)) {
1118                 return EMSGSIZE;
1119         }
1120         if (buflen < offsetof(struct ctdb_rec_data_wire, data) +
1121                         wire->keylen + wire->datalen) {
1122                 return EMSGSIZE;
1123         }
1124
1125         *reqid = wire->reqid;
1126
1127         key->dsize = wire->keylen;
1128         key->dptr = wire->data;
1129         offset = wire->keylen;
1130
1131         /* Always set header to NULL.  If it is required, exact it using
1132          * ctdb_rec_data_extract_header()
1133          */
1134         *header = NULL;
1135
1136         data->dsize = wire->datalen;
1137         data->dptr = &wire->data[offset];
1138
1139         *reclen = offsetof(struct ctdb_rec_data_wire, data) +
1140                         wire->keylen + wire->datalen;
1141
1142         return 0;
1143 }
1144
1145 static int ctdb_rec_data_pull_elems(uint8_t *buf, size_t buflen,
1146                                     TALLOC_CTX *mem_ctx,
1147                                     struct ctdb_rec_data *out)
1148 {
1149         uint32_t reqid;
1150         struct ctdb_ltdb_header *header;
1151         TDB_DATA key, data;
1152         size_t reclen;
1153         int ret;
1154
1155         ret = ctdb_rec_data_pull_data(buf, buflen, &reqid, &header,
1156                                       &key, &data, &reclen);
1157         if (ret != 0) {
1158                 return ret;
1159         }
1160
1161         out->reqid = reqid;
1162         out->header = NULL;
1163
1164         out->key.dsize = key.dsize;
1165         if (key.dsize > 0) {
1166                 out->key.dptr = talloc_memdup(mem_ctx, key.dptr, key.dsize);
1167                 if (out->key.dptr == NULL) {
1168                         return ENOMEM;
1169                 }
1170         }
1171
1172         out->data.dsize = data.dsize;
1173         if (data.dsize > 0) {
1174                 out->data.dptr = talloc_memdup(mem_ctx, data.dptr, data.dsize);
1175                 if (out->data.dptr == NULL) {
1176                         return ENOMEM;
1177                 }
1178         }
1179
1180         return 0;
1181 }
1182
1183 int ctdb_rec_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1184                        struct ctdb_rec_data **out)
1185 {
1186         struct ctdb_rec_data *rec;
1187         int ret;
1188
1189         rec = talloc(mem_ctx, struct ctdb_rec_data);
1190         if (rec == NULL) {
1191                 return ENOMEM;
1192         }
1193
1194         ret = ctdb_rec_data_pull_elems(buf, buflen, rec, rec);
1195         if (ret != 0) {
1196                 TALLOC_FREE(rec);
1197         }
1198
1199         *out = rec;
1200         return ret;
1201 }
1202
1203 struct ctdb_rec_buffer_wire {
1204         uint32_t db_id;
1205         uint32_t count;
1206         uint8_t data[1];
1207 };
1208
1209 size_t ctdb_rec_buffer_len(struct ctdb_rec_buffer *recbuf)
1210 {
1211         return offsetof(struct ctdb_rec_buffer_wire, data) + recbuf->buflen;
1212 }
1213
1214 void ctdb_rec_buffer_push(struct ctdb_rec_buffer *recbuf, uint8_t *buf)
1215 {
1216         struct ctdb_rec_buffer_wire *wire = (struct ctdb_rec_buffer_wire *)buf;
1217
1218         wire->db_id = recbuf->db_id;
1219         wire->count = recbuf->count;
1220         if (recbuf->buflen > 0) {
1221                 memcpy(wire->data, recbuf->buf, recbuf->buflen);
1222         }
1223 }
1224
1225 int ctdb_rec_buffer_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1226                          struct ctdb_rec_buffer **out)
1227 {
1228         struct ctdb_rec_buffer *recbuf;
1229         struct ctdb_rec_buffer_wire *wire = (struct ctdb_rec_buffer_wire *)buf;
1230         size_t offset;
1231
1232         if (buflen < offsetof(struct ctdb_rec_buffer_wire, data)) {
1233                 return EMSGSIZE;
1234         }
1235
1236         recbuf = talloc(mem_ctx, struct ctdb_rec_buffer);
1237         if (recbuf == NULL) {
1238                 return ENOMEM;
1239         }
1240
1241         recbuf->db_id = wire->db_id;
1242         recbuf->count = wire->count;
1243
1244         offset = offsetof(struct ctdb_rec_buffer_wire, data);
1245         recbuf->buflen = buflen - offset;
1246         recbuf->buf = talloc_memdup(recbuf, wire->data, recbuf->buflen);
1247         if (recbuf->buf == NULL) {
1248                 talloc_free(recbuf);
1249                 return ENOMEM;
1250         }
1251
1252         *out = recbuf;
1253         return 0;
1254 }
1255
1256 struct ctdb_rec_buffer *ctdb_rec_buffer_init(TALLOC_CTX *mem_ctx,
1257                                              uint32_t db_id)
1258 {
1259         struct ctdb_rec_buffer *recbuf;
1260
1261         recbuf = talloc_zero(mem_ctx, struct ctdb_rec_buffer);
1262         if (recbuf == NULL) {
1263                 return recbuf;
1264         }
1265
1266         recbuf->db_id = db_id;
1267
1268         return recbuf;
1269 }
1270
1271 int ctdb_rec_buffer_add(TALLOC_CTX *mem_ctx, struct ctdb_rec_buffer *recbuf,
1272                         uint32_t reqid, struct ctdb_ltdb_header *header,
1273                         TDB_DATA key, TDB_DATA data)
1274 {
1275         struct ctdb_rec_data recdata;
1276         size_t len;
1277         uint8_t *ptr;
1278
1279         recdata.reqid = reqid;
1280         recdata.header = header;
1281         recdata.key = key;
1282         recdata.data = data;
1283
1284         len = ctdb_rec_data_len(&recdata);
1285
1286         ptr = talloc_realloc(mem_ctx, recbuf->buf, uint8_t,
1287                              recbuf->buflen + len);
1288         if (ptr == NULL) {
1289                 return ENOMEM;
1290         }
1291
1292         ctdb_rec_data_push(&recdata, &ptr[recbuf->buflen]);
1293
1294         recbuf->count++;
1295         recbuf->buf = ptr;
1296         recbuf->buflen += len;
1297         return 0;
1298 }
1299
1300 int ctdb_rec_buffer_traverse(struct ctdb_rec_buffer *recbuf,
1301                              ctdb_rec_parser_func_t func,
1302                              void *private_data)
1303 {
1304         struct ctdb_ltdb_header *header;
1305         TDB_DATA key, data;
1306         uint32_t reqid;
1307         size_t offset, reclen;
1308         int ret = 0, i;
1309
1310         offset = 0;
1311         for (i=0; i<recbuf->count; i++) {
1312                 ret = ctdb_rec_data_pull_data(&recbuf->buf[offset],
1313                                               recbuf->buflen - offset,
1314                                               &reqid, &header,
1315                                               &key, &data, &reclen);
1316                 if (ret != 0) {
1317                         return ret;
1318                 }
1319
1320                 ret = func(reqid, header, key, data, private_data);
1321                 if (ret != 0) {
1322                         break;
1323                 }
1324
1325                 offset += reclen;
1326         }
1327
1328         return ret;
1329 }
1330
1331 int ctdb_rec_buffer_write(struct ctdb_rec_buffer *recbuf, int fd)
1332 {
1333         ssize_t n;
1334
1335         n = write(fd, &recbuf->db_id, sizeof(uint32_t));
1336         if (n == -1 || n != sizeof(uint32_t)) {
1337                 return (errno != 0 ? errno : EIO);
1338         }
1339         n = write(fd, &recbuf->count, sizeof(uint32_t));
1340         if (n == -1 || n != sizeof(uint32_t)) {
1341                 return (errno != 0 ? errno : EIO);
1342         }
1343         n = write(fd, &recbuf->buflen, sizeof(size_t));
1344         if (n == -1 || n != sizeof(size_t)) {
1345                 return (errno != 0 ? errno : EIO);
1346         }
1347         n = write(fd, recbuf->buf, recbuf->buflen);
1348         if (n == -1 || n != recbuf->buflen) {
1349                 return (errno != 0 ? errno : EIO);
1350         }
1351
1352         return 0;
1353 }
1354
1355 int ctdb_rec_buffer_read(int fd, TALLOC_CTX *mem_ctx,
1356                          struct ctdb_rec_buffer **out)
1357 {
1358         struct ctdb_rec_buffer *recbuf;
1359         ssize_t n;
1360
1361         recbuf = talloc(mem_ctx, struct ctdb_rec_buffer);
1362         if (recbuf == NULL) {
1363                 return ENOMEM;
1364         }
1365
1366         n = read(fd, &recbuf->db_id, sizeof(uint32_t));
1367         if (n == -1 || n != sizeof(uint32_t)) {
1368                 return (errno != 0 ? errno : EIO);
1369         }
1370         n = read(fd, &recbuf->count, sizeof(uint32_t));
1371         if (n == -1 || n != sizeof(uint32_t)) {
1372                 return (errno != 0 ? errno : EIO);
1373         }
1374         n = read(fd, &recbuf->buflen, sizeof(size_t));
1375         if (n == -1 || n != sizeof(size_t)) {
1376                 return (errno != 0 ? errno : EIO);
1377         }
1378
1379         recbuf->buf = talloc_size(recbuf, recbuf->buflen);
1380         if (recbuf->buf == NULL) {
1381                 return ENOMEM;
1382         }
1383
1384         n = read(fd, recbuf->buf, recbuf->buflen);
1385         if (n == -1 || n != recbuf->buflen) {
1386                 return (errno != 0 ? errno : EIO);
1387         }
1388
1389         *out = recbuf;
1390         return 0;
1391 }
1392
1393 size_t ctdb_traverse_start_len(struct ctdb_traverse_start *traverse)
1394 {
1395         return sizeof(struct ctdb_traverse_start);
1396 }
1397
1398 void ctdb_traverse_start_push(struct ctdb_traverse_start *traverse,
1399                               uint8_t *buf)
1400 {
1401         memcpy(buf, traverse, sizeof(struct ctdb_traverse_start));
1402 }
1403
1404 int ctdb_traverse_start_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1405                              struct ctdb_traverse_start **out)
1406 {
1407         struct ctdb_traverse_start *traverse;
1408
1409         if (buflen < sizeof(struct ctdb_traverse_start)) {
1410                 return EMSGSIZE;
1411         }
1412
1413         traverse = talloc_memdup(mem_ctx, buf,
1414                                  sizeof(struct ctdb_traverse_start));
1415         if (traverse == NULL) {
1416                 return ENOMEM;
1417         }
1418
1419         *out = traverse;
1420         return 0;
1421 }
1422
1423 size_t ctdb_traverse_all_len(struct ctdb_traverse_all *traverse)
1424 {
1425         return sizeof(struct ctdb_traverse_all);
1426 }
1427
1428 void ctdb_traverse_all_push(struct ctdb_traverse_all *traverse, uint8_t *buf)
1429 {
1430         memcpy(buf, traverse, sizeof(struct ctdb_traverse_all));
1431 }
1432
1433 int ctdb_traverse_all_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1434                            struct ctdb_traverse_all **out)
1435 {
1436         struct ctdb_traverse_all *traverse;
1437
1438         if (buflen < sizeof(struct ctdb_traverse_all)) {
1439                 return EMSGSIZE;
1440         }
1441
1442         traverse = talloc_memdup(mem_ctx, buf,
1443                                  sizeof(struct ctdb_traverse_all));
1444         if (traverse == NULL) {
1445                 return ENOMEM;
1446         }
1447
1448         *out = traverse;
1449         return 0;
1450 }
1451
1452 size_t ctdb_traverse_start_ext_len(struct ctdb_traverse_start_ext *traverse)
1453 {
1454         return sizeof(struct ctdb_traverse_start_ext);
1455 }
1456
1457 void ctdb_traverse_start_ext_push(struct ctdb_traverse_start_ext *traverse,
1458                                   uint8_t *buf)
1459 {
1460         memcpy(buf, traverse, sizeof(struct ctdb_traverse_start_ext));
1461 }
1462
1463 int ctdb_traverse_start_ext_pull(uint8_t *buf, size_t buflen,
1464                                  TALLOC_CTX *mem_ctx,
1465                                  struct ctdb_traverse_start_ext **out)
1466 {
1467         struct ctdb_traverse_start_ext *traverse;
1468
1469         if (buflen < sizeof(struct ctdb_traverse_start_ext)) {
1470                 return EMSGSIZE;
1471         }
1472
1473         traverse = talloc_memdup(mem_ctx, buf,
1474                                  sizeof(struct ctdb_traverse_start_ext));
1475         if (traverse == NULL) {
1476                 return ENOMEM;
1477         }
1478
1479         *out = traverse;
1480         return 0;
1481 }
1482
1483 size_t ctdb_traverse_all_ext_len(struct ctdb_traverse_all_ext *traverse)
1484 {
1485         return sizeof(struct ctdb_traverse_all_ext);
1486 }
1487
1488 void ctdb_traverse_all_ext_push(struct ctdb_traverse_all_ext *traverse,
1489                                 uint8_t *buf)
1490 {
1491         memcpy(buf, traverse, sizeof(struct ctdb_traverse_all_ext));
1492 }
1493
1494 int ctdb_traverse_all_ext_pull(uint8_t *buf, size_t buflen,
1495                                TALLOC_CTX *mem_ctx,
1496                                struct ctdb_traverse_all_ext **out)
1497 {
1498         struct ctdb_traverse_all_ext *traverse;
1499
1500         if (buflen < sizeof(struct ctdb_traverse_all_ext)) {
1501                 return EMSGSIZE;
1502         }
1503
1504         traverse = talloc_memdup(mem_ctx, buf,
1505                                  sizeof(struct ctdb_traverse_all_ext));
1506         if (traverse == NULL) {
1507                 return ENOMEM;
1508         }
1509
1510         *out = traverse;
1511         return 0;
1512 }
1513
1514 size_t ctdb_sock_addr_len(ctdb_sock_addr *addr)
1515 {
1516         return sizeof(ctdb_sock_addr);
1517 }
1518
1519 void ctdb_sock_addr_push(ctdb_sock_addr *addr, uint8_t *buf)
1520 {
1521         memcpy(buf, addr, sizeof(ctdb_sock_addr));
1522 }
1523
1524 static int ctdb_sock_addr_pull_elems(uint8_t *buf, size_t buflen,
1525                                      TALLOC_CTX *mem_ctx, ctdb_sock_addr *out)
1526 {
1527         if (buflen < sizeof(ctdb_sock_addr)) {
1528                 return EMSGSIZE;
1529         }
1530
1531         memcpy(out, buf, sizeof(ctdb_sock_addr));
1532
1533         return 0;
1534 }
1535
1536 int ctdb_sock_addr_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1537                         ctdb_sock_addr **out)
1538 {
1539         ctdb_sock_addr *addr;
1540         int ret;
1541
1542         addr = talloc(mem_ctx, ctdb_sock_addr);
1543         if (addr == NULL) {
1544                 return false;
1545         }
1546
1547         ret = ctdb_sock_addr_pull_elems(buf, buflen, addr, addr);
1548         if (ret != 0) {
1549                 TALLOC_FREE(addr);
1550         }
1551
1552         *out = addr;
1553         return ret;
1554 }
1555
1556 size_t ctdb_connection_len(struct ctdb_connection *conn)
1557 {
1558         return sizeof(struct ctdb_connection);
1559 }
1560
1561 void ctdb_connection_push(struct ctdb_connection *conn, uint8_t *buf)
1562 {
1563         memcpy(buf, conn, sizeof(struct ctdb_connection));
1564 }
1565
1566 static int ctdb_connection_pull_elems(uint8_t *buf, size_t buflen,
1567                                       TALLOC_CTX *mem_ctx,
1568                                       struct ctdb_connection *out)
1569 {
1570         if (buflen < sizeof(struct ctdb_connection)) {
1571                 return EMSGSIZE;
1572         }
1573
1574         memcpy(out, buf, sizeof(struct ctdb_connection));
1575
1576         return 0;
1577 }
1578
1579 int ctdb_connection_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1580                          struct ctdb_connection **out)
1581 {
1582         struct ctdb_connection *conn;
1583         int ret;
1584
1585         conn = talloc(mem_ctx, struct ctdb_connection);
1586         if (conn == NULL) {
1587                 return ENOMEM;
1588         }
1589
1590         ret = ctdb_connection_pull_elems(buf, buflen, conn, conn);
1591         if (ret != 0) {
1592                 TALLOC_FREE(conn);
1593         }
1594
1595         *out = conn;
1596         return ret;
1597 }
1598
1599 struct ctdb_tunable_wire {
1600         uint32_t value;
1601         uint32_t length;
1602         uint8_t name[1];
1603 };
1604
1605 size_t ctdb_tunable_len(struct ctdb_tunable *tunable)
1606 {
1607         return offsetof(struct ctdb_tunable_wire, name) +
1608                strlen(tunable->name) + 1;
1609 }
1610
1611 void ctdb_tunable_push(struct ctdb_tunable *tunable, uint8_t *buf)
1612 {
1613         struct ctdb_tunable_wire *wire = (struct ctdb_tunable_wire *)buf;
1614
1615         wire->value = tunable->value;
1616         wire->length = strlen(tunable->name) + 1;
1617         memcpy(wire->name, tunable->name, wire->length);
1618 }
1619
1620 int ctdb_tunable_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1621                       struct ctdb_tunable **out)
1622 {
1623         struct ctdb_tunable *tunable;
1624         struct ctdb_tunable_wire *wire = (struct ctdb_tunable_wire *)buf;
1625
1626         if (buflen < offsetof(struct ctdb_tunable_wire, name)) {
1627                 return EMSGSIZE;
1628         }
1629         if (wire->length > buflen) {
1630                 return EMSGSIZE;
1631         }
1632         if (offsetof(struct ctdb_tunable_wire, name) + wire->length <
1633             offsetof(struct ctdb_tunable_wire, name)) {
1634                 return EMSGSIZE;
1635         }
1636         if (buflen < offsetof(struct ctdb_tunable_wire, name) + wire->length) {
1637                 return EMSGSIZE;
1638         }
1639
1640         tunable = talloc(mem_ctx, struct ctdb_tunable);
1641         if (tunable == NULL) {
1642                 return ENOMEM;
1643         }
1644
1645         tunable->value = wire->value;
1646         tunable->name = talloc_memdup(tunable, wire->name, wire->length);
1647         if (tunable->name == NULL) {
1648                 talloc_free(tunable);
1649                 return ENOMEM;
1650         }
1651
1652         *out = tunable;
1653         return 0;
1654 }
1655
1656 size_t ctdb_node_flag_change_len(struct ctdb_node_flag_change *flag_change)
1657 {
1658         return sizeof(struct ctdb_node_flag_change);
1659 }
1660
1661 void ctdb_node_flag_change_push(struct ctdb_node_flag_change *flag_change,
1662                                 uint8_t *buf)
1663 {
1664         memcpy(buf, flag_change, sizeof(struct ctdb_node_flag_change));
1665 }
1666
1667 int ctdb_node_flag_change_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1668                                struct ctdb_node_flag_change **out)
1669 {
1670         struct ctdb_node_flag_change *flag_change;
1671
1672         if (buflen < sizeof(struct ctdb_node_flag_change)) {
1673                 return EMSGSIZE;
1674         }
1675
1676         flag_change = talloc_memdup(mem_ctx, buf,
1677                                     sizeof(struct ctdb_node_flag_change));
1678         if (flag_change == NULL) {
1679                 return ENOMEM;
1680         }
1681
1682         *out = flag_change;
1683         return 0;
1684 }
1685
1686 struct ctdb_var_list_wire {
1687         uint32_t length;
1688         char list_str[1];
1689 };
1690
1691 size_t ctdb_var_list_len(struct ctdb_var_list *var_list)
1692 {
1693         int i;
1694         size_t len = sizeof(uint32_t);
1695
1696         for (i=0; i<var_list->count; i++) {
1697                 len += strlen(var_list->var[i]) + 1;
1698         }
1699         return len;
1700 }
1701
1702 void ctdb_var_list_push(struct ctdb_var_list *var_list, uint8_t *buf)
1703 {
1704         struct ctdb_var_list_wire *wire = (struct ctdb_var_list_wire *)buf;
1705         int i, n;
1706         size_t offset = 0;
1707
1708         if (var_list->count > 0) {
1709                 n = sprintf(wire->list_str, "%s", var_list->var[0]);
1710                 offset += n;
1711         }
1712         for (i=1; i<var_list->count; i++) {
1713                 n = sprintf(&wire->list_str[offset], ":%s", var_list->var[i]);
1714                 offset += n;
1715         }
1716         wire->length = offset + 1;
1717 }
1718
1719 int ctdb_var_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1720                        struct ctdb_var_list **out)
1721 {
1722         struct ctdb_var_list *var_list = NULL;
1723         struct ctdb_var_list_wire *wire = (struct ctdb_var_list_wire *)buf;
1724         char *str, *s, *tok, *ptr;
1725         const char **list;
1726
1727         if (buflen < sizeof(uint32_t)) {
1728                 return EMSGSIZE;
1729         }
1730         if (wire->length > buflen) {
1731                 return EMSGSIZE;
1732         }
1733         if (sizeof(uint32_t) + wire->length < sizeof(uint32_t)) {
1734                 return EMSGSIZE;
1735         }
1736         if (buflen < sizeof(uint32_t) + wire->length) {
1737                 return EMSGSIZE;
1738         }
1739
1740         str = talloc_strndup(mem_ctx, (char *)wire->list_str, wire->length);
1741         if (str == NULL) {
1742                 return ENOMEM;
1743         }
1744
1745         var_list = talloc_zero(mem_ctx, struct ctdb_var_list);
1746         if (var_list == NULL) {
1747                 goto fail;
1748         }
1749
1750         s = str;
1751         while ((tok = strtok_r(s, ":", &ptr)) != NULL) {
1752                 s = NULL;
1753                 list = talloc_realloc(var_list, var_list->var, const char *,
1754                                       var_list->count+1);
1755                 if (list == NULL) {
1756                         goto fail;
1757                 }
1758
1759                 var_list->var = list;
1760                 var_list->var[var_list->count] = talloc_strdup(var_list, tok);
1761                 if (var_list->var[var_list->count] == NULL) {
1762                         goto fail;
1763                 }
1764                 var_list->count++;
1765         }
1766
1767         talloc_free(str);
1768         *out = var_list;
1769         return 0;
1770
1771 fail:
1772         talloc_free(str);
1773         talloc_free(var_list);
1774         return ENOMEM;
1775 }
1776
1777 size_t ctdb_tunable_list_len(struct ctdb_tunable_list *tun_list)
1778 {
1779         return sizeof(struct ctdb_tunable_list);
1780 }
1781
1782 void ctdb_tunable_list_push(struct ctdb_tunable_list *tun_list, uint8_t *buf)
1783 {
1784         memcpy(buf, tun_list, sizeof(struct ctdb_tunable_list));
1785 }
1786
1787 int ctdb_tunable_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1788                            struct ctdb_tunable_list **out)
1789 {
1790         struct ctdb_tunable_list *tun_list;
1791
1792         if (buflen < sizeof(struct ctdb_tunable_list)) {
1793                 return EMSGSIZE;
1794         }
1795
1796         tun_list = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_tunable_list));
1797         if (tun_list == NULL) {
1798                 return ENOMEM;
1799         }
1800
1801         *out = tun_list;
1802         return 0;
1803 }
1804
1805 struct ctdb_tickle_list_wire {
1806         ctdb_sock_addr addr;
1807         uint32_t num;
1808         struct ctdb_connection conn[1];
1809 };
1810
1811 size_t ctdb_tickle_list_len(struct ctdb_tickle_list *tickles)
1812 {
1813         return offsetof(struct ctdb_tickle_list, conn) +
1814                tickles->num * sizeof(struct ctdb_connection);
1815 }
1816
1817 void ctdb_tickle_list_push(struct ctdb_tickle_list *tickles, uint8_t *buf)
1818 {
1819         struct ctdb_tickle_list_wire *wire =
1820                 (struct ctdb_tickle_list_wire *)buf;
1821         size_t offset;
1822         int i;
1823
1824         memcpy(&wire->addr, &tickles->addr, sizeof(ctdb_sock_addr));
1825         wire->num = tickles->num;
1826
1827         offset = offsetof(struct ctdb_tickle_list_wire, conn);
1828         for (i=0; i<tickles->num; i++) {
1829                 ctdb_connection_push(&tickles->conn[i], &buf[offset]);
1830                 offset += ctdb_connection_len(&tickles->conn[i]);
1831         }
1832 }
1833
1834 int ctdb_tickle_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1835                            struct ctdb_tickle_list **out)
1836 {
1837         struct ctdb_tickle_list *tickles;
1838         struct ctdb_tickle_list_wire *wire =
1839                 (struct ctdb_tickle_list_wire *)buf;
1840         size_t offset;
1841         int i, ret;
1842
1843         if (buflen < offsetof(struct ctdb_tickle_list_wire, conn)) {
1844                 return EMSGSIZE;
1845         }
1846         if (wire->num > buflen / sizeof(struct ctdb_connection)) {
1847                 return EMSGSIZE;
1848         }
1849         if (offsetof(struct ctdb_tickle_list_wire, conn) +
1850             wire->num * sizeof(struct ctdb_connection) <
1851             offsetof(struct ctdb_tickle_list_wire, conn)) {
1852                 return EMSGSIZE;
1853         }
1854         if (buflen < offsetof(struct ctdb_tickle_list_wire, conn) +
1855                      wire->num * sizeof(struct ctdb_connection)) {
1856                 return EMSGSIZE;
1857         }
1858
1859         tickles = talloc(mem_ctx, struct ctdb_tickle_list);
1860         if (tickles == NULL) {
1861                 return ENOMEM;
1862         }
1863
1864         offset = offsetof(struct ctdb_tickle_list, conn);
1865         memcpy(tickles, wire, offset);
1866
1867         tickles->conn = talloc_array(tickles, struct ctdb_connection,
1868                                      wire->num);
1869         if (tickles->conn == NULL) {
1870                 talloc_free(tickles);
1871                 return ENOMEM;
1872         }
1873
1874         for (i=0; i<wire->num; i++) {
1875                 ret = ctdb_connection_pull_elems(&buf[offset], buflen-offset,
1876                                                  tickles->conn,
1877                                                  &tickles->conn[i]);
1878                 if (ret != 0) {
1879                         talloc_free(tickles);
1880                         return ret;
1881                 }
1882                 offset += ctdb_connection_len(&tickles->conn[i]);
1883         }
1884
1885         *out = tickles;
1886         return 0;
1887 }
1888
1889 struct ctdb_addr_info_wire {
1890         ctdb_sock_addr addr;
1891         uint32_t mask;
1892         uint32_t len;
1893         char iface[1];
1894 };
1895
1896 size_t ctdb_addr_info_len(struct ctdb_addr_info *arp)
1897 {
1898         uint32_t len;
1899
1900         len = offsetof(struct ctdb_addr_info_wire, iface);
1901         if (arp->iface != NULL) {
1902                len += strlen(arp->iface)+1;
1903         }
1904
1905         return len;
1906 }
1907
1908 void ctdb_addr_info_push(struct ctdb_addr_info *addr_info, uint8_t *buf)
1909 {
1910         struct ctdb_addr_info_wire *wire = (struct ctdb_addr_info_wire *)buf;
1911
1912         wire->addr = addr_info->addr;
1913         wire->mask = addr_info->mask;
1914         if (addr_info->iface == NULL) {
1915                 wire->len = 0;
1916         } else {
1917                 wire->len = strlen(addr_info->iface)+1;
1918                 memcpy(wire->iface, addr_info->iface, wire->len);
1919         }
1920 }
1921
1922 int ctdb_addr_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1923                         struct ctdb_addr_info **out)
1924 {
1925         struct ctdb_addr_info *addr_info;
1926         struct ctdb_addr_info_wire *wire = (struct ctdb_addr_info_wire *)buf;
1927
1928         if (buflen < offsetof(struct ctdb_addr_info_wire, iface)) {
1929                 return EMSGSIZE;
1930         }
1931         if (wire->len > buflen) {
1932                 return EMSGSIZE;
1933         }
1934         if (offsetof(struct ctdb_addr_info_wire, iface) + wire->len <
1935             offsetof(struct ctdb_addr_info_wire, iface)) {
1936                 return EMSGSIZE;
1937         }
1938         if (buflen < offsetof(struct ctdb_addr_info_wire, iface) + wire->len) {
1939                 return EMSGSIZE;
1940         }
1941
1942         addr_info = talloc(mem_ctx, struct ctdb_addr_info);
1943         if (addr_info == NULL) {
1944                 return ENOMEM;
1945         }
1946
1947         addr_info->addr = wire->addr;
1948         addr_info->mask = wire->mask;
1949
1950         if (wire->len == 0) {
1951                 addr_info->iface = NULL;
1952         } else {
1953                 addr_info->iface = talloc_strndup(addr_info, wire->iface,
1954                                                   wire->len);
1955                 if (addr_info->iface == NULL) {
1956                         talloc_free(addr_info);
1957                         return ENOMEM;
1958                 }
1959         }
1960
1961         *out = addr_info;
1962         return 0;
1963 }
1964
1965 size_t ctdb_transdb_len(struct ctdb_transdb *transdb)
1966 {
1967         return sizeof(struct ctdb_transdb);
1968 }
1969
1970 void ctdb_transdb_push(struct ctdb_transdb *transdb, uint8_t *buf)
1971 {
1972         memcpy(buf, transdb, sizeof(struct ctdb_transdb));
1973 }
1974
1975 int ctdb_transdb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
1976                      struct ctdb_transdb **out)
1977 {
1978         struct ctdb_transdb *transdb;
1979
1980         if (buflen < sizeof(struct ctdb_transdb)) {
1981                 return EMSGSIZE;
1982         }
1983
1984         transdb = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_transdb));
1985         if (transdb == NULL) {
1986                 return ENOMEM;
1987         }
1988
1989         *out = transdb;
1990         return 0;
1991 }
1992
1993 size_t ctdb_uptime_len(struct ctdb_uptime *uptime)
1994 {
1995         return sizeof(struct ctdb_uptime);
1996 }
1997
1998 void ctdb_uptime_push(struct ctdb_uptime *uptime, uint8_t *buf)
1999 {
2000         memcpy(buf, uptime, sizeof(struct ctdb_uptime));
2001 }
2002
2003 int ctdb_uptime_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2004                      struct ctdb_uptime **out)
2005 {
2006         struct ctdb_uptime *uptime;
2007
2008         if (buflen < sizeof(struct ctdb_uptime)) {
2009                 return EMSGSIZE;
2010         }
2011
2012         uptime = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_uptime));
2013         if (uptime == NULL) {
2014                 return ENOMEM;
2015         }
2016
2017         *out = uptime;
2018         return 0;
2019 }
2020
2021 size_t ctdb_public_ip_len(struct ctdb_public_ip *pubip)
2022 {
2023         return sizeof(struct ctdb_public_ip);
2024 }
2025
2026 void ctdb_public_ip_push(struct ctdb_public_ip *pubip, uint8_t *buf)
2027 {
2028         memcpy(buf, pubip, sizeof(struct ctdb_public_ip));
2029 }
2030
2031 static int ctdb_public_ip_pull_elems(uint8_t *buf, size_t buflen,
2032                                      TALLOC_CTX *mem_ctx,
2033                                      struct ctdb_public_ip *out)
2034 {
2035         if (buflen < sizeof(struct ctdb_public_ip)) {
2036                 return EMSGSIZE;
2037         }
2038
2039         memcpy(out, buf, sizeof(struct ctdb_public_ip));
2040
2041         return 0;
2042 }
2043
2044 int ctdb_public_ip_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2045                         struct ctdb_public_ip **out)
2046 {
2047         struct ctdb_public_ip *pubip;
2048         int ret;
2049
2050         pubip = talloc(mem_ctx, struct ctdb_public_ip);
2051         if (pubip == NULL) {
2052                 return ENOMEM;
2053         }
2054
2055         ret = ctdb_public_ip_pull_elems(buf, buflen, pubip, pubip);
2056         if (ret != 0) {
2057                 TALLOC_FREE(pubip);
2058         }
2059
2060         *out = pubip;
2061         return ret;
2062 }
2063
2064 struct ctdb_public_ip_list_wire {
2065         uint32_t num;
2066         struct ctdb_public_ip ip[1];
2067 };
2068
2069 size_t ctdb_public_ip_list_len(struct ctdb_public_ip_list *pubip_list)
2070 {
2071         int i;
2072         size_t len;
2073
2074         len = sizeof(uint32_t);
2075         for (i=0; i<pubip_list->num; i++) {
2076                 len += ctdb_public_ip_len(&pubip_list->ip[i]);
2077         }
2078         return len;
2079 }
2080
2081 void ctdb_public_ip_list_push(struct ctdb_public_ip_list *pubip_list,
2082                               uint8_t *buf)
2083 {
2084         struct ctdb_public_ip_list_wire *wire =
2085                 (struct ctdb_public_ip_list_wire *)buf;
2086         size_t offset;
2087         int i;
2088
2089         wire->num = pubip_list->num;
2090
2091         offset = offsetof(struct ctdb_public_ip_list_wire, ip);
2092         for (i=0; i<pubip_list->num; i++) {
2093                 ctdb_public_ip_push(&pubip_list->ip[i], &buf[offset]);
2094                 offset += ctdb_public_ip_len(&pubip_list->ip[i]);
2095         }
2096 }
2097
2098 int ctdb_public_ip_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2099                              struct ctdb_public_ip_list **out)
2100 {
2101         struct ctdb_public_ip_list *pubip_list;
2102         struct ctdb_public_ip_list_wire *wire =
2103                 (struct ctdb_public_ip_list_wire *)buf;
2104         size_t offset;
2105         int i;
2106         bool ret;
2107
2108         if (buflen < sizeof(uint32_t)) {
2109                 return EMSGSIZE;
2110         }
2111         if (wire->num > buflen / sizeof(struct ctdb_public_ip)) {
2112                 return EMSGSIZE;
2113         }
2114         if (sizeof(uint32_t) + wire->num * sizeof(struct ctdb_public_ip) <
2115             sizeof(uint32_t)) {
2116                 return EMSGSIZE;
2117         }
2118         if (buflen < sizeof(uint32_t) +
2119                      wire->num * sizeof(struct ctdb_public_ip)) {
2120                 return EMSGSIZE;
2121         }
2122
2123         pubip_list = talloc(mem_ctx, struct ctdb_public_ip_list);
2124         if (pubip_list == NULL) {
2125                 return ENOMEM;
2126         }
2127
2128         pubip_list->num = wire->num;
2129         if (wire->num == 0) {
2130                 pubip_list->ip = NULL;
2131                 *out = pubip_list;
2132                 return 0;
2133         }
2134         pubip_list->ip = talloc_array(pubip_list, struct ctdb_public_ip,
2135                                       wire->num);
2136         if (pubip_list->ip == NULL) {
2137                 talloc_free(pubip_list);
2138                 return ENOMEM;
2139         }
2140
2141         offset = offsetof(struct ctdb_public_ip_list_wire, ip);
2142         for (i=0; i<wire->num; i++) {
2143                 ret = ctdb_public_ip_pull_elems(&buf[offset], buflen-offset,
2144                                                 pubip_list->ip,
2145                                                 &pubip_list->ip[i]);
2146                 if (ret != 0) {
2147                         talloc_free(pubip_list);
2148                         return ret;
2149                 }
2150                 offset += ctdb_public_ip_len(&pubip_list->ip[i]);
2151         }
2152
2153         *out = pubip_list;
2154         return 0;
2155 }
2156
2157 size_t ctdb_node_and_flags_len(struct ctdb_node_and_flags *node)
2158 {
2159         return sizeof(struct ctdb_node_and_flags);
2160 }
2161
2162 void ctdb_node_and_flags_push(struct ctdb_node_and_flags *node, uint8_t *buf)
2163 {
2164         memcpy(buf, node, sizeof(struct ctdb_node_and_flags));
2165 }
2166
2167 static int ctdb_node_and_flags_pull_elems(TALLOC_CTX *mem_ctx,
2168                                           uint8_t *buf, size_t buflen,
2169                                           struct ctdb_node_and_flags *out)
2170 {
2171         if (buflen < sizeof(struct ctdb_node_and_flags)) {
2172                 return EMSGSIZE;
2173         }
2174
2175         memcpy(out, buf, sizeof(struct ctdb_node_and_flags));
2176
2177         return 0;
2178 }
2179
2180 int ctdb_node_and_flags_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2181                               struct ctdb_node_and_flags **out)
2182 {
2183         struct ctdb_node_and_flags *node;
2184         int ret;
2185
2186         node = talloc(mem_ctx, struct ctdb_node_and_flags);
2187         if (node == NULL) {
2188                 return ENOMEM;
2189         }
2190
2191         ret = ctdb_node_and_flags_pull_elems(node, buf, buflen, node);
2192         if (ret != 0) {
2193                 TALLOC_FREE(node);
2194         }
2195
2196         *out = node;
2197         return ret;
2198 }
2199
2200 struct ctdb_node_map_wire {
2201         uint32_t num;
2202         struct ctdb_node_and_flags node[1];
2203 };
2204
2205 size_t ctdb_node_map_len(struct ctdb_node_map *nodemap)
2206 {
2207         return sizeof(uint32_t) +
2208                nodemap->num * sizeof(struct ctdb_node_and_flags);
2209 }
2210
2211 void ctdb_node_map_push(struct ctdb_node_map *nodemap, uint8_t *buf)
2212 {
2213         struct ctdb_node_map_wire *wire = (struct ctdb_node_map_wire *)buf;
2214         size_t offset;
2215         int i;
2216
2217         wire->num = nodemap->num;
2218
2219         offset = offsetof(struct ctdb_node_map_wire, node);
2220         for (i=0; i<nodemap->num; i++) {
2221                 ctdb_node_and_flags_push(&nodemap->node[i], &buf[offset]);
2222                 offset += ctdb_node_and_flags_len(&nodemap->node[i]);
2223         }
2224 }
2225
2226 int ctdb_node_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2227                        struct ctdb_node_map **out)
2228 {
2229         struct ctdb_node_map *nodemap;
2230         struct ctdb_node_map_wire *wire = (struct ctdb_node_map_wire *)buf;
2231         size_t offset;
2232         int i;
2233         bool ret;
2234
2235         if (buflen < sizeof(uint32_t)) {
2236                 return EMSGSIZE;
2237         }
2238         if (wire->num > buflen / sizeof(struct ctdb_node_and_flags)) {
2239                 return EMSGSIZE;
2240         }
2241         if (sizeof(uint32_t) + wire->num * sizeof(struct ctdb_node_and_flags) <
2242             sizeof(uint32_t)) {
2243                 return EMSGSIZE;
2244         }
2245         if (buflen < sizeof(uint32_t) +
2246                      wire->num * sizeof(struct ctdb_node_and_flags)) {
2247                 return EMSGSIZE;
2248         }
2249
2250         nodemap = talloc(mem_ctx, struct ctdb_node_map);
2251         if (nodemap == NULL) {
2252                 return ENOMEM;
2253         }
2254
2255         nodemap->num = wire->num;
2256         nodemap->node = talloc_array(nodemap, struct ctdb_node_and_flags,
2257                                      wire->num);
2258         if (nodemap->node == NULL) {
2259                 talloc_free(nodemap);
2260                 return ENOMEM;
2261         }
2262
2263         offset = offsetof(struct ctdb_node_map_wire, node);
2264         for (i=0; i<wire->num; i++) {
2265                 ret = ctdb_node_and_flags_pull_elems(nodemap->node,
2266                                                      &buf[offset],
2267                                                      buflen-offset,
2268                                                      &nodemap->node[i]);
2269                 if (ret != 0) {
2270                         talloc_free(nodemap);
2271                         return ret;
2272                 }
2273                 offset += ctdb_node_and_flags_len(&nodemap->node[i]);
2274         }
2275
2276         *out = nodemap;
2277         return 0;
2278 }
2279
2280 size_t ctdb_script_len(struct ctdb_script *script)
2281 {
2282         return sizeof(struct ctdb_script);
2283 }
2284
2285 void ctdb_script_push(struct ctdb_script *script, uint8_t *buf)
2286 {
2287         memcpy(buf, script, sizeof(struct ctdb_script));
2288 }
2289
2290 static int ctdb_script_pull_elems(uint8_t *buf, size_t buflen,
2291                                   TALLOC_CTX *mem_ctx,
2292                                   struct ctdb_script *out)
2293 {
2294         if (buflen < sizeof(struct ctdb_script)) {
2295                 return EMSGSIZE;
2296         }
2297
2298         memcpy(out, buf, sizeof(struct ctdb_script));
2299
2300         return 0;
2301 }
2302
2303 int ctdb_script_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2304                      struct ctdb_script **out)
2305 {
2306         struct ctdb_script *script;
2307         int ret;
2308
2309         script = talloc(mem_ctx, struct ctdb_script);
2310         if (script == NULL) {
2311                 return ENOMEM;
2312         }
2313
2314         ret = ctdb_script_pull_elems(buf, buflen, script, script);
2315         if (ret != 0) {
2316                 TALLOC_FREE(script);
2317         }
2318
2319         *out = script;
2320         return ret;
2321 }
2322
2323 struct ctdb_script_list_wire {
2324         uint32_t num_scripts;
2325         struct ctdb_script script[1];
2326 };
2327
2328 size_t ctdb_script_list_len(struct ctdb_script_list *script_list)
2329 {
2330         int i;
2331         size_t len;
2332
2333         if (script_list == NULL) {
2334                 return 0;
2335         }
2336
2337         len = offsetof(struct ctdb_script_list_wire, script);
2338         for (i=0; i<script_list->num_scripts; i++) {
2339                 len += ctdb_script_len(&script_list->script[i]);
2340         }
2341         return len;
2342 }
2343
2344 void ctdb_script_list_push(struct ctdb_script_list *script_list, uint8_t *buf)
2345 {
2346         struct ctdb_script_list_wire *wire =
2347                 (struct ctdb_script_list_wire *)buf;
2348         size_t offset;
2349         int i;
2350
2351         if (script_list == NULL) {
2352                 return;
2353         }
2354
2355         wire->num_scripts = script_list->num_scripts;
2356
2357         offset = offsetof(struct ctdb_script_list_wire, script);
2358         for (i=0; i<script_list->num_scripts; i++) {
2359                 ctdb_script_push(&script_list->script[i], &buf[offset]);
2360                 offset += ctdb_script_len(&script_list->script[i]);
2361         }
2362 }
2363
2364 int ctdb_script_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2365                           struct ctdb_script_list **out)
2366 {
2367         struct ctdb_script_list *script_list;
2368         struct ctdb_script_list_wire *wire =
2369                 (struct ctdb_script_list_wire *)buf;
2370         size_t offset;
2371         int i;
2372         bool ret;
2373
2374         /* If event scripts have never been run, the result will be NULL */
2375         if (buflen == 0) {
2376                 *out = NULL;
2377                 return 0;
2378         }
2379
2380         offset = offsetof(struct ctdb_script_list_wire, script);
2381
2382         if (buflen < offset) {
2383                 return EMSGSIZE;
2384         }
2385         if (wire->num_scripts > buflen / sizeof(struct ctdb_script)) {
2386                 return EMSGSIZE;
2387         }
2388         if (offset + wire->num_scripts * sizeof(struct ctdb_script) < offset) {
2389                 return EMSGSIZE;
2390         }
2391         if (buflen < offset + wire->num_scripts * sizeof(struct ctdb_script)) {
2392                 return EMSGSIZE;
2393         }
2394
2395         script_list = talloc(mem_ctx, struct ctdb_script_list);
2396         if (script_list == NULL) {
2397                 return ENOMEM;
2398
2399         }
2400
2401         script_list->num_scripts = wire->num_scripts;
2402         script_list->script = talloc_array(script_list, struct ctdb_script,
2403                                            wire->num_scripts);
2404         if (script_list->script == NULL) {
2405                 talloc_free(script_list);
2406                 return ENOMEM;
2407         }
2408
2409         for (i=0; i<wire->num_scripts; i++) {
2410                 ret = ctdb_script_pull_elems(&buf[offset], buflen-offset,
2411                                              script_list->script,
2412                                              &script_list->script[i]);
2413                 if (ret != 0) {
2414                         talloc_free(script_list);
2415                         return ret;
2416                 }
2417                 offset += ctdb_script_len(&script_list->script[i]);
2418         }
2419
2420         *out = script_list;
2421         return 0;
2422 }
2423
2424 size_t ctdb_ban_state_len(struct ctdb_ban_state *ban_state)
2425 {
2426         return sizeof(struct ctdb_ban_state);
2427 }
2428
2429 void ctdb_ban_state_push(struct ctdb_ban_state *ban_state, uint8_t *buf)
2430 {
2431         memcpy(buf, ban_state, sizeof(struct ctdb_ban_state));
2432 }
2433
2434 int ctdb_ban_state_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2435                         struct ctdb_ban_state **out)
2436 {
2437         struct ctdb_ban_state *ban_state;
2438
2439         if (buflen < sizeof(struct ctdb_ban_state)) {
2440                 return EMSGSIZE;
2441         }
2442
2443         ban_state = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_ban_state));
2444         if (ban_state == NULL) {
2445                 return ENOMEM;
2446         }
2447
2448         *out = ban_state;
2449         return 0;
2450 }
2451
2452 struct ctdb_notify_data_wire {
2453         uint64_t srvid;
2454         uint32_t len;
2455         uint8_t data[1];
2456 };
2457
2458 size_t ctdb_notify_data_len(struct ctdb_notify_data *notify)
2459 {
2460         return offsetof(struct ctdb_notify_data_wire, data) +
2461                notify->data.dsize;
2462 }
2463
2464 void ctdb_notify_data_push(struct ctdb_notify_data *notify, uint8_t *buf)
2465 {
2466         struct ctdb_notify_data_wire *wire =
2467                 (struct ctdb_notify_data_wire *)buf;
2468
2469         wire->srvid = notify->srvid;
2470         wire->len = notify->data.dsize;
2471         memcpy(wire->data, notify->data.dptr, notify->data.dsize);
2472 }
2473
2474 int ctdb_notify_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2475                           struct ctdb_notify_data **out)
2476 {
2477         struct ctdb_notify_data *notify;
2478         struct ctdb_notify_data_wire *wire =
2479                 (struct ctdb_notify_data_wire *)buf;
2480
2481         if (buflen < offsetof(struct ctdb_notify_data_wire, data)) {
2482                 return EMSGSIZE;
2483         }
2484         if (wire->len > buflen) {
2485                 return EMSGSIZE;
2486         }
2487         if (offsetof(struct ctdb_notify_data_wire, data) + wire->len <
2488             offsetof(struct ctdb_notify_data_wire, data)) {
2489                 return EMSGSIZE;
2490         }
2491         if (buflen < offsetof(struct ctdb_notify_data_wire, data) + wire->len) {
2492                 return EMSGSIZE;
2493         }
2494
2495         notify = talloc(mem_ctx, struct ctdb_notify_data);
2496         if (notify == NULL) {
2497                 return ENOMEM;
2498         }
2499
2500         notify->srvid = wire->srvid;
2501         notify->data.dsize = wire->len;
2502         notify->data.dptr = talloc_memdup(notify, wire->data, wire->len);
2503         if (notify->data.dptr == NULL) {
2504                 talloc_free(notify);
2505                 return ENOMEM;
2506         }
2507
2508         *out = notify;
2509         return 0;
2510 }
2511
2512 size_t ctdb_iface_len(struct ctdb_iface *iface)
2513 {
2514         return sizeof(struct ctdb_iface);
2515 }
2516
2517 void ctdb_iface_push(struct ctdb_iface *iface, uint8_t *buf)
2518 {
2519         memcpy(buf, iface, sizeof(struct ctdb_iface));
2520 }
2521
2522 static int ctdb_iface_pull_elems(uint8_t *buf, size_t buflen,
2523                                  TALLOC_CTX *mem_ctx,
2524                                  struct ctdb_iface *out)
2525 {
2526         if (buflen < sizeof(struct ctdb_iface)) {
2527                 return EMSGSIZE;
2528         }
2529
2530         memcpy(out, buf, sizeof(struct ctdb_iface));
2531
2532         return 0;
2533 }
2534
2535 int ctdb_iface_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2536                     struct ctdb_iface **out)
2537 {
2538         struct ctdb_iface *iface;
2539         int ret;
2540
2541         iface = talloc(mem_ctx, struct ctdb_iface);
2542         if (iface == NULL) {
2543                 return ENOMEM;
2544         }
2545
2546         ret = ctdb_iface_pull_elems(buf, buflen, iface, iface);
2547         if (ret != 0) {
2548                 TALLOC_FREE(iface);
2549         }
2550
2551         *out = iface;
2552         return ret;
2553 }
2554
2555 struct ctdb_iface_list_wire {
2556         uint32_t num;
2557         struct ctdb_iface iface[1];
2558 };
2559
2560 size_t ctdb_iface_list_len(struct ctdb_iface_list *iface_list)
2561 {
2562         return sizeof(uint32_t) +
2563                iface_list->num * sizeof(struct ctdb_iface);
2564 }
2565
2566 void ctdb_iface_list_push(struct ctdb_iface_list *iface_list, uint8_t *buf)
2567 {
2568         struct ctdb_iface_list_wire *wire =
2569                 (struct ctdb_iface_list_wire *)buf;
2570
2571         wire->num = iface_list->num;
2572         memcpy(wire->iface, iface_list->iface,
2573                iface_list->num * sizeof(struct ctdb_iface));
2574 }
2575
2576 int ctdb_iface_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2577                          struct ctdb_iface_list **out)
2578 {
2579         struct ctdb_iface_list *iface_list;
2580         struct ctdb_iface_list_wire *wire =
2581                 (struct ctdb_iface_list_wire *)buf;
2582
2583         if (buflen < sizeof(uint32_t)) {
2584                 return EMSGSIZE;
2585         }
2586         if (wire->num > buflen / sizeof(struct ctdb_iface)) {
2587                 return EMSGSIZE;
2588         }
2589         if (sizeof(uint32_t) + wire->num * sizeof(struct ctdb_iface) <
2590             sizeof(uint32_t)) {
2591                 return EMSGSIZE;
2592         }
2593         if (buflen < sizeof(uint32_t) + wire->num * sizeof(struct ctdb_iface)) {
2594                 return EMSGSIZE;
2595         }
2596
2597         iface_list = talloc(mem_ctx, struct ctdb_iface_list);
2598         if (iface_list == NULL) {
2599                 return ENOMEM;
2600         }
2601
2602         iface_list->num = wire->num;
2603         iface_list->iface = talloc_array(iface_list, struct ctdb_iface,
2604                                          wire->num);
2605         if (iface_list->iface == NULL) {
2606                 talloc_free(iface_list);
2607                 return ENOMEM;
2608         }
2609
2610         memcpy(iface_list->iface, wire->iface,
2611                wire->num * sizeof(struct ctdb_iface));
2612
2613         *out = iface_list;
2614         return 0;
2615 }
2616
2617 struct ctdb_public_ip_info_wire {
2618         struct ctdb_public_ip ip;
2619         uint32_t active_idx;
2620         uint32_t num;
2621         struct ctdb_iface ifaces[1];
2622 };
2623
2624 size_t ctdb_public_ip_info_len(struct ctdb_public_ip_info *ipinfo)
2625 {
2626         return offsetof(struct ctdb_public_ip_info_wire, num) +
2627                ctdb_iface_list_len(ipinfo->ifaces);
2628 }
2629
2630 void ctdb_public_ip_info_push(struct ctdb_public_ip_info *ipinfo, uint8_t *buf)
2631 {
2632         struct ctdb_public_ip_info_wire *wire =
2633                 (struct ctdb_public_ip_info_wire *)buf;
2634         size_t offset;
2635
2636         offset = offsetof(struct ctdb_public_ip_info_wire, num);
2637         memcpy(wire, ipinfo, offset);
2638         wire->num = ipinfo->ifaces->num;
2639         memcpy(wire->ifaces, ipinfo->ifaces->iface,
2640                ipinfo->ifaces->num * sizeof(struct ctdb_iface));
2641 }
2642
2643 int ctdb_public_ip_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2644                              struct ctdb_public_ip_info **out)
2645 {
2646         struct ctdb_public_ip_info *ipinfo;
2647         struct ctdb_public_ip_info_wire *wire =
2648                 (struct ctdb_public_ip_info_wire *)buf;
2649
2650         if (buflen < offsetof(struct ctdb_public_ip_info_wire, ifaces)) {
2651                 return EMSGSIZE;
2652         }
2653         if (wire->num > buflen / sizeof(struct ctdb_iface)) {
2654                 return EMSGSIZE;
2655         }
2656         if (offsetof(struct ctdb_public_ip_info_wire, ifaces) +
2657             wire->num * sizeof(struct ctdb_iface) <
2658             offsetof(struct ctdb_public_ip_info_wire, ifaces)) {
2659                 return EMSGSIZE;
2660         }
2661         if (buflen < offsetof(struct ctdb_public_ip_info_wire, ifaces) +
2662                      wire->num * sizeof(struct ctdb_iface)) {
2663                 return EMSGSIZE;
2664         }
2665
2666         ipinfo = talloc(mem_ctx, struct ctdb_public_ip_info);
2667         if (ipinfo == NULL) {
2668                 return ENOMEM;
2669         }
2670
2671         memcpy(ipinfo, wire, offsetof(struct ctdb_public_ip_info_wire, num));
2672
2673         ipinfo->ifaces = talloc(ipinfo, struct ctdb_iface_list);
2674         if (ipinfo->ifaces == NULL) {
2675                 talloc_free(ipinfo);
2676                 return ENOMEM;
2677         }
2678
2679         ipinfo->ifaces->num = wire->num;
2680         ipinfo->ifaces->iface = talloc_array(ipinfo->ifaces, struct ctdb_iface,
2681                                              wire->num);
2682         if (ipinfo->ifaces->iface == NULL) {
2683                 talloc_free(ipinfo);
2684                 return ENOMEM;
2685         }
2686
2687         memcpy(ipinfo->ifaces->iface, wire->ifaces,
2688                wire->num * sizeof(struct ctdb_iface));
2689
2690         *out = ipinfo;
2691         return 0;
2692 }
2693
2694 struct ctdb_key_data_wire {
2695         uint32_t db_id;
2696         struct ctdb_ltdb_header header;
2697         uint32_t keylen;
2698         uint8_t key[1];
2699 };
2700
2701 size_t ctdb_key_data_len(struct ctdb_key_data *key)
2702 {
2703         return offsetof(struct ctdb_key_data_wire, key) + key->key.dsize;
2704 }
2705
2706 void ctdb_key_data_push(struct ctdb_key_data *key, uint8_t *buf)
2707 {
2708         struct ctdb_key_data_wire *wire = (struct ctdb_key_data_wire *)buf;
2709
2710         memcpy(wire, key, offsetof(struct ctdb_key_data, key));
2711         wire->keylen = key->key.dsize;
2712         memcpy(wire->key, key->key.dptr, key->key.dsize);
2713 }
2714
2715 int ctdb_key_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2716                        struct ctdb_key_data **out)
2717 {
2718         struct ctdb_key_data *key_data;
2719         struct ctdb_key_data_wire *wire = (struct ctdb_key_data_wire *)buf;
2720
2721         if (buflen < offsetof(struct ctdb_key_data_wire, key)) {
2722                 return EMSGSIZE;
2723         }
2724         if (wire->keylen > buflen) {
2725                 return EMSGSIZE;
2726         }
2727         if (offsetof(struct ctdb_key_data_wire, key) + wire->keylen <
2728             offsetof(struct ctdb_key_data_wire, key)) {
2729                 return EMSGSIZE;
2730         }
2731         if (buflen < offsetof(struct ctdb_key_data_wire, key) + wire->keylen) {
2732                 return EMSGSIZE;
2733         }
2734
2735         key_data = talloc(mem_ctx, struct ctdb_key_data);
2736         if (key_data == NULL) {
2737                 return ENOMEM;
2738         }
2739
2740         memcpy(key_data, wire, offsetof(struct ctdb_key_data, key));
2741
2742         key_data->key.dsize = wire->keylen;
2743         key_data->key.dptr = talloc_memdup(key_data, wire->key, wire->keylen);
2744         if (key_data->key.dptr == NULL) {
2745                 talloc_free(key_data);
2746                 return ENOMEM;
2747         }
2748
2749         *out = key_data;
2750         return 0;
2751 }
2752
2753 struct ctdb_db_statistics_wire {
2754         struct ctdb_db_statistics dbstats;
2755         char hot_keys_wire[1];
2756 };
2757
2758 size_t ctdb_db_statistics_len(struct ctdb_db_statistics *dbstats)
2759 {
2760         size_t len;
2761         int i;
2762
2763         len = sizeof(struct ctdb_db_statistics);
2764         for (i=0; i<MAX_HOT_KEYS; i++) {
2765                 len += dbstats->hot_keys[i].key.dsize;
2766         }
2767         return len;
2768 }
2769
2770 void ctdb_db_statistics_push(struct ctdb_db_statistics *dbstats, void *buf)
2771 {
2772         struct ctdb_db_statistics_wire *wire =
2773                 (struct ctdb_db_statistics_wire *)buf;
2774         size_t offset;
2775         int i;
2776
2777         dbstats->num_hot_keys = MAX_HOT_KEYS;
2778         memcpy(wire, dbstats, sizeof(struct ctdb_db_statistics));
2779
2780         offset = 0;
2781         for (i=0; i<MAX_HOT_KEYS; i++) {
2782                 memcpy(&wire->hot_keys_wire[offset],
2783                        dbstats->hot_keys[i].key.dptr,
2784                        dbstats->hot_keys[i].key.dsize);
2785                 offset += dbstats->hot_keys[i].key.dsize;
2786         }
2787 }
2788
2789 int ctdb_db_statistics_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2790                             struct ctdb_db_statistics **out)
2791 {
2792         struct ctdb_db_statistics *dbstats;
2793         struct ctdb_db_statistics_wire *wire =
2794                 (struct ctdb_db_statistics_wire *)buf;
2795         size_t offset;
2796         int i;
2797
2798         if (buflen < sizeof(struct ctdb_db_statistics)) {
2799                 return EMSGSIZE;
2800         }
2801
2802         offset = 0;
2803         for (i=0; i<wire->dbstats.num_hot_keys; i++) {
2804                 if (wire->dbstats.hot_keys[i].key.dsize > buflen) {
2805                         return EMSGSIZE;
2806                 }
2807                 if (offset + wire->dbstats.hot_keys[i].key.dsize < offset) {
2808                         return EMSGSIZE;
2809                 }
2810                 offset += wire->dbstats.hot_keys[i].key.dsize;
2811                 if (offset > buflen) {
2812                         return EMSGSIZE;
2813                 }
2814         }
2815         if (sizeof(struct ctdb_db_statistics) + offset <
2816             sizeof(struct ctdb_db_statistics)) {
2817                 return EMSGSIZE;
2818         }
2819         if (buflen < sizeof(struct ctdb_db_statistics) + offset) {
2820                 return EMSGSIZE;
2821         }
2822
2823         dbstats = talloc(mem_ctx, struct ctdb_db_statistics);
2824         if (dbstats == NULL) {
2825                 return ENOMEM;
2826         }
2827
2828         memcpy(dbstats, wire, sizeof(struct ctdb_db_statistics));
2829
2830         offset = 0;
2831         for (i=0; i<wire->dbstats.num_hot_keys; i++) {
2832                 uint8_t *ptr;
2833                 size_t key_size;
2834
2835                 key_size = dbstats->hot_keys[i].key.dsize;
2836                 ptr = talloc_memdup(mem_ctx, &wire->hot_keys_wire[offset],
2837                                     key_size);
2838                 if (ptr == NULL) {
2839                         talloc_free(dbstats);
2840                         return ENOMEM;
2841                 }
2842                 dbstats->hot_keys[i].key.dptr = ptr;
2843                 offset += key_size;
2844         }
2845
2846         *out = dbstats;
2847         return 0;
2848 }
2849
2850 size_t ctdb_election_message_len(struct ctdb_election_message *election)
2851 {
2852         return sizeof(struct ctdb_election_message);
2853 }
2854
2855 void ctdb_election_message_push(struct ctdb_election_message *election,
2856                                 uint8_t *buf)
2857 {
2858         memcpy(buf, election, sizeof(struct ctdb_election_message));
2859 }
2860
2861 int ctdb_election_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2862                                struct ctdb_election_message **out)
2863 {
2864         struct ctdb_election_message *election;
2865
2866         if (buflen < sizeof(struct ctdb_election_message)) {
2867                 return EMSGSIZE;
2868         }
2869
2870         election = talloc_memdup(mem_ctx, buf,
2871                                  sizeof(struct ctdb_election_message));
2872         if (election == NULL) {
2873                 return ENOMEM;
2874         }
2875
2876         *out = election;
2877         return 0;
2878 }
2879
2880 size_t ctdb_srvid_message_len(struct ctdb_srvid_message *msg)
2881 {
2882         return sizeof(struct ctdb_srvid_message);
2883 }
2884
2885 void ctdb_srvid_message_push(struct ctdb_srvid_message *msg, uint8_t *buf)
2886 {
2887         memcpy(buf, msg, sizeof(struct ctdb_srvid_message));
2888 }
2889
2890 int ctdb_srvid_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2891                             struct ctdb_srvid_message **out)
2892 {
2893         struct ctdb_srvid_message *msg;
2894
2895         if (buflen < sizeof(struct ctdb_srvid_message)) {
2896                 return EMSGSIZE;
2897         }
2898
2899         msg = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_srvid_message));
2900         if (msg == NULL) {
2901                 return ENOMEM;
2902         }
2903
2904         *out = msg;
2905         return 0;
2906 }
2907
2908 size_t ctdb_disable_message_len(struct ctdb_disable_message *disable)
2909 {
2910         return sizeof(struct ctdb_disable_message);
2911 }
2912
2913 void ctdb_disable_message_push(struct ctdb_disable_message *disable,
2914                                uint8_t *buf)
2915 {
2916         memcpy(buf, disable, sizeof(struct ctdb_disable_message));
2917 }
2918
2919 int ctdb_disable_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2920                               struct ctdb_disable_message **out)
2921 {
2922         struct ctdb_disable_message *disable;
2923
2924         if (buflen < sizeof(struct ctdb_disable_message)) {
2925                 return EMSGSIZE;
2926         }
2927
2928         disable = talloc_memdup(mem_ctx, buf,
2929                                 sizeof(struct ctdb_disable_message));
2930         if (disable == NULL) {
2931                 return ENOMEM;
2932         }
2933
2934         *out = disable;
2935         return 0;
2936 }
2937
2938 size_t ctdb_server_id_len(struct ctdb_server_id *sid)
2939 {
2940         return sizeof(struct ctdb_server_id);
2941 }
2942
2943 void ctdb_server_id_push(struct ctdb_server_id *sid, uint8_t *buf)
2944 {
2945         memcpy(buf, sid, sizeof(struct ctdb_server_id));
2946 }
2947
2948 int ctdb_server_id_pull(uint8_t *buf, size_t buflen,
2949                         struct ctdb_server_id *sid)
2950 {
2951         if (buflen < sizeof(struct ctdb_server_id)) {
2952                 return EMSGSIZE;
2953         }
2954
2955         memcpy(sid, buf, sizeof(struct ctdb_server_id));
2956         return 0;
2957 }
2958
2959 size_t ctdb_g_lock_len(struct ctdb_g_lock *lock)
2960 {
2961         return sizeof(struct ctdb_g_lock);
2962 }
2963
2964 void ctdb_g_lock_push(struct ctdb_g_lock *lock, uint8_t *buf)
2965 {
2966         memcpy(buf, lock, sizeof(struct ctdb_g_lock));
2967 }
2968
2969 int ctdb_g_lock_pull(uint8_t *buf, size_t buflen, struct ctdb_g_lock *lock)
2970 {
2971         if (buflen < sizeof(struct ctdb_g_lock)) {
2972                 return EMSGSIZE;
2973         }
2974
2975         memcpy(lock, buf, sizeof(struct ctdb_g_lock));
2976         return 0;
2977 }
2978
2979 size_t ctdb_g_lock_list_len(struct ctdb_g_lock_list *lock_list)
2980 {
2981         return lock_list->num * sizeof(struct ctdb_g_lock);
2982 }
2983
2984 void ctdb_g_lock_list_push(struct ctdb_g_lock_list *lock_list, uint8_t *buf)
2985 {
2986         size_t offset = 0;
2987         int i;
2988
2989         for (i=0; i<lock_list->num; i++) {
2990                 ctdb_g_lock_push(&lock_list->lock[i], &buf[offset]);
2991                 offset += sizeof(struct ctdb_g_lock);
2992         }
2993 }
2994
2995 int ctdb_g_lock_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
2996                           struct ctdb_g_lock_list **out)
2997 {
2998         struct ctdb_g_lock_list *lock_list;
2999         unsigned count;
3000         size_t offset;
3001         int ret, i;
3002
3003         lock_list = talloc_zero(mem_ctx, struct ctdb_g_lock_list);
3004         if (lock_list == NULL) {
3005                 return ENOMEM;
3006         }
3007
3008         count = buflen / sizeof(struct ctdb_g_lock);
3009         lock_list->lock = talloc_array(lock_list, struct ctdb_g_lock, count);
3010         if (lock_list->lock == NULL) {
3011                 talloc_free(lock_list);
3012                 return ENOMEM;
3013         }
3014
3015         offset = 0;
3016         for (i=0; i<count; i++) {
3017                 ret = ctdb_g_lock_pull(&buf[offset], buflen-offset,
3018                                        &lock_list->lock[i]);
3019                 if (ret != 0) {
3020                         talloc_free(lock_list);
3021                         return ret;
3022                 }
3023                 offset += sizeof(struct ctdb_g_lock);
3024         }
3025
3026         lock_list->num = count;
3027
3028         *out = lock_list;
3029         return 0;
3030 }