]> git.samba.org - vlendec/samba-autobuild/.git/blob - ctdb/protocol/protocol_message.c
ctdb-protocol: Fix marshalling for ctdb_req_message
[vlendec/samba-autobuild/.git] / ctdb / protocol / protocol_message.c
1 /*
2    CTDB protocol marshalling
3
4    Copyright (C) Amitay Isaacs  2015
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21 #include "system/network.h"
22
23 #include <talloc.h>
24 #include <tdb.h>
25
26 #include "protocol.h"
27 #include "protocol_api.h"
28 #include "protocol_private.h"
29
30 struct ctdb_req_message_wire {
31         struct ctdb_req_header hdr;
32         uint64_t srvid;
33         uint32_t datalen;
34         uint8_t data[1];
35 };
36
37 static size_t ctdb_message_data_len(union ctdb_message_data *mdata,
38                                     uint64_t srvid)
39 {
40         size_t len = 0;
41
42         switch (srvid) {
43         case CTDB_SRVID_BANNING:
44                 len = ctdb_uint32_len(&mdata->pnn);
45                 break;
46
47         case CTDB_SRVID_ELECTION:
48                 len = ctdb_election_message_len(mdata->election);
49                 break;
50
51         case CTDB_SRVID_RECONFIGURE:
52                 break;
53
54         case CTDB_SRVID_RELEASE_IP:
55                 len = ctdb_string_len(&mdata->ipaddr);
56                 break;
57
58         case CTDB_SRVID_TAKE_IP:
59                 len = ctdb_string_len(&mdata->ipaddr);
60                 break;
61
62         case CTDB_SRVID_SET_NODE_FLAGS:
63                 len = ctdb_node_flag_change_len(mdata->flag_change);
64                 break;
65
66         case CTDB_SRVID_RECD_UPDATE_IP:
67                 len = ctdb_public_ip_len(mdata->pubip);
68                 break;
69
70         case CTDB_SRVID_VACUUM_FETCH:
71                 len = ctdb_rec_buffer_len(mdata->recbuf);
72                 break;
73
74         case CTDB_SRVID_DETACH_DATABASE:
75                 len = ctdb_uint32_len(&mdata->db_id);
76                 break;
77
78         case CTDB_SRVID_MEM_DUMP:
79                 len = ctdb_srvid_message_len(mdata->msg);
80                 break;
81
82         case CTDB_SRVID_GETLOG:
83                 break;
84
85         case CTDB_SRVID_CLEARLOG:
86                 break;
87
88         case CTDB_SRVID_PUSH_NODE_FLAGS:
89                 len = ctdb_node_flag_change_len(mdata->flag_change);
90                 break;
91
92         case CTDB_SRVID_RELOAD_NODES:
93                 break;
94
95         case CTDB_SRVID_TAKEOVER_RUN:
96                 len = ctdb_srvid_message_len(mdata->msg);
97                 break;
98
99         case CTDB_SRVID_REBALANCE_NODE:
100                 len = ctdb_uint32_len(&mdata->pnn);
101                 break;
102
103         case CTDB_SRVID_DISABLE_TAKEOVER_RUNS:
104                 len = ctdb_disable_message_len(mdata->disable);
105                 break;
106
107         case CTDB_SRVID_DISABLE_RECOVERIES:
108                 len = ctdb_disable_message_len(mdata->disable);
109                 break;
110
111         case CTDB_SRVID_DISABLE_IP_CHECK:
112                 len = ctdb_uint32_len(&mdata->timeout);
113                 break;
114
115         default:
116                 len = ctdb_tdb_data_len(&mdata->data);
117                 break;
118         }
119
120         return len;
121 }
122
123 static void ctdb_message_data_push(union ctdb_message_data *mdata,
124                                    uint64_t srvid, uint8_t *buf,
125                                    size_t *npush)
126 {
127         size_t np = 0;
128
129         switch (srvid) {
130         case CTDB_SRVID_BANNING:
131                 ctdb_uint32_push(&mdata->pnn, buf, &np);
132                 break;
133
134         case CTDB_SRVID_ELECTION:
135                 ctdb_election_message_push(mdata->election, buf, &np);
136                 break;
137
138         case CTDB_SRVID_RECONFIGURE:
139                 break;
140
141         case CTDB_SRVID_RELEASE_IP:
142                 ctdb_string_push(&mdata->ipaddr, buf, &np);
143                 break;
144
145         case CTDB_SRVID_TAKE_IP:
146                 ctdb_string_push(&mdata->ipaddr, buf, &np);
147                 break;
148
149         case CTDB_SRVID_SET_NODE_FLAGS:
150                 ctdb_node_flag_change_push(mdata->flag_change, buf, &np);
151                 break;
152
153         case CTDB_SRVID_RECD_UPDATE_IP:
154                 ctdb_public_ip_push(mdata->pubip, buf, &np);
155                 break;
156
157         case CTDB_SRVID_VACUUM_FETCH:
158                 ctdb_rec_buffer_push(mdata->recbuf, buf, &np);
159                 break;
160
161         case CTDB_SRVID_DETACH_DATABASE:
162                 ctdb_uint32_push(&mdata->db_id, buf, &np);
163                 break;
164
165         case CTDB_SRVID_MEM_DUMP:
166                 ctdb_srvid_message_push(mdata->msg, buf, &np);
167                 break;
168
169         case CTDB_SRVID_GETLOG:
170                 break;
171
172         case CTDB_SRVID_CLEARLOG:
173                 break;
174
175         case CTDB_SRVID_PUSH_NODE_FLAGS:
176                 ctdb_node_flag_change_push(mdata->flag_change, buf, &np);
177                 break;
178
179         case CTDB_SRVID_RELOAD_NODES:
180                 break;
181
182         case CTDB_SRVID_TAKEOVER_RUN:
183                 ctdb_srvid_message_push(mdata->msg, buf, &np);
184                 break;
185
186         case CTDB_SRVID_REBALANCE_NODE:
187                 ctdb_uint32_push(&mdata->pnn, buf, &np);
188                 break;
189
190         case CTDB_SRVID_DISABLE_TAKEOVER_RUNS:
191                 ctdb_disable_message_push(mdata->disable, buf, &np);
192                 break;
193
194         case CTDB_SRVID_DISABLE_RECOVERIES:
195                 ctdb_disable_message_push(mdata->disable, buf, &np);
196                 break;
197
198         case CTDB_SRVID_DISABLE_IP_CHECK:
199                 ctdb_uint32_push(&mdata->timeout, buf, &np);
200                 break;
201
202         default:
203                 ctdb_tdb_data_push(&mdata->data, buf, &np);
204                 break;
205         }
206
207         *npush = np;
208 }
209
210 static int ctdb_message_data_pull(uint8_t *buf, size_t buflen,
211                                   uint64_t srvid, TALLOC_CTX *mem_ctx,
212                                   union ctdb_message_data *mdata,
213                                   size_t *npull)
214 {
215         int ret = 0;
216         size_t np = 0;
217
218         switch (srvid) {
219         case CTDB_SRVID_BANNING:
220                 ret = ctdb_uint32_pull(buf, buflen, &mdata->pnn, &np);
221                 break;
222
223         case CTDB_SRVID_ELECTION:
224                 ret = ctdb_election_message_pull(buf, buflen, mem_ctx,
225                                                  &mdata->election, &np);
226                 break;
227
228         case CTDB_SRVID_RECONFIGURE:
229                 break;
230
231         case CTDB_SRVID_RELEASE_IP:
232                 ret = ctdb_string_pull(buf, buflen, mem_ctx, &mdata->ipaddr,
233                                        &np);
234                 break;
235
236         case CTDB_SRVID_TAKE_IP:
237                 ret = ctdb_string_pull(buf, buflen, mem_ctx, &mdata->ipaddr,
238                                        &np);
239                 break;
240
241         case CTDB_SRVID_SET_NODE_FLAGS:
242                 ret = ctdb_node_flag_change_pull(buf, buflen, mem_ctx,
243                                                  &mdata->flag_change, &np);
244                 break;
245
246         case CTDB_SRVID_RECD_UPDATE_IP:
247                 ret = ctdb_public_ip_pull(buf, buflen, mem_ctx,
248                                           &mdata->pubip, &np);
249                 break;
250
251         case CTDB_SRVID_VACUUM_FETCH:
252                 ret = ctdb_rec_buffer_pull(buf, buflen, mem_ctx,
253                                            &mdata->recbuf, &np);
254                 break;
255
256         case CTDB_SRVID_DETACH_DATABASE:
257                 ret = ctdb_uint32_pull(buf, buflen, &mdata->db_id, &np);
258                 break;
259
260         case CTDB_SRVID_MEM_DUMP:
261                 ret = ctdb_srvid_message_pull(buf, buflen, mem_ctx,
262                                               &mdata->msg, &np);
263                 break;
264
265         case CTDB_SRVID_GETLOG:
266                 break;
267
268         case CTDB_SRVID_CLEARLOG:
269                 break;
270
271         case CTDB_SRVID_PUSH_NODE_FLAGS:
272                 ret = ctdb_node_flag_change_pull(buf, buflen, mem_ctx,
273                                                  &mdata->flag_change, &np);
274                 break;
275
276         case CTDB_SRVID_RELOAD_NODES:
277                 break;
278
279         case CTDB_SRVID_TAKEOVER_RUN:
280                 ret = ctdb_srvid_message_pull(buf, buflen, mem_ctx,
281                                               &mdata->msg, &np);
282                 break;
283
284         case CTDB_SRVID_REBALANCE_NODE:
285                 ret = ctdb_uint32_pull(buf, buflen, &mdata->pnn, &np);
286                 break;
287
288         case CTDB_SRVID_DISABLE_TAKEOVER_RUNS:
289                 ret = ctdb_disable_message_pull(buf, buflen, mem_ctx,
290                                                 &mdata->disable, &np);
291                 break;
292
293         case CTDB_SRVID_DISABLE_RECOVERIES:
294                 ret = ctdb_disable_message_pull(buf, buflen, mem_ctx,
295                                                 &mdata->disable, &np);
296                 break;
297
298         case CTDB_SRVID_DISABLE_IP_CHECK:
299                 ret = ctdb_uint32_pull(buf, buflen, &mdata->timeout, &np);
300                 break;
301
302         default:
303                 ret = ctdb_tdb_data_pull(buf, buflen, mem_ctx, &mdata->data,
304                                          &np);
305                 break;
306         }
307
308         if (ret != 0) {
309                 return ret;
310         }
311
312         *npull = np;
313         return 0;
314 }
315
316 size_t ctdb_req_message_len(struct ctdb_req_header *h,
317                             struct ctdb_req_message *c)
318 {
319         uint32_t u32 = ctdb_message_data_len(&c->data, c->srvid);
320
321         return ctdb_req_header_len(h) +
322                 ctdb_uint64_len(&c->srvid) +
323                 ctdb_uint32_len(&u32) + u32;
324 }
325
326 int ctdb_req_message_push(struct ctdb_req_header *h,
327                           struct ctdb_req_message *c,
328                           uint8_t *buf, size_t *buflen)
329 {
330         size_t offset = 0, np;
331         size_t length;
332         uint32_t u32;
333
334         length = ctdb_req_message_len(h, c);
335         if (*buflen < length) {
336                 *buflen = length;
337                 return EMSGSIZE;
338         }
339
340         h->length = *buflen;
341         ctdb_req_header_push(h, buf+offset, &np);
342         offset += np;
343
344         ctdb_uint64_push(&c->srvid, buf+offset, &np);
345         offset += np;
346
347         u32 = ctdb_message_data_len(&c->data, c->srvid);
348         ctdb_uint32_push(&u32, buf+offset, &np);
349         offset += np;
350
351         ctdb_message_data_push(&c->data, c->srvid, buf+offset, &np);
352         offset += np;
353
354         return 0;
355 }
356
357 int ctdb_req_message_pull(uint8_t *buf, size_t buflen,
358                           struct ctdb_req_header *h,
359                           TALLOC_CTX *mem_ctx,
360                           struct ctdb_req_message *c)
361 {
362         struct ctdb_req_header header;
363         size_t offset = 0, np;
364         uint32_t u32;
365         int ret;
366
367         ret = ctdb_req_header_pull(buf+offset, buflen-offset, &header, &np);
368         if (ret != 0) {
369                 return ret;
370         }
371         offset += np;
372
373         if (h != NULL) {
374                 *h = header;
375         }
376
377         ret = ctdb_uint64_pull(buf+offset, buflen-offset, &c->srvid, &np);
378         if (ret != 0) {
379                 return ret;
380         }
381         offset += np;
382
383         ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
384         if (ret != 0) {
385                 return ret;
386         }
387         offset += np;
388
389         if (buflen-offset < u32) {
390                 return EMSGSIZE;
391         }
392
393         ret = ctdb_message_data_pull(buf+offset, u32, c->srvid,
394                                      mem_ctx, &c->data, &np);
395         if (ret != 0) {
396                 return ret;
397         }
398         offset += np;
399
400         return ret;
401 }
402
403 size_t ctdb_req_message_data_len(struct ctdb_req_header *h,
404                                  struct ctdb_req_message_data *c)
405 {
406         return offsetof(struct ctdb_req_message_wire, data) +
407                 ctdb_tdb_data_len(&c->data);
408 }
409
410 int ctdb_req_message_data_push(struct ctdb_req_header *h,
411                                struct ctdb_req_message_data *message,
412                                uint8_t *buf, size_t *buflen)
413 {
414         struct ctdb_req_message_wire *wire =
415                 (struct ctdb_req_message_wire *)buf;
416         size_t length, np;
417
418         length = ctdb_req_message_data_len(h, message);
419         if (*buflen < length) {
420                 *buflen = length;
421                 return EMSGSIZE;
422         }
423
424         h->length = *buflen;
425         ctdb_req_header_push(h, (uint8_t *)&wire->hdr, &np);
426
427         wire->srvid = message->srvid;
428         wire->datalen = ctdb_tdb_data_len(&message->data);
429         ctdb_tdb_data_push(&message->data, wire->data, &np);
430
431         return 0;
432 }
433
434 int ctdb_req_message_data_pull(uint8_t *buf, size_t buflen,
435                                struct ctdb_req_header *h,
436                                TALLOC_CTX *mem_ctx,
437                                struct ctdb_req_message_data *c)
438 {
439         struct ctdb_req_message_wire *wire =
440                 (struct ctdb_req_message_wire *)buf;
441         size_t length, np;
442         int ret;
443
444         length = offsetof(struct ctdb_req_message_wire, data);
445         if (buflen < length) {
446                 return EMSGSIZE;
447         }
448         if (wire->datalen > buflen) {
449                 return EMSGSIZE;
450         }
451         if (length + wire->datalen < length) {
452                 return EMSGSIZE;
453         }
454         if (buflen < length + wire->datalen) {
455                 return EMSGSIZE;
456         }
457
458         if (h != NULL) {
459                 ret = ctdb_req_header_pull((uint8_t *)&wire->hdr, buflen, h,
460                                            &np);
461                 if (ret != 0) {
462                         return ret;
463                 }
464         }
465
466         c->srvid = wire->srvid;
467
468         ret = ctdb_tdb_data_pull(wire->data, wire->datalen,
469                                  mem_ctx, &c->data, &np);
470         if (ret != 0) {
471                 return ret;
472         }
473
474         return 0;
475 }