ctdb: Fix CID 1398179 Argument cannot be negative
[Samba.git] / ctdb / protocol / protocol_call.c
blob2dbd309317b1ea1b776d9a8e5c9bf317f7565d40
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 size_t ctdb_req_call_len(struct ctdb_req_header *h, struct ctdb_req_call *c)
76 return offsetof(struct ctdb_req_call_wire, data) +
77 ctdb_tdb_data_len(c->key) + ctdb_tdb_data_len(c->calldata);
80 int ctdb_req_call_push(struct ctdb_req_header *h, struct ctdb_req_call *c,
81 uint8_t *buf, size_t *buflen)
83 struct ctdb_req_call_wire *wire =
84 (struct ctdb_req_call_wire *)buf;
85 size_t length;
87 if (c->key.dsize == 0) {
88 return EINVAL;
91 length = ctdb_req_call_len(h, c);
92 if (*buflen < length) {
93 *buflen = length;
94 return EMSGSIZE;
97 h->length = *buflen;
98 ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
100 wire->flags = c->flags;
101 wire->db_id = c->db_id;
102 wire->callid = c->callid;
103 wire->hopcount = c->hopcount;
104 wire->keylen = ctdb_tdb_data_len(c->key);
105 wire->calldatalen = ctdb_tdb_data_len(c->calldata);
106 ctdb_tdb_data_push(c->key, wire->data);
107 ctdb_tdb_data_push(c->calldata, wire->data + wire->keylen);
109 return 0;
112 int ctdb_req_call_pull(uint8_t *buf, size_t buflen,
113 struct ctdb_req_header *h,
114 TALLOC_CTX *mem_ctx,
115 struct ctdb_req_call *c)
117 struct ctdb_req_call_wire *wire =
118 (struct ctdb_req_call_wire *)buf;
119 size_t length;
120 int ret;
122 length = offsetof(struct ctdb_req_call_wire, data);
123 if (buflen < length) {
124 return EMSGSIZE;
126 if (wire->keylen > buflen || wire->calldatalen > buflen) {
127 return EMSGSIZE;
129 if (length + wire->keylen < length) {
130 return EMSGSIZE;
132 if (length + wire->keylen + wire->calldatalen < length) {
133 return EMSGSIZE;
135 if (buflen < length + wire->keylen + wire->calldatalen) {
136 return EMSGSIZE;
139 if (h != NULL) {
140 ret = ctdb_req_header_pull((uint8_t *)&wire->hdr, buflen, h);
141 if (ret != 0) {
142 return ret;
146 c->flags = wire->flags;
147 c->db_id = wire->db_id;
148 c->callid = wire->callid;
149 c->hopcount = wire->hopcount;
151 ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key);
152 if (ret != 0) {
153 return ret;
156 ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->calldatalen,
157 mem_ctx, &c->calldata);
158 if (ret != 0) {
159 return ret;
162 return 0;
165 size_t ctdb_reply_call_len(struct ctdb_req_header *h,
166 struct ctdb_reply_call *c)
168 return offsetof(struct ctdb_reply_call_wire, data) +
169 ctdb_tdb_data_len(c->data);
172 int ctdb_reply_call_push(struct ctdb_req_header *h, struct ctdb_reply_call *c,
173 uint8_t *buf, size_t *buflen)
175 struct ctdb_reply_call_wire *wire =
176 (struct ctdb_reply_call_wire *)buf;
177 size_t length;
179 length = ctdb_reply_call_len(h, c);
180 if (*buflen < length) {
181 *buflen = length;
182 return EMSGSIZE;
185 h->length = *buflen;
186 ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
188 wire->status = c->status;
189 wire->datalen = ctdb_tdb_data_len(c->data);
190 ctdb_tdb_data_push(c->data, wire->data);
192 return 0;
195 int ctdb_reply_call_pull(uint8_t *buf, size_t buflen,
196 struct ctdb_req_header *h,
197 TALLOC_CTX *mem_ctx,
198 struct ctdb_reply_call *c)
200 struct ctdb_reply_call_wire *wire =
201 (struct ctdb_reply_call_wire *)buf;
202 size_t length;
203 int ret;
205 length = offsetof(struct ctdb_reply_call_wire, data);
206 if (buflen < length) {
207 return EMSGSIZE;
209 if (wire->datalen > buflen) {
210 return EMSGSIZE;
212 if (length + wire->datalen < length) {
213 return EMSGSIZE;
215 if (buflen < length + wire->datalen) {
216 return EMSGSIZE;
219 if (h != NULL) {
220 ret = ctdb_req_header_pull((uint8_t *)&wire->hdr, buflen, h);
221 if (ret != 0) {
222 return ret;
226 c->status = wire->status;
228 ret = ctdb_tdb_data_pull(wire->data, wire->datalen, mem_ctx, &c->data);
229 if (ret != 0) {
230 return ret;
233 return 0;
236 size_t ctdb_reply_error_len(struct ctdb_req_header *h,
237 struct ctdb_reply_error *c)
239 return offsetof(struct ctdb_reply_error_wire, msg) +
240 ctdb_tdb_data_len(c->msg);
243 int ctdb_reply_error_push(struct ctdb_req_header *h, struct ctdb_reply_error *c,
244 uint8_t *buf, size_t *buflen)
246 struct ctdb_reply_error_wire *wire =
247 (struct ctdb_reply_error_wire *)buf;
248 size_t length;
250 length = ctdb_reply_error_len(h, c);
251 if (*buflen < length) {
252 *buflen = length;
253 return EMSGSIZE;
256 h->length = *buflen;
257 ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
259 wire->status = c->status;
260 wire->msglen = ctdb_tdb_data_len(c->msg);
261 ctdb_tdb_data_push(c->msg, wire->msg);
263 return 0;
266 int ctdb_reply_error_pull(uint8_t *buf, size_t buflen,
267 struct ctdb_req_header *h,
268 TALLOC_CTX *mem_ctx,
269 struct ctdb_reply_error *c)
271 struct ctdb_reply_error_wire *wire =
272 (struct ctdb_reply_error_wire *)buf;
273 size_t length;
274 int ret;
276 length = offsetof(struct ctdb_reply_error_wire, msg);
277 if (buflen < length) {
278 return EMSGSIZE;
280 if (wire->msglen > buflen) {
281 return EMSGSIZE;
283 if (length + wire->msglen < length) {
284 return EMSGSIZE;
286 if (buflen < length + wire->msglen) {
287 return EMSGSIZE;
290 if (h != NULL) {
291 ret = ctdb_req_header_pull((uint8_t *)&wire->hdr, buflen, h);
292 if (ret != 0) {
293 return ret;
297 c->status = wire->status;
299 ret = ctdb_tdb_data_pull(wire->msg, wire->msglen, mem_ctx, &c->msg);
300 if (ret != 0) {
301 return ret;
304 return 0;
307 size_t ctdb_req_dmaster_len(struct ctdb_req_header *h,
308 struct ctdb_req_dmaster *c)
310 return offsetof(struct ctdb_req_dmaster_wire, data) +
311 ctdb_tdb_data_len(c->key) + ctdb_tdb_data_len(c->data);
314 int ctdb_req_dmaster_push(struct ctdb_req_header *h, struct ctdb_req_dmaster *c,
315 uint8_t *buf, size_t *buflen)
317 struct ctdb_req_dmaster_wire *wire =
318 (struct ctdb_req_dmaster_wire *)buf;
319 size_t length;
321 length = ctdb_req_dmaster_len(h, c);
322 if (*buflen < length) {
323 *buflen = length;
324 return EMSGSIZE;
327 h->length = *buflen;
328 ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
330 wire->db_id = c->db_id;
331 wire->rsn = c->rsn;
332 wire->dmaster = c->dmaster;
333 wire->keylen = ctdb_tdb_data_len(c->key);
334 wire->datalen = ctdb_tdb_data_len(c->data);
335 ctdb_tdb_data_push(c->key, wire->data);
336 ctdb_tdb_data_push(c->data, wire->data + wire->keylen);
338 return 0;
341 int ctdb_req_dmaster_pull(uint8_t *buf, size_t buflen,
342 struct ctdb_req_header *h,
343 TALLOC_CTX *mem_ctx,
344 struct ctdb_req_dmaster *c)
346 struct ctdb_req_dmaster_wire *wire =
347 (struct ctdb_req_dmaster_wire *)buf;
348 size_t length;
349 int ret;
351 length = offsetof(struct ctdb_req_dmaster_wire, data);
352 if (buflen < length) {
353 return EMSGSIZE;
355 if (wire->keylen > buflen || wire->datalen > buflen) {
356 return EMSGSIZE;
358 if (length + wire->keylen < length) {
359 return EMSGSIZE;
361 if (length + wire->keylen + wire->datalen < length) {
362 return EMSGSIZE;
364 if (buflen < length + wire->keylen + wire->datalen) {
365 return EMSGSIZE;
368 if (h != NULL) {
369 ret = ctdb_req_header_pull((uint8_t *)&wire->hdr, buflen, h);
370 if (ret != 0) {
371 return ret;
375 c->db_id = wire->db_id;
376 c->rsn = wire->rsn;
377 c->dmaster = wire->dmaster;
379 ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key);
380 if (ret != 0) {
381 return ret;
384 ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->datalen,
385 mem_ctx, &c->data);
386 if (ret != 0) {
387 return ret;
390 return 0;
393 size_t ctdb_reply_dmaster_len(struct ctdb_req_header *h,
394 struct ctdb_reply_dmaster *c)
396 return offsetof(struct ctdb_reply_dmaster_wire, data) +
397 ctdb_tdb_data_len(c->key) + ctdb_tdb_data_len(c->data);
400 int ctdb_reply_dmaster_push(struct ctdb_req_header *h,
401 struct ctdb_reply_dmaster *c,
402 uint8_t *buf, size_t *buflen)
404 struct ctdb_reply_dmaster_wire *wire =
405 (struct ctdb_reply_dmaster_wire *)buf;
406 size_t length;
408 length = ctdb_reply_dmaster_len(h, c);
409 if (*buflen < length) {
410 *buflen = length;
411 return EMSGSIZE;
414 h->length = *buflen;
415 ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
417 wire->db_id = c->db_id;
418 wire->rsn = c->rsn;
419 wire->keylen = ctdb_tdb_data_len(c->key);
420 wire->datalen = ctdb_tdb_data_len(c->data);
421 ctdb_tdb_data_push(c->key, wire->data);
422 ctdb_tdb_data_push(c->data, wire->data + wire->keylen);
424 return 0;
427 int ctdb_reply_dmaster_pull(uint8_t *buf, size_t buflen,
428 struct ctdb_req_header *h,
429 TALLOC_CTX *mem_ctx,
430 struct ctdb_reply_dmaster *c)
432 struct ctdb_reply_dmaster_wire *wire =
433 (struct ctdb_reply_dmaster_wire *)buf;
434 size_t length;
435 int ret;
437 length = offsetof(struct ctdb_reply_dmaster_wire, data);
438 if (buflen < length) {
439 return EMSGSIZE;
441 if (wire->keylen > buflen || wire->datalen > buflen) {
442 return EMSGSIZE;
444 if (length + wire->keylen < length) {
445 return EMSGSIZE;
447 if (length + wire->keylen + wire->datalen < length) {
448 return EMSGSIZE;
450 if (buflen < length + wire->keylen + wire->datalen) {
451 return EMSGSIZE;
454 if (h != NULL) {
455 ret = ctdb_req_header_pull((uint8_t *)&wire->hdr, buflen, h);
456 if (ret != 0) {
457 return ret;
461 c->db_id = wire->db_id;
462 c->rsn = wire->rsn;
464 ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key);
465 if (ret != 0) {
466 return ret;
469 ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->datalen,
470 mem_ctx, &c->data);
471 if (ret != 0) {
472 return ret;
475 return 0;