VERSION: Disable git snapshots for the 4.4.2 release.
[Samba.git] / ctdb / protocol / protocol_call.c
blobe0f38d97e08cc91adee0e794232cc2008e0ae82d
1 /*
2 CTDB protocol marshalling
4 Copyright (C) Amitay Isaacs 2015
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.
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.
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/>.
20 #include "replace.h"
21 #include "system/network.h"
23 #include <talloc.h>
24 #include <tdb.h>
26 #include "protocol.h"
27 #include "protocol_api.h"
28 #include "protocol_private.h"
30 struct ctdb_req_call_wire {
31 struct ctdb_req_header hdr;
32 uint32_t flags;
33 uint32_t db_id;
34 uint32_t callid;
35 uint32_t hopcount;
36 uint32_t keylen;
37 uint32_t calldatalen;
38 uint8_t data[1]; /* key[] followed by calldata[] */
41 struct ctdb_reply_call_wire {
42 struct ctdb_req_header hdr;
43 uint32_t status;
44 uint32_t datalen;
45 uint8_t data[1];
48 struct ctdb_reply_error_wire {
49 struct ctdb_req_header hdr;
50 uint32_t status;
51 uint32_t msglen;
52 uint8_t msg[1];
55 struct ctdb_req_dmaster_wire {
56 struct ctdb_req_header hdr;
57 uint32_t db_id;
58 uint64_t rsn;
59 uint32_t dmaster;
60 uint32_t keylen;
61 uint32_t datalen;
62 uint8_t data[1];
65 struct ctdb_reply_dmaster_wire {
66 struct ctdb_req_header hdr;
67 uint32_t db_id;
68 uint64_t rsn;
69 uint32_t keylen;
70 uint32_t datalen;
71 uint8_t data[1];
74 int ctdb_req_call_push(struct ctdb_req_header *h, struct ctdb_req_call *c,
75 TALLOC_CTX *mem_ctx, uint8_t **pkt, size_t *pkt_len)
77 struct ctdb_req_call_wire *wire;
78 uint8_t *buf;
79 size_t length, buflen;
80 int ret;
82 if (c->key.dsize == 0) {
83 return EINVAL;
86 length = offsetof(struct ctdb_req_call_wire, data) +
87 c->key.dsize + c->calldata.dsize;
89 ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
90 if (ret != 0) {
91 return ret;
94 wire = (struct ctdb_req_call_wire *)buf;
96 h->length = buflen;
97 memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
99 wire->flags = c->flags;
100 wire->db_id = c->db_id;
101 wire->callid = c->callid;
102 wire->hopcount = c->hopcount;
103 wire->keylen = c->key.dsize;
104 wire->calldatalen = c->calldata.dsize;
105 memcpy(wire->data, c->key.dptr, c->key.dsize);
106 if (c->calldata.dsize > 0) {
107 memcpy(wire->data + c->key.dsize, c->calldata.dptr,
108 c->calldata.dsize);
111 *pkt = buf;
112 *pkt_len = buflen;
113 return 0;
116 int ctdb_req_call_pull(uint8_t *pkt, size_t pkt_len,
117 struct ctdb_req_header *h,
118 TALLOC_CTX *mem_ctx,
119 struct ctdb_req_call *c)
121 struct ctdb_req_call_wire *wire;
122 size_t length;
124 length = offsetof(struct ctdb_req_call_wire, data);
125 if (pkt_len < length) {
126 return EMSGSIZE;
129 wire = (struct ctdb_req_call_wire *)pkt;
131 if (pkt_len < length + wire->keylen + wire->calldatalen) {
132 return EMSGSIZE;
135 memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
137 c->flags = wire->flags;
138 c->db_id = wire->db_id;
139 c->callid = wire->callid;
140 c->hopcount = wire->hopcount;
141 c->key.dsize = wire->keylen;
142 c->key.dptr = talloc_memdup(mem_ctx, wire->data, wire->keylen);
143 if (c->key.dptr == NULL) {
144 return ENOMEM;
146 c->calldata.dsize = wire->calldatalen;
147 if (wire->calldatalen > 0) {
148 c->calldata.dptr = talloc_memdup(mem_ctx,
149 wire->data + wire->keylen,
150 wire->calldatalen);
151 if (c->calldata.dptr == NULL) {
152 talloc_free(c->key.dptr);
153 return ENOMEM;
157 return 0;
160 int ctdb_reply_call_push(struct ctdb_req_header *h, struct ctdb_reply_call *c,
161 TALLOC_CTX *mem_ctx, uint8_t **pkt, size_t *pkt_len)
163 struct ctdb_reply_call_wire *wire;
164 uint8_t *buf;
165 size_t length, buflen;
166 int ret;
168 length = offsetof(struct ctdb_reply_call_wire, data) + c->data.dsize;
170 ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
171 if (ret != 0) {
172 return ret;
175 wire = (struct ctdb_reply_call_wire *)buf;
177 h->length = buflen;
178 memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
180 wire->status = c->status;
181 wire->datalen = c->data.dsize;
182 if (c->data.dsize > 0) {
183 memcpy(wire->data, c->data.dptr, c->data.dsize);
186 *pkt = buf;
187 *pkt_len = buflen;
188 return 0;
191 int ctdb_reply_call_pull(uint8_t *pkt, size_t pkt_len,
192 struct ctdb_req_header *h,
193 TALLOC_CTX *mem_ctx,
194 struct ctdb_reply_call *c)
196 struct ctdb_reply_call_wire *wire;
197 size_t length;
199 length = offsetof(struct ctdb_reply_call_wire, data);
200 if (pkt_len < length) {
201 return EMSGSIZE;
204 wire = (struct ctdb_reply_call_wire *)pkt;
206 if (pkt_len < length + wire->datalen) {
207 return EMSGSIZE;
210 memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
212 c->status = wire->status;
213 c->data.dsize = wire->datalen;
214 if (wire->datalen > 0) {
215 c->data.dptr = talloc_memdup(mem_ctx, wire->data,
216 wire->datalen);
217 if (c->data.dptr == NULL) {
218 return ENOMEM;
222 return 0;
225 int ctdb_reply_error_push(struct ctdb_req_header *h, struct ctdb_reply_error *c,
226 TALLOC_CTX *mem_ctx, uint8_t **pkt, size_t *pkt_len)
228 struct ctdb_reply_error_wire *wire;
229 uint8_t *buf;
230 size_t length, buflen;
231 int ret;
233 length = offsetof(struct ctdb_reply_error_wire, msg) + c->msg.dsize;
235 ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
236 if (ret != 0) {
237 return ret;
240 wire = (struct ctdb_reply_error_wire *)buf;
242 h->length = buflen;
243 memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
245 wire->status = c->status;
246 wire->msglen = c->msg.dsize;
247 if (c->msg.dsize > 0) {
248 memcpy(wire->msg, c->msg.dptr, c->msg.dsize);
251 *pkt = buf;
252 *pkt_len = buflen;
253 return 0;
256 int ctdb_reply_error_pull(uint8_t *pkt, size_t pkt_len,
257 struct ctdb_req_header *h,
258 TALLOC_CTX *mem_ctx,
259 struct ctdb_reply_error *c)
261 struct ctdb_reply_error_wire *wire;
262 size_t length;
264 length = offsetof(struct ctdb_reply_error_wire, msg);
265 if (pkt_len < length) {
266 return EMSGSIZE;
269 wire = (struct ctdb_reply_error_wire *)pkt;
271 if (pkt_len < length + wire->msglen) {
272 return EMSGSIZE;
275 memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
277 c->status = wire->status;
278 c->msg.dsize = wire->msglen;
279 if (wire->msglen > 0) {
280 c->msg.dptr = talloc_memdup(mem_ctx, wire->msg, wire->msglen);
281 if (c->msg.dptr == NULL) {
282 return ENOMEM;
286 return 0;
289 int ctdb_req_dmaster_push(struct ctdb_req_header *h, struct ctdb_req_dmaster *c,
290 TALLOC_CTX *mem_ctx, uint8_t **pkt, size_t *pkt_len)
292 struct ctdb_req_dmaster_wire *wire;
293 uint8_t *buf;
294 size_t length, buflen;
295 int ret;
297 length = offsetof(struct ctdb_req_dmaster_wire, data) +
298 c->key.dsize + c->data.dsize;
300 ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
301 if (ret != 0) {
302 return ret;
305 wire = (struct ctdb_req_dmaster_wire *)buf;
307 h->length = buflen;
308 memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
310 wire->db_id = c->db_id;
311 wire->rsn = c->rsn;
312 wire->dmaster = c->dmaster;
313 wire->keylen = c->key.dsize;
314 if (c->key.dsize > 0) {
315 memcpy(wire->data, c->key.dptr, c->key.dsize);
317 wire->datalen = c->data.dsize;
318 if (c->data.dsize > 0) {
319 memcpy(wire->data + c->key.dsize, c->data.dptr, c->data.dsize);
322 *pkt = buf;
323 *pkt_len = buflen;
324 return 0;
327 int ctdb_req_dmaster_pull(uint8_t *pkt, size_t pkt_len,
328 struct ctdb_req_header *h,
329 TALLOC_CTX *mem_ctx,
330 struct ctdb_req_dmaster *c)
332 struct ctdb_req_dmaster_wire *wire;
333 size_t length;
335 length = offsetof(struct ctdb_req_dmaster_wire, data);
336 if (pkt_len < length) {
337 return EMSGSIZE;
340 wire = (struct ctdb_req_dmaster_wire *)pkt;
342 if (pkt_len < length + wire->keylen + wire->datalen) {
343 return EMSGSIZE;
346 memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
348 c->db_id = wire->db_id;
349 c->rsn = wire->rsn;
350 c->dmaster = wire->dmaster;
351 c->key.dsize = wire->keylen;
352 c->key.dptr = talloc_memdup(mem_ctx, wire->data, wire->keylen);
353 if (c->key.dptr == NULL) {
354 return ENOMEM;
356 c->data.dsize = wire->datalen;
357 if (wire->datalen > 0) {
358 c->data.dptr = talloc_memdup(mem_ctx, wire->data + wire->keylen,
359 wire->datalen);
360 if (c->data.dptr == NULL) {
361 talloc_free(c->key.dptr);
362 return ENOMEM;
366 return 0;
369 int ctdb_reply_dmaster_push(struct ctdb_req_header *h,
370 struct ctdb_reply_dmaster *c,
371 TALLOC_CTX *mem_ctx, uint8_t **pkt, size_t *pkt_len)
373 struct ctdb_reply_dmaster_wire *wire;
374 uint8_t *buf;
375 size_t length, buflen;
376 int ret;
378 length = offsetof(struct ctdb_reply_dmaster_wire, data) +
379 c->key.dsize + c->data.dsize;
381 ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
382 if (ret != 0) {
383 return ret;
386 wire = (struct ctdb_reply_dmaster_wire *)buf;
388 h->length = buflen;
389 memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
391 wire->db_id = c->db_id;
392 wire->rsn = c->rsn;
393 wire->keylen = c->key.dsize;
394 if (c->key.dsize > 0) {
395 memcpy(wire->data, c->key.dptr, c->key.dsize);
397 wire->datalen = c->data.dsize;
398 if (c->data.dsize > 0) {
399 memcpy(wire->data + c->key.dsize, c->data.dptr, c->data.dsize);
402 *pkt = buf;
403 *pkt_len = buflen;
404 return 0;
407 int ctdb_reply_dmaster_pull(uint8_t *pkt, size_t pkt_len,
408 struct ctdb_req_header *h,
409 TALLOC_CTX *mem_ctx,
410 struct ctdb_reply_dmaster *c)
412 struct ctdb_reply_dmaster_wire *wire;
413 size_t length;
415 length = offsetof(struct ctdb_reply_dmaster_wire, data);
416 if (pkt_len < length) {
417 return EMSGSIZE;
420 wire = (struct ctdb_reply_dmaster_wire *)pkt;
422 if (pkt_len < length + wire->keylen + wire->datalen) {
423 return EMSGSIZE;
426 memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
428 c->db_id = wire->db_id;
429 c->rsn = wire->rsn;
430 c->key.dsize = wire->keylen;
431 c->key.dptr = talloc_memdup(mem_ctx, wire->data, wire->keylen);
432 if (c->key.dptr == NULL) {
433 return ENOMEM;
435 c->data.dsize = wire->datalen;
436 if (wire->datalen > 0) {
437 c->data.dptr = talloc_memdup(mem_ctx, wire->data + wire->keylen,
438 wire->datalen);
439 if (c->data.dptr == NULL) {
440 talloc_free(c->key.dptr);
441 return ENOMEM;
445 return 0;