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