password_lockout: Remove use of global lp and host vars
[nivanova/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_PUSH_NODE_FLAGS:
83                 len = ctdb_node_flag_change_len(mdata->flag_change);
84                 break;
85
86         case CTDB_SRVID_RELOAD_NODES:
87                 break;
88
89         case CTDB_SRVID_TAKEOVER_RUN:
90                 len = ctdb_srvid_message_len(mdata->msg);
91                 break;
92
93         case CTDB_SRVID_REBALANCE_NODE:
94                 len = ctdb_uint32_len(mdata->pnn);
95                 break;
96
97         case CTDB_SRVID_DISABLE_TAKEOVER_RUNS:
98                 len = ctdb_disable_message_len(mdata->disable);
99                 break;
100
101         case CTDB_SRVID_DISABLE_RECOVERIES:
102                 len = ctdb_disable_message_len(mdata->disable);
103                 break;
104
105         case CTDB_SRVID_DISABLE_IP_CHECK:
106                 len = ctdb_uint32_len(mdata->timeout);
107                 break;
108
109         default:
110                 len = ctdb_tdb_data_len(mdata->data);
111                 break;
112         }
113
114         return len;
115 }
116
117 static void ctdb_message_data_push(union ctdb_message_data *mdata,
118                                    uint64_t srvid, uint8_t *buf)
119 {
120         switch (srvid) {
121         case CTDB_SRVID_BANNING:
122                 ctdb_uint32_push(mdata->pnn, buf);
123                 break;
124
125         case CTDB_SRVID_ELECTION:
126                 ctdb_election_message_push(mdata->election, buf);
127                 break;
128
129         case CTDB_SRVID_RECONFIGURE:
130                 break;
131
132         case CTDB_SRVID_RELEASE_IP:
133                 ctdb_string_push(mdata->ipaddr, buf);
134                 break;
135
136         case CTDB_SRVID_TAKE_IP:
137                 ctdb_string_push(mdata->ipaddr, buf);
138                 break;
139
140         case CTDB_SRVID_SET_NODE_FLAGS:
141                 ctdb_node_flag_change_push(mdata->flag_change, buf);
142                 break;
143
144         case CTDB_SRVID_RECD_UPDATE_IP:
145                 ctdb_public_ip_push(mdata->pubip, buf);
146                 break;
147
148         case CTDB_SRVID_VACUUM_FETCH:
149                 ctdb_rec_buffer_push(mdata->recbuf, buf);
150                 break;
151
152         case CTDB_SRVID_DETACH_DATABASE:
153                 ctdb_uint32_push(mdata->db_id, buf);
154                 break;
155
156         case CTDB_SRVID_MEM_DUMP:
157                 ctdb_srvid_message_push(mdata->msg, buf);
158                 break;
159
160         case CTDB_SRVID_PUSH_NODE_FLAGS:
161                 ctdb_node_flag_change_push(mdata->flag_change, buf);
162                 break;
163
164         case CTDB_SRVID_RELOAD_NODES:
165                 break;
166
167         case CTDB_SRVID_TAKEOVER_RUN:
168                 ctdb_srvid_message_push(mdata->msg, buf);
169                 break;
170
171         case CTDB_SRVID_REBALANCE_NODE:
172                 ctdb_uint32_push(mdata->pnn, buf);
173                 break;
174
175         case CTDB_SRVID_DISABLE_TAKEOVER_RUNS:
176                 ctdb_disable_message_push(mdata->disable, buf);
177                 break;
178
179         case CTDB_SRVID_DISABLE_RECOVERIES:
180                 ctdb_disable_message_push(mdata->disable, buf);
181                 break;
182
183         case CTDB_SRVID_DISABLE_IP_CHECK:
184                 ctdb_uint32_push(mdata->timeout, buf);
185                 break;
186
187         default:
188                 ctdb_tdb_data_push(mdata->data, buf);
189                 break;
190         }
191 }
192
193 static int ctdb_message_data_pull(uint8_t *buf, size_t buflen,
194                                   uint64_t srvid, TALLOC_CTX *mem_ctx,
195                                   union ctdb_message_data *mdata)
196 {
197         int ret = 0;
198
199         switch (srvid) {
200         case CTDB_SRVID_BANNING:
201                 ret = ctdb_uint32_pull(buf, buflen, mem_ctx, &mdata->pnn);
202                 break;
203
204         case CTDB_SRVID_ELECTION:
205                 ret = ctdb_election_message_pull(buf, buflen, mem_ctx,
206                                                  &mdata->election);
207                 break;
208
209         case CTDB_SRVID_RECONFIGURE:
210                 break;
211
212         case CTDB_SRVID_RELEASE_IP:
213                 ret = ctdb_string_pull(buf, buflen, mem_ctx, &mdata->ipaddr);
214                 break;
215
216         case CTDB_SRVID_TAKE_IP:
217                 ret = ctdb_string_pull(buf, buflen, mem_ctx, &mdata->ipaddr);
218                 break;
219
220         case CTDB_SRVID_SET_NODE_FLAGS:
221                 ret = ctdb_node_flag_change_pull(buf, buflen, mem_ctx,
222                                                  &mdata->flag_change);
223                 break;
224
225         case CTDB_SRVID_RECD_UPDATE_IP:
226                 ret = ctdb_public_ip_pull(buf, buflen, mem_ctx,
227                                           &mdata->pubip);
228                 break;
229
230         case CTDB_SRVID_VACUUM_FETCH:
231                 ret = ctdb_rec_buffer_pull(buf, buflen, mem_ctx,
232                                            &mdata->recbuf);
233                 break;
234
235         case CTDB_SRVID_DETACH_DATABASE:
236                 ret = ctdb_uint32_pull(buf, buflen, mem_ctx, &mdata->db_id);
237                 break;
238
239         case CTDB_SRVID_MEM_DUMP:
240                 ret = ctdb_srvid_message_pull(buf, buflen, mem_ctx,
241                                               &mdata->msg);
242                 break;
243
244         case CTDB_SRVID_PUSH_NODE_FLAGS:
245                 ret = ctdb_node_flag_change_pull(buf, buflen, mem_ctx,
246                                                  &mdata->flag_change);
247                 break;
248
249         case CTDB_SRVID_RELOAD_NODES:
250                 break;
251
252         case CTDB_SRVID_TAKEOVER_RUN:
253                 ret = ctdb_srvid_message_pull(buf, buflen, mem_ctx,
254                                               &mdata->msg);
255                 break;
256
257         case CTDB_SRVID_REBALANCE_NODE:
258                 ret = ctdb_uint32_pull(buf, buflen, mem_ctx, &mdata->pnn);
259                 break;
260
261         case CTDB_SRVID_DISABLE_TAKEOVER_RUNS:
262                 ret = ctdb_disable_message_pull(buf, buflen, mem_ctx,
263                                                 &mdata->disable);
264                 break;
265
266         case CTDB_SRVID_DISABLE_RECOVERIES:
267                 ret = ctdb_disable_message_pull(buf, buflen, mem_ctx,
268                                                 &mdata->disable);
269                 break;
270
271         case CTDB_SRVID_DISABLE_IP_CHECK:
272                 ret = ctdb_uint32_pull(buf, buflen, mem_ctx, &mdata->timeout);
273                 break;
274
275         default:
276                 ret = ctdb_tdb_data_pull(buf, buflen, mem_ctx, &mdata->data);
277                 break;
278         }
279
280         return ret;
281 }
282
283 size_t ctdb_req_message_len(struct ctdb_req_header *h,
284                             struct ctdb_req_message *c)
285 {
286         return offsetof(struct ctdb_req_message_wire, data) +
287                 ctdb_message_data_len(&c->data, c->srvid);
288 }
289
290 int ctdb_req_message_push(struct ctdb_req_header *h,
291                           struct ctdb_req_message *message,
292                           uint8_t *buf, size_t *buflen)
293 {
294         struct ctdb_req_message_wire *wire =
295                 (struct ctdb_req_message_wire *)buf;
296         size_t length;
297
298         length = ctdb_req_message_len(h, message);
299         if (*buflen < length) {
300                 *buflen = length;
301                 return EMSGSIZE;
302         }
303
304         h->length = *buflen;
305         ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
306
307         wire->srvid = message->srvid;
308         wire->datalen = ctdb_message_data_len(&message->data, message->srvid);
309         ctdb_message_data_push(&message->data, message->srvid, wire->data);
310
311         return 0;
312 }
313
314 int ctdb_req_message_pull(uint8_t *buf, size_t buflen,
315                           struct ctdb_req_header *h,
316                           TALLOC_CTX *mem_ctx,
317                           struct ctdb_req_message *c)
318 {
319         struct ctdb_req_message_wire *wire =
320                 (struct ctdb_req_message_wire *)buf;
321         size_t length;
322         int ret;
323
324         length = offsetof(struct ctdb_req_message_wire, data);
325         if (buflen < length) {
326                 return EMSGSIZE;
327         }
328         if (wire->datalen > buflen) {
329                 return EMSGSIZE;
330         }
331         if (length + wire->datalen < length) {
332                 return EMSGSIZE;
333         }
334         if (buflen < length + wire->datalen) {
335                 return EMSGSIZE;
336         }
337
338         if (h != NULL) {
339                 ret = ctdb_req_header_pull((uint8_t *)&wire->hdr, buflen, h);
340                 if (ret != 0) {
341                         return ret;
342                 }
343         }
344
345         c->srvid = wire->srvid;
346         ret = ctdb_message_data_pull(wire->data, wire->datalen, wire->srvid,
347                                      mem_ctx, &c->data);
348         return ret;
349 }
350
351 size_t ctdb_req_message_data_len(struct ctdb_req_header *h,
352                                  struct ctdb_req_message_data *c)
353 {
354         return offsetof(struct ctdb_req_message_wire, data) +
355                 ctdb_tdb_data_len(c->data);
356 }
357
358 int ctdb_req_message_data_push(struct ctdb_req_header *h,
359                                struct ctdb_req_message_data *message,
360                                uint8_t *buf, size_t *buflen)
361 {
362         struct ctdb_req_message_wire *wire =
363                 (struct ctdb_req_message_wire *)buf;
364         size_t length;
365
366         length = ctdb_req_message_data_len(h, message);
367         if (*buflen < length) {
368                 *buflen = length;
369                 return EMSGSIZE;
370         }
371
372         h->length = *buflen;
373         ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
374
375         wire->srvid = message->srvid;
376         wire->datalen = ctdb_tdb_data_len(message->data);
377         ctdb_tdb_data_push(message->data, wire->data);
378
379         return 0;
380 }
381
382 int ctdb_req_message_data_pull(uint8_t *buf, size_t buflen,
383                                struct ctdb_req_header *h,
384                                TALLOC_CTX *mem_ctx,
385                                struct ctdb_req_message_data *c)
386 {
387         struct ctdb_req_message_wire *wire =
388                 (struct ctdb_req_message_wire *)buf;
389         size_t length;
390         int ret;
391
392         length = offsetof(struct ctdb_req_message_wire, data);
393         if (buflen < length) {
394                 return EMSGSIZE;
395         }
396         if (wire->datalen > buflen) {
397                 return EMSGSIZE;
398         }
399         if (length + wire->datalen < length) {
400                 return EMSGSIZE;
401         }
402         if (buflen < length + wire->datalen) {
403                 return EMSGSIZE;
404         }
405
406         if (h != NULL) {
407                 ret = ctdb_req_header_pull((uint8_t *)&wire->hdr, buflen, h);
408                 if (ret != 0) {
409                         return ret;
410                 }
411         }
412
413         c->srvid = wire->srvid;
414
415         ret = ctdb_tdb_data_pull(wire->data, wire->datalen,
416                                  mem_ctx, &c->data);
417         if (ret != 0) {
418                 return ret;
419         }
420
421         return 0;
422 }