From 5eac71502356a517f7998e365000a2019a8d9a18 Mon Sep 17 00:00:00 2001 From: Amitay Isaacs Date: Wed, 19 Jul 2017 14:41:45 +1000 Subject: [PATCH] ctdb-protocol: Fix marshalling for ctdb_reply_error Signed-off-by: Amitay Isaacs Reviewed-by: Martin Schwenke --- ctdb/protocol/protocol_call.c | 66 +++++++---------- ctdb/tests/src/protocol_ctdb_compat_test.c | 83 ++++++++++++++++++++++ ctdb/tests/src/protocol_ctdb_test.c | 43 +---------- 3 files changed, 113 insertions(+), 79 deletions(-) diff --git a/ctdb/protocol/protocol_call.c b/ctdb/protocol/protocol_call.c index 0e3cd9577e4..b6bd0a88dad 100644 --- a/ctdb/protocol/protocol_call.c +++ b/ctdb/protocol/protocol_call.c @@ -27,13 +27,6 @@ #include "protocol_api.h" #include "protocol_private.h" -struct ctdb_reply_error_wire { - struct ctdb_req_header hdr; - uint32_t status; - uint32_t msglen; - uint8_t msg[1]; -}; - struct ctdb_req_dmaster_wire { struct ctdb_req_header hdr; uint32_t db_id; @@ -268,16 +261,16 @@ int ctdb_reply_call_pull(uint8_t *buf, size_t buflen, size_t ctdb_reply_error_len(struct ctdb_req_header *h, struct ctdb_reply_error *c) { - return offsetof(struct ctdb_reply_error_wire, msg) + - ctdb_tdb_data_len(&c->msg); + return ctdb_req_header_len(h) + + ctdb_int32_len(&c->status) + + ctdb_tdb_datan_len(&c->msg); } int ctdb_reply_error_push(struct ctdb_req_header *h, struct ctdb_reply_error *c, uint8_t *buf, size_t *buflen) { - struct ctdb_reply_error_wire *wire = - (struct ctdb_reply_error_wire *)buf; - size_t length, np; + size_t offset = 0, np; + size_t length; length = ctdb_reply_error_len(h, c); if (*buflen < length) { @@ -286,11 +279,14 @@ int ctdb_reply_error_push(struct ctdb_req_header *h, struct ctdb_reply_error *c, } h->length = *buflen; - ctdb_req_header_push(h, (uint8_t *)&wire->hdr, &np); + ctdb_req_header_push(h, buf+offset, &np); + offset += np; - wire->status = c->status; - wire->msglen = ctdb_tdb_data_len(&c->msg); - ctdb_tdb_data_push(&c->msg, wire->msg, &np); + ctdb_int32_push(&c->status, buf+offset, &np); + offset += np; + + ctdb_tdb_datan_push(&c->msg, buf+offset, &np); + offset += np; return 0; } @@ -300,40 +296,32 @@ int ctdb_reply_error_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx, struct ctdb_reply_error *c) { - struct ctdb_reply_error_wire *wire = - (struct ctdb_reply_error_wire *)buf; - size_t length, np; + struct ctdb_req_header header; + size_t offset = 0, np; int ret; - length = offsetof(struct ctdb_reply_error_wire, msg); - if (buflen < length) { - return EMSGSIZE; - } - if (wire->msglen > buflen) { - return EMSGSIZE; - } - if (length + wire->msglen < length) { - return EMSGSIZE; - } - if (buflen < length + wire->msglen) { - 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->status = wire->status; + ret = ctdb_int32_pull(buf+offset, buflen-offset, &c->status, &np); + if (ret != 0) { + return ret; + } + offset += np; - ret = ctdb_tdb_data_pull(wire->msg, wire->msglen, mem_ctx, &c->msg, - &np); + ret = ctdb_tdb_datan_pull(buf+offset, buflen-offset, mem_ctx, &c->msg, + &np); if (ret != 0) { return ret; } + offset += np; return 0; } diff --git a/ctdb/tests/src/protocol_ctdb_compat_test.c b/ctdb/tests/src/protocol_ctdb_compat_test.c index 08712947437..884bc9eb520 100644 --- a/ctdb/tests/src/protocol_ctdb_compat_test.c +++ b/ctdb/tests/src/protocol_ctdb_compat_test.c @@ -415,11 +415,93 @@ static int ctdb_reply_call_pull_old(uint8_t *buf, size_t buflen, return 0; } +struct ctdb_reply_error_wire { + struct ctdb_req_header hdr; + uint32_t status; + uint32_t msglen; + uint8_t msg[1]; +}; + +static size_t ctdb_reply_error_len_old(struct ctdb_req_header *h, + struct ctdb_reply_error *c) +{ + return offsetof(struct ctdb_reply_error_wire, msg) + + ctdb_tdb_data_len(&c->msg); +} + +static int ctdb_reply_error_push_old(struct ctdb_req_header *h, + struct ctdb_reply_error *c, + uint8_t *buf, size_t *buflen) +{ + struct ctdb_reply_error_wire *wire = + (struct ctdb_reply_error_wire *)buf; + size_t length, np; + + length = ctdb_reply_error_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->status = c->status; + wire->msglen = ctdb_tdb_data_len(&c->msg); + ctdb_tdb_data_push(&c->msg, wire->msg, &np); + + return 0; +} + +static int ctdb_reply_error_pull_old(uint8_t *buf, size_t buflen, + struct ctdb_req_header *h, + TALLOC_CTX *mem_ctx, + struct ctdb_reply_error *c) +{ + struct ctdb_reply_error_wire *wire = + (struct ctdb_reply_error_wire *)buf; + size_t length, np; + int ret; + + length = offsetof(struct ctdb_reply_error_wire, msg); + if (buflen < length) { + return EMSGSIZE; + } + if (wire->msglen > buflen) { + return EMSGSIZE; + } + if (length + wire->msglen < length) { + return EMSGSIZE; + } + if (buflen < length + wire->msglen) { + return EMSGSIZE; + } + + if (h != NULL) { + ret = ctdb_req_header_pull_old((uint8_t *)&wire->hdr, buflen, + h); + if (ret != 0) { + return ret; + } + } + + c->status = wire->status; + + ret = ctdb_tdb_data_pull(wire->msg, wire->msglen, mem_ctx, &c->msg, + &np); + if (ret != 0) { + return ret; + } + + return 0; +} + COMPAT_CTDB1_TEST(struct ctdb_req_header, ctdb_req_header); 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); int main(int argc, char *argv[]) { @@ -432,6 +514,7 @@ int main(int argc, char *argv[]) COMPAT_TEST_FUNC(ctdb_req_call)(); COMPAT_TEST_FUNC(ctdb_reply_call)(); + COMPAT_TEST_FUNC(ctdb_reply_error)(); return 0; } diff --git a/ctdb/tests/src/protocol_ctdb_test.c b/ctdb/tests/src/protocol_ctdb_test.c index 3d14c3b1eaa..7ccc90fbc64 100644 --- a/ctdb/tests/src/protocol_ctdb_test.c +++ b/ctdb/tests/src/protocol_ctdb_test.c @@ -282,45 +282,8 @@ PROTOCOL_CTDB1_TEST(struct ctdb_req_header, ctdb_req_header); PROTOCOL_CTDB4_TEST(struct ctdb_req_call, ctdb_req_call, CTDB_REQ_CALL); PROTOCOL_CTDB4_TEST(struct ctdb_reply_call, ctdb_reply_call, CTDB_REPLY_CALL); - -static void test_ctdb_reply_error(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_error c, c2; - - printf("ctdb_reply_error\n"); - fflush(stdout); - - mem_ctx = talloc_new(NULL); - assert(mem_ctx != NULL); - - ctdb_req_header_fill(&h, GENERATION, CTDB_REPLY_ERROR, - DESTNODE, SRCNODE, REQID); - - fill_ctdb_reply_error(mem_ctx, &c); - datalen = ctdb_reply_error_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_error_push(&h, &c, pkt, &len); - assert(ret == EMSGSIZE); - assert(len == datalen); - ret = ctdb_reply_error_push(&h, &c, pkt, &pkt_len); - assert(ret == 0); - ret = ctdb_reply_error_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_error(&c, &c2); - - talloc_free(mem_ctx); -} +PROTOCOL_CTDB4_TEST(struct ctdb_reply_error, ctdb_reply_error, + CTDB_REPLY_ERROR); static void test_ctdb_req_dmaster(void) { @@ -606,7 +569,7 @@ int main(int argc, char *argv[]) TEST_FUNC(ctdb_req_call)(); TEST_FUNC(ctdb_reply_call)(); - test_ctdb_reply_error(); + TEST_FUNC(ctdb_reply_error)(); test_ctdb_req_dmaster(); test_ctdb_reply_dmaster(); -- 2.34.1