mirror of
https://github.com/samba-team/samba.git
synced 2024-12-31 17:18:04 +03:00
ctdb-protocol: Fix marshalling for ctdb_reply_dmaster
Signed-off-by: Amitay Isaacs <amitay@gmail.com> Reviewed-by: Martin Schwenke <martin@meltin.net>
This commit is contained in:
parent
dbe16ce002
commit
4c4094cd94
@ -27,15 +27,6 @@
|
||||
#include "protocol_api.h"
|
||||
#include "protocol_private.h"
|
||||
|
||||
struct ctdb_reply_dmaster_wire {
|
||||
struct ctdb_req_header hdr;
|
||||
uint32_t db_id;
|
||||
uint64_t rsn;
|
||||
uint32_t keylen;
|
||||
uint32_t datalen;
|
||||
uint8_t data[1];
|
||||
};
|
||||
|
||||
size_t ctdb_req_call_len(struct ctdb_req_header *h, struct ctdb_req_call *c)
|
||||
{
|
||||
return ctdb_req_header_len(h) +
|
||||
@ -460,18 +451,21 @@ int ctdb_req_dmaster_pull(uint8_t *buf, size_t buflen,
|
||||
size_t ctdb_reply_dmaster_len(struct ctdb_req_header *h,
|
||||
struct ctdb_reply_dmaster *c)
|
||||
{
|
||||
return offsetof(struct ctdb_reply_dmaster_wire, data) +
|
||||
ctdb_tdb_data_len(&c->key) +
|
||||
ctdb_tdb_data_len(&c->data);
|
||||
return ctdb_req_header_len(h) +
|
||||
ctdb_uint32_len(&c->db_id) +
|
||||
ctdb_padding_len(4) +
|
||||
ctdb_uint64_len(&c->rsn) +
|
||||
ctdb_tdb_datan_len(&c->key) +
|
||||
ctdb_tdb_datan_len(&c->data);
|
||||
}
|
||||
|
||||
int ctdb_reply_dmaster_push(struct ctdb_req_header *h,
|
||||
struct ctdb_reply_dmaster *c,
|
||||
uint8_t *buf, size_t *buflen)
|
||||
{
|
||||
struct ctdb_reply_dmaster_wire *wire =
|
||||
(struct ctdb_reply_dmaster_wire *)buf;
|
||||
size_t length, np;
|
||||
size_t offset = 0, np;
|
||||
size_t length;
|
||||
uint32_t u32;
|
||||
|
||||
length = ctdb_reply_dmaster_len(h, c);
|
||||
if (*buflen < length) {
|
||||
@ -480,14 +474,31 @@ int ctdb_reply_dmaster_push(struct ctdb_req_header *h,
|
||||
}
|
||||
|
||||
h->length = *buflen;
|
||||
ctdb_req_header_push(h, (uint8_t *)&wire->hdr, &np);
|
||||
ctdb_req_header_push(h, buf+offset, &np);
|
||||
offset += np;
|
||||
|
||||
wire->db_id = c->db_id;
|
||||
wire->rsn = c->rsn;
|
||||
wire->keylen = ctdb_tdb_data_len(&c->key);
|
||||
wire->datalen = ctdb_tdb_data_len(&c->data);
|
||||
ctdb_tdb_data_push(&c->key, wire->data, &np);
|
||||
ctdb_tdb_data_push(&c->data, wire->data + wire->keylen, &np);
|
||||
ctdb_uint32_push(&c->db_id, buf+offset, &np);
|
||||
offset += np;
|
||||
|
||||
ctdb_padding_push(4, buf+offset, &np);
|
||||
offset += np;
|
||||
|
||||
ctdb_uint64_push(&c->rsn, buf+offset, &np);
|
||||
offset += np;
|
||||
|
||||
u32 = ctdb_tdb_data_len(&c->key);
|
||||
ctdb_uint32_push(&u32, buf+offset, &np);
|
||||
offset += np;
|
||||
|
||||
u32 = ctdb_tdb_data_len(&c->data);
|
||||
ctdb_uint32_push(&u32, buf+offset, &np);
|
||||
offset += np;
|
||||
|
||||
ctdb_tdb_data_push(&c->key, buf+offset, &np);
|
||||
offset += np;
|
||||
|
||||
ctdb_tdb_data_push(&c->data, buf+offset, &np);
|
||||
offset += np;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -497,50 +508,74 @@ int ctdb_reply_dmaster_pull(uint8_t *buf, size_t buflen,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct ctdb_reply_dmaster *c)
|
||||
{
|
||||
struct ctdb_reply_dmaster_wire *wire =
|
||||
(struct ctdb_reply_dmaster_wire *)buf;
|
||||
size_t length, np;
|
||||
struct ctdb_req_header header;
|
||||
size_t offset = 0, np;
|
||||
uint32_t u32;
|
||||
int ret;
|
||||
|
||||
length = offsetof(struct ctdb_reply_dmaster_wire, data);
|
||||
if (buflen < length) {
|
||||
return EMSGSIZE;
|
||||
}
|
||||
if (wire->keylen > buflen || wire->datalen > buflen) {
|
||||
return EMSGSIZE;
|
||||
}
|
||||
if (length + wire->keylen < length) {
|
||||
return EMSGSIZE;
|
||||
}
|
||||
if (length + wire->keylen + wire->datalen < length) {
|
||||
return EMSGSIZE;
|
||||
}
|
||||
if (buflen < length + wire->keylen + wire->datalen) {
|
||||
return EMSGSIZE;
|
||||
ret = ctdb_req_header_pull(buf+offset, buflen-offset, &header, &np);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
offset += np;
|
||||
|
||||
if (h != NULL) {
|
||||
ret = ctdb_req_header_pull((uint8_t *)&wire->hdr, buflen, h,
|
||||
&np);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
*h = header;
|
||||
}
|
||||
|
||||
c->db_id = wire->db_id;
|
||||
c->rsn = wire->rsn;
|
||||
ret = ctdb_uint32_pull(buf+offset, buflen-offset, &c->db_id, &np);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
offset += np;
|
||||
|
||||
ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key,
|
||||
ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
offset += np;
|
||||
|
||||
ret = ctdb_uint64_pull(buf+offset, buflen-offset, &c->rsn, &np);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
offset += np;
|
||||
|
||||
ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
offset += np;
|
||||
c->key.dsize = u32;
|
||||
|
||||
ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
offset += np;
|
||||
c->data.dsize = u32;
|
||||
|
||||
if (buflen-offset < c->key.dsize) {
|
||||
return EMSGSIZE;
|
||||
}
|
||||
|
||||
ret = ctdb_tdb_data_pull(buf+offset, c->key.dsize, mem_ctx, &c->key,
|
||||
&np);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
offset += np;
|
||||
|
||||
ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->datalen,
|
||||
mem_ctx, &c->data, &np);
|
||||
if (buflen-offset < c->data.dsize) {
|
||||
return EMSGSIZE;
|
||||
}
|
||||
|
||||
ret = ctdb_tdb_data_pull(buf+offset, c->data.dsize, mem_ctx, &c->data,
|
||||
&np);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
offset += np;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -595,6 +595,102 @@ static int ctdb_req_dmaster_pull_old(uint8_t *buf, size_t buflen,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ctdb_reply_dmaster_wire {
|
||||
struct ctdb_req_header hdr;
|
||||
uint32_t db_id;
|
||||
uint64_t rsn;
|
||||
uint32_t keylen;
|
||||
uint32_t datalen;
|
||||
uint8_t data[1];
|
||||
};
|
||||
|
||||
static size_t ctdb_reply_dmaster_len_old(struct ctdb_req_header *h,
|
||||
struct ctdb_reply_dmaster *c)
|
||||
{
|
||||
return offsetof(struct ctdb_reply_dmaster_wire, data) +
|
||||
ctdb_tdb_data_len(&c->key) + ctdb_tdb_data_len(&c->data);
|
||||
}
|
||||
|
||||
static int ctdb_reply_dmaster_push_old(struct ctdb_req_header *h,
|
||||
struct ctdb_reply_dmaster *c,
|
||||
uint8_t *buf, size_t *buflen)
|
||||
{
|
||||
struct ctdb_reply_dmaster_wire *wire =
|
||||
(struct ctdb_reply_dmaster_wire *)buf;
|
||||
size_t length, np;
|
||||
|
||||
length = ctdb_reply_dmaster_len_old(h, c);
|
||||
if (*buflen < length) {
|
||||
*buflen = length;
|
||||
return EMSGSIZE;
|
||||
}
|
||||
|
||||
h->length = *buflen;
|
||||
ctdb_req_header_push_old(h, (uint8_t *)&wire->hdr);
|
||||
|
||||
wire->db_id = c->db_id;
|
||||
wire->rsn = c->rsn;
|
||||
wire->keylen = ctdb_tdb_data_len(&c->key);
|
||||
wire->datalen = ctdb_tdb_data_len(&c->data);
|
||||
ctdb_tdb_data_push(&c->key, wire->data, &np);
|
||||
ctdb_tdb_data_push(&c->data, wire->data + wire->keylen, &np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctdb_reply_dmaster_pull_old(uint8_t *buf, size_t buflen,
|
||||
struct ctdb_req_header *h,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct ctdb_reply_dmaster *c)
|
||||
{
|
||||
struct ctdb_reply_dmaster_wire *wire =
|
||||
(struct ctdb_reply_dmaster_wire *)buf;
|
||||
size_t length, np;
|
||||
int ret;
|
||||
|
||||
length = offsetof(struct ctdb_reply_dmaster_wire, data);
|
||||
if (buflen < length) {
|
||||
return EMSGSIZE;
|
||||
}
|
||||
if (wire->keylen > buflen || wire->datalen > buflen) {
|
||||
return EMSGSIZE;
|
||||
}
|
||||
if (length + wire->keylen < length) {
|
||||
return EMSGSIZE;
|
||||
}
|
||||
if (length + wire->keylen + wire->datalen < length) {
|
||||
return EMSGSIZE;
|
||||
}
|
||||
if (buflen < length + wire->keylen + wire->datalen) {
|
||||
return EMSGSIZE;
|
||||
}
|
||||
|
||||
if (h != NULL) {
|
||||
ret = ctdb_req_header_pull_old((uint8_t *)&wire->hdr, buflen,
|
||||
h);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
c->db_id = wire->db_id;
|
||||
c->rsn = wire->rsn;
|
||||
|
||||
ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key,
|
||||
&np);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->datalen,
|
||||
mem_ctx, &c->data, &np);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
COMPAT_CTDB1_TEST(struct ctdb_req_header, ctdb_req_header);
|
||||
|
||||
@ -602,6 +698,7 @@ COMPAT_CTDB4_TEST(struct ctdb_req_call, ctdb_req_call, CTDB_REQ_CALL);
|
||||
COMPAT_CTDB4_TEST(struct ctdb_reply_call, ctdb_reply_call, CTDB_REPLY_CALL);
|
||||
COMPAT_CTDB4_TEST(struct ctdb_reply_error, ctdb_reply_error, CTDB_REPLY_ERROR);
|
||||
COMPAT_CTDB4_TEST(struct ctdb_req_dmaster, ctdb_req_dmaster, CTDB_REQ_DMASTER);
|
||||
COMPAT_CTDB4_TEST(struct ctdb_reply_dmaster, ctdb_reply_dmaster, CTDB_REPLY_DMASTER);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@ -616,6 +713,7 @@ int main(int argc, char *argv[])
|
||||
COMPAT_TEST_FUNC(ctdb_reply_call)();
|
||||
COMPAT_TEST_FUNC(ctdb_reply_error)();
|
||||
COMPAT_TEST_FUNC(ctdb_req_dmaster)();
|
||||
COMPAT_TEST_FUNC(ctdb_reply_dmaster)();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -286,45 +286,8 @@ PROTOCOL_CTDB4_TEST(struct ctdb_reply_error, ctdb_reply_error,
|
||||
CTDB_REPLY_ERROR);
|
||||
PROTOCOL_CTDB4_TEST(struct ctdb_req_dmaster, ctdb_req_dmaster,
|
||||
CTDB_REQ_DMASTER);
|
||||
|
||||
static void test_ctdb_reply_dmaster(void)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx;
|
||||
uint8_t *pkt;
|
||||
size_t datalen, pkt_len, len;
|
||||
int ret;
|
||||
struct ctdb_req_header h, h2;
|
||||
struct ctdb_reply_dmaster c, c2;
|
||||
|
||||
printf("ctdb_reply_dmaster\n");
|
||||
fflush(stdout);
|
||||
|
||||
mem_ctx = talloc_new(NULL);
|
||||
assert(mem_ctx != NULL);
|
||||
|
||||
ctdb_req_header_fill(&h, GENERATION, CTDB_REPLY_DMASTER,
|
||||
DESTNODE, SRCNODE, REQID);
|
||||
|
||||
fill_ctdb_reply_dmaster(mem_ctx, &c);
|
||||
datalen = ctdb_reply_dmaster_len(&h, &c);
|
||||
ret = ctdb_allocate_pkt(mem_ctx, datalen, &pkt, &pkt_len);
|
||||
assert(ret == 0);
|
||||
assert(pkt != NULL);
|
||||
assert(pkt_len >= datalen);
|
||||
len = 0;
|
||||
ret = ctdb_reply_dmaster_push(&h, &c, pkt, &len);
|
||||
assert(ret == EMSGSIZE);
|
||||
assert(len == datalen);
|
||||
ret = ctdb_reply_dmaster_push(&h, &c, pkt, &pkt_len);
|
||||
assert(ret == 0);
|
||||
ret = ctdb_reply_dmaster_pull(pkt, pkt_len, &h2, mem_ctx, &c2);
|
||||
assert(ret == 0);
|
||||
verify_ctdb_req_header(&h, &h2);
|
||||
assert(h2.length == pkt_len);
|
||||
verify_ctdb_reply_dmaster(&c, &c2);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
}
|
||||
PROTOCOL_CTDB4_TEST(struct ctdb_reply_dmaster, ctdb_reply_dmaster,
|
||||
CTDB_REPLY_DMASTER);
|
||||
|
||||
#define NUM_CONTROLS 151
|
||||
|
||||
@ -534,7 +497,7 @@ int main(int argc, char *argv[])
|
||||
TEST_FUNC(ctdb_reply_call)();
|
||||
TEST_FUNC(ctdb_reply_error)();
|
||||
TEST_FUNC(ctdb_req_dmaster)();
|
||||
test_ctdb_reply_dmaster();
|
||||
TEST_FUNC(ctdb_reply_dmaster)();
|
||||
|
||||
test_ctdb_req_control_data();
|
||||
test_ctdb_reply_control_data();
|
||||
|
Loading…
Reference in New Issue
Block a user