diff --git a/ctdb/protocol/protocol_message.c b/ctdb/protocol/protocol_message.c index 2a33acd01ae..f254ed19408 100644 --- a/ctdb/protocol/protocol_message.c +++ b/ctdb/protocol/protocol_message.c @@ -316,31 +316,40 @@ static int ctdb_message_data_pull(uint8_t *buf, size_t buflen, size_t ctdb_req_message_len(struct ctdb_req_header *h, struct ctdb_req_message *c) { - return offsetof(struct ctdb_req_message_wire, data) + - ctdb_message_data_len(&c->data, c->srvid); + uint32_t u32 = ctdb_message_data_len(&c->data, c->srvid); + + return ctdb_req_header_len(h) + + ctdb_uint64_len(&c->srvid) + + ctdb_uint32_len(&u32) + u32; } int ctdb_req_message_push(struct ctdb_req_header *h, - struct ctdb_req_message *message, + struct ctdb_req_message *c, uint8_t *buf, size_t *buflen) { - struct ctdb_req_message_wire *wire = - (struct ctdb_req_message_wire *)buf; - size_t length, np; + size_t offset = 0, np; + size_t length; + uint32_t u32; - length = ctdb_req_message_len(h, message); + length = ctdb_req_message_len(h, c); if (*buflen < length) { *buflen = length; return EMSGSIZE; } h->length = *buflen; - ctdb_req_header_push(h, (uint8_t *)&wire->hdr, &np); + ctdb_req_header_push(h, buf+offset, &np); + offset += np; - wire->srvid = message->srvid; - wire->datalen = ctdb_message_data_len(&message->data, message->srvid); - ctdb_message_data_push(&message->data, message->srvid, wire->data, - &np); + ctdb_uint64_push(&c->srvid, buf+offset, &np); + offset += np; + + u32 = ctdb_message_data_len(&c->data, c->srvid); + ctdb_uint32_push(&u32, buf+offset, &np); + offset += np; + + ctdb_message_data_push(&c->data, c->srvid, buf+offset, &np); + offset += np; return 0; } @@ -350,36 +359,44 @@ int ctdb_req_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx, struct ctdb_req_message *c) { - struct ctdb_req_message_wire *wire = - (struct ctdb_req_message_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_req_message_wire, data); - if (buflen < length) { - return EMSGSIZE; - } - if (wire->datalen > buflen) { - return EMSGSIZE; - } - if (length + wire->datalen < length) { - return EMSGSIZE; - } - if (buflen < length + 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->srvid = wire->srvid; - ret = ctdb_message_data_pull(wire->data, wire->datalen, wire->srvid, + ret = ctdb_uint64_pull(buf+offset, buflen-offset, &c->srvid, &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; + + if (buflen-offset < u32) { + return EMSGSIZE; + } + + ret = ctdb_message_data_pull(buf+offset, u32, c->srvid, mem_ctx, &c->data, &np); + if (ret != 0) { + return ret; + } + offset += np; + return ret; } diff --git a/ctdb/tests/cunit/protocol_test_101.sh b/ctdb/tests/cunit/protocol_test_101.sh index 8d6a74acc34..d21d16b31e4 100755 --- a/ctdb/tests/cunit/protocol_test_101.sh +++ b/ctdb/tests/cunit/protocol_test_101.sh @@ -52,6 +52,7 @@ output=$( generate_control_output "ctdb_req_control" generate_control_output "ctdb_reply_control" generate_message_output "ctdb_message_data" + generate_message_output "ctdb_req_message" echo "ctdb_req_message" ) diff --git a/ctdb/tests/src/protocol_common_ctdb.c b/ctdb/tests/src/protocol_common_ctdb.c index 6f3a738dabc..be9e2560cc6 100644 --- a/ctdb/tests/src/protocol_common_ctdb.c +++ b/ctdb/tests/src/protocol_common_ctdb.c @@ -1921,6 +1921,20 @@ void verify_ctdb_message_data(union ctdb_message_data *md, } } +void fill_ctdb_req_message(TALLOC_CTX *mem_ctx, struct ctdb_req_message *c, + uint64_t srvid) +{ + c->srvid = srvid; + fill_ctdb_message_data(mem_ctx, &c->data, srvid); +} + +void verify_ctdb_req_message(struct ctdb_req_message *c, + struct ctdb_req_message *c2) +{ + assert(c->srvid == c2->srvid); + verify_ctdb_message_data(&c->data, &c2->data, c->srvid); +} + void fill_ctdb_req_message_data(TALLOC_CTX *mem_ctx, struct ctdb_req_message_data *c) { diff --git a/ctdb/tests/src/protocol_common_ctdb.h b/ctdb/tests/src/protocol_common_ctdb.h index bdf2c02ae7b..f5bd16a8ef7 100644 --- a/ctdb/tests/src/protocol_common_ctdb.h +++ b/ctdb/tests/src/protocol_common_ctdb.h @@ -79,6 +79,11 @@ void fill_ctdb_message_data(TALLOC_CTX *mem_ctx, union ctdb_message_data *md, void verify_ctdb_message_data(union ctdb_message_data *md, union ctdb_message_data *md2, uint64_t srvid); +void fill_ctdb_req_message(TALLOC_CTX *mem_ctx, struct ctdb_req_message *c, + uint64_t srvid); +void verify_ctdb_req_message(struct ctdb_req_message *c, + struct ctdb_req_message *c2); + void fill_ctdb_req_message_data(TALLOC_CTX *mem_ctx, struct ctdb_req_message_data *c); void verify_ctdb_req_message_data(struct ctdb_req_message_data *c, diff --git a/ctdb/tests/src/protocol_ctdb_compat_test.c b/ctdb/tests/src/protocol_ctdb_compat_test.c index 960f131abb0..0de62f42999 100644 --- a/ctdb/tests/src/protocol_ctdb_compat_test.c +++ b/ctdb/tests/src/protocol_ctdb_compat_test.c @@ -27,6 +27,7 @@ #include "protocol/protocol_header.c" #include "protocol/protocol_call.c" #include "protocol/protocol_control.c" +#include "protocol/protocol_message.c" #include "tests/src/protocol_common.h" #include "tests/src/protocol_common_ctdb.h" @@ -891,6 +892,75 @@ static int ctdb_reply_control_pull_old(uint8_t *buf, size_t buflen, return 0; } +static size_t ctdb_req_message_len_old(struct ctdb_req_header *h, + struct ctdb_req_message *c) +{ + return offsetof(struct ctdb_req_message_wire, data) + + ctdb_message_data_len(&c->data, c->srvid); +} + +static int ctdb_req_message_push_old(struct ctdb_req_header *h, + struct ctdb_req_message *c, + uint8_t *buf, size_t *buflen) +{ + struct ctdb_req_message_wire *wire = + (struct ctdb_req_message_wire *)buf; + size_t length, np; + + length = ctdb_req_message_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->srvid = c->srvid; + wire->datalen = ctdb_message_data_len(&c->data, c->srvid); + ctdb_message_data_push(&c->data, c->srvid, wire->data, &np); + + return 0; +} + +static int ctdb_req_message_pull_old(uint8_t *buf, size_t buflen, + struct ctdb_req_header *h, + TALLOC_CTX *mem_ctx, + struct ctdb_req_message *c) +{ + struct ctdb_req_message_wire *wire = + (struct ctdb_req_message_wire *)buf; + size_t length, np; + int ret; + + length = offsetof(struct ctdb_req_message_wire, data); + if (buflen < length) { + return EMSGSIZE; + } + if (wire->datalen > buflen) { + return EMSGSIZE; + } + if (length + wire->datalen < length) { + return EMSGSIZE; + } + if (buflen < length + 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->srvid = wire->srvid; + ret = ctdb_message_data_pull(wire->data, wire->datalen, wire->srvid, + mem_ctx, &c->data, &np); + return ret; +} + COMPAT_CTDB1_TEST(struct ctdb_req_header, ctdb_req_header); @@ -903,11 +973,35 @@ COMPAT_CTDB4_TEST(struct ctdb_reply_dmaster, ctdb_reply_dmaster, CTDB_REPLY_DMAS COMPAT_CTDB5_TEST(struct ctdb_req_control, ctdb_req_control, CTDB_REQ_CONTROL); COMPAT_CTDB6_TEST(struct ctdb_reply_control, ctdb_reply_control, CTDB_REPLY_CONTROL); +COMPAT_CTDB7_TEST(struct ctdb_req_message, ctdb_req_message, CTDB_REQ_MESSAGE); + #define NUM_CONTROLS 151 int main(int argc, char *argv[]) { uint32_t opcode; + uint64_t test_srvid[] = { + CTDB_SRVID_BANNING, + CTDB_SRVID_ELECTION, + CTDB_SRVID_RECONFIGURE, + CTDB_SRVID_RELEASE_IP, + CTDB_SRVID_TAKE_IP, + CTDB_SRVID_SET_NODE_FLAGS, + CTDB_SRVID_RECD_UPDATE_IP, + CTDB_SRVID_VACUUM_FETCH, + CTDB_SRVID_DETACH_DATABASE, + CTDB_SRVID_MEM_DUMP, + CTDB_SRVID_GETLOG, + CTDB_SRVID_CLEARLOG, + CTDB_SRVID_PUSH_NODE_FLAGS, + CTDB_SRVID_RELOAD_NODES, + CTDB_SRVID_TAKEOVER_RUN, + CTDB_SRVID_REBALANCE_NODE, + CTDB_SRVID_DISABLE_TAKEOVER_RUNS, + CTDB_SRVID_DISABLE_RECOVERIES, + CTDB_SRVID_DISABLE_IP_CHECK, + }; + int i; if (argc == 2) { int seed = atoi(argv[1]); @@ -929,5 +1023,9 @@ int main(int argc, char *argv[]) COMPAT_TEST_FUNC(ctdb_reply_control)(opcode); } + for (i=0; i