1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-10 01:18:15 +03:00

ctdb-protocol: Fix marshalling for ctdb_reply_control

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
This commit is contained in:
Amitay Isaacs 2017-08-03 18:05:41 +10:00 committed by Martin Schwenke
parent bf782343a5
commit 955426d47c
4 changed files with 212 additions and 125 deletions

View File

@ -27,14 +27,6 @@
#include "protocol_api.h"
#include "protocol_private.h"
struct ctdb_reply_control_wire {
struct ctdb_req_header hdr;
int32_t status;
uint32_t datalen;
uint32_t errorlen;
uint8_t data[1];
};
static size_t ctdb_req_control_data_len(struct ctdb_req_control_data *cd)
{
size_t len = 0;
@ -1910,42 +1902,65 @@ int ctdb_req_control_pull(uint8_t *buf, size_t buflen,
size_t ctdb_reply_control_len(struct ctdb_req_header *h,
struct ctdb_reply_control *c)
{
return offsetof(struct ctdb_reply_control_wire, data) +
(c->status == 0 ?
ctdb_reply_control_data_len(&c->rdata) :
ctdb_string_len(&c->errmsg));
uint32_t dsize, esize;
if (c->status == 0) {
dsize = ctdb_reply_control_data_len(&c->rdata);
esize = 0;
} else {
dsize = 0;
esize = ctdb_string_len(&c->errmsg);
}
return ctdb_req_header_len(h) +
ctdb_int32_len(&c->status) +
ctdb_uint32_len(&dsize) +
ctdb_uint32_len(&esize) +
dsize + esize;
}
int ctdb_reply_control_push(struct ctdb_req_header *h,
struct ctdb_reply_control *reply,
struct ctdb_reply_control *c,
uint8_t *buf, size_t *buflen)
{
struct ctdb_reply_control_wire *wire =
(struct ctdb_reply_control_wire *)buf;
size_t length, np;
size_t offset = 0, np;
size_t length;
uint32_t dsize, esize;
length = ctdb_reply_control_len(h, reply);
length = ctdb_reply_control_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->status = reply->status;
ctdb_int32_push(&c->status, buf+offset, &np);
offset += np;
if (reply->status == 0) {
wire->datalen = ctdb_reply_control_data_len(&reply->rdata);
wire->errorlen = 0;
ctdb_reply_control_data_push(&reply->rdata, wire->data, &np);
if (c->status == 0) {
dsize = ctdb_reply_control_data_len(&c->rdata);
esize = 0;
} else {
wire->datalen = 0;
wire->errorlen = ctdb_string_len(&reply->errmsg);
ctdb_string_push(&reply->errmsg, wire->data + wire->datalen,
&np);
dsize = 0;
esize = ctdb_string_len(&c->errmsg);
}
ctdb_uint32_push(&dsize, buf+offset, &np);
offset += np;
ctdb_uint32_push(&esize, buf+offset, &np);
offset += np;
if (c->status == 0) {
ctdb_reply_control_data_push(&c->rdata, buf+offset, &np);
} else {
ctdb_string_push(&c->errmsg, buf+offset, &np);
}
offset += np;
return 0;
}
@ -1954,52 +1969,66 @@ int ctdb_reply_control_pull(uint8_t *buf, size_t buflen, uint32_t opcode,
TALLOC_CTX *mem_ctx,
struct ctdb_reply_control *c)
{
struct ctdb_reply_control_wire *wire =
(struct ctdb_reply_control_wire *)buf;
size_t length, np;
struct ctdb_req_header header;
size_t offset = 0, np;
uint32_t dsize, esize;
int ret;
length = offsetof(struct ctdb_reply_control_wire, data);
if (buflen < length) {
return EMSGSIZE;
}
if (wire->datalen > buflen || wire->errorlen > buflen) {
return EMSGSIZE;
}
if (length + wire->datalen < length) {
return EMSGSIZE;
}
if (length + wire->datalen + wire->errorlen < length) {
return EMSGSIZE;
}
if (buflen < length + wire->datalen + wire->errorlen) {
return EMSGSIZE;
}
if (h != NULL) {
ret = ctdb_req_header_pull((uint8_t *)&wire->hdr, buflen, h,
&np);
if (ret != 0) {
return ret;
}
}
c->status = wire->status;
if (c->status != -1) {
ret = ctdb_reply_control_data_pull(wire->data, wire->datalen,
opcode, mem_ctx,
&c->rdata, &np);
if (ret != 0) {
return ret;
}
}
ret = ctdb_string_pull(wire->data + wire->datalen, wire->errorlen,
mem_ctx, &c->errmsg, &np);
ret = ctdb_req_header_pull(buf+offset, buflen-offset, &header, &np);
if (ret != 0) {
return ret;
}
offset += np;
if (h != NULL) {
*h = header;
}
ret = ctdb_int32_pull(buf+offset, buflen-offset, &c->status, &np);
if (ret != 0) {
return ret;
}
offset += np;
ret = ctdb_uint32_pull(buf+offset, buflen-offset, &dsize, &np);
if (ret != 0) {
return ret;
}
offset += np;
ret = ctdb_uint32_pull(buf+offset, buflen-offset, &esize, &np);
if (ret != 0) {
return ret;
}
offset += np;
c->errmsg = NULL;
if (c->status == 0) {
if (buflen-offset < dsize) {
return EMSGSIZE;
}
ret = ctdb_reply_control_data_pull(buf+offset, dsize,
opcode, mem_ctx, &c->rdata,
&np);
if (ret != 0) {
return ret;
}
offset += np;
} else {
if (buflen-offset < esize) {
return EMSGSIZE;
}
ret = ctdb_string_pull(buf+offset, esize, mem_ctx, &c->errmsg,
&np);
if (ret != 0) {
return ret;
}
offset += np;
}
return 0;
}

View File

@ -4,13 +4,6 @@
last_control=150
control_output=$(
for i in $(seq 0 $last_control) ; do
echo -n "$i.. "
done
echo
)
generate_control_output ()
{
for i in $(seq 0 $last_control) ; do
@ -28,8 +21,7 @@ output=$(
generate_control_output "ctdb_req_control_data"
generate_control_output "ctdb_reply_control_data"
generate_control_output "ctdb_req_control"
echo "ctdb_reply_control"
echo "$control_output"
generate_control_output "ctdb_reply_control"
echo "ctdb_req_message"
)

View File

@ -786,6 +786,111 @@ static int ctdb_req_control_pull_old(uint8_t *buf, size_t buflen,
return 0;
}
struct ctdb_reply_control_wire {
struct ctdb_req_header hdr;
int32_t status;
uint32_t datalen;
uint32_t errorlen;
uint8_t data[1];
};
static size_t ctdb_reply_control_len_old(struct ctdb_req_header *h,
struct ctdb_reply_control *c)
{
return offsetof(struct ctdb_reply_control_wire, data) +
(c->status == 0 ?
ctdb_reply_control_data_len(&c->rdata) :
ctdb_string_len(&c->errmsg));
}
static int ctdb_reply_control_push_old(struct ctdb_req_header *h,
struct ctdb_reply_control *c,
uint8_t *buf, size_t *buflen)
{
struct ctdb_reply_control_wire *wire =
(struct ctdb_reply_control_wire *)buf;
size_t length, np;
length = ctdb_reply_control_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;
if (c->status == 0) {
wire->datalen = ctdb_reply_control_data_len(&c->rdata);
wire->errorlen = 0;
ctdb_reply_control_data_push(&c->rdata, wire->data, &np);
} else {
wire->datalen = 0;
wire->errorlen = ctdb_string_len(&c->errmsg);
ctdb_string_push(&c->errmsg, wire->data + wire->datalen, &np);
}
return 0;
}
static int ctdb_reply_control_pull_old(uint8_t *buf, size_t buflen,
uint32_t opcode,
struct ctdb_req_header *h,
TALLOC_CTX *mem_ctx,
struct ctdb_reply_control *c)
{
struct ctdb_reply_control_wire *wire =
(struct ctdb_reply_control_wire *)buf;
size_t length, np;
int ret;
length = offsetof(struct ctdb_reply_control_wire, data);
if (buflen < length) {
return EMSGSIZE;
}
if (wire->datalen > buflen || wire->errorlen > buflen) {
return EMSGSIZE;
}
if (length + wire->datalen < length) {
return EMSGSIZE;
}
if (length + wire->datalen + wire->errorlen < length) {
return EMSGSIZE;
}
if (buflen < length + wire->datalen + wire->errorlen) {
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;
if (c->status != -1) {
ret = ctdb_reply_control_data_pull(wire->data, wire->datalen,
opcode, mem_ctx,
&c->rdata, &np);
if (ret != 0) {
return ret;
}
}
ret = ctdb_string_pull(wire->data + wire->datalen, wire->errorlen,
mem_ctx, &c->errmsg, &np);
if (ret != 0) {
return ret;
}
return 0;
}
COMPAT_CTDB1_TEST(struct ctdb_req_header, ctdb_req_header);
@ -796,6 +901,7 @@ 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);
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);
#define NUM_CONTROLS 151
@ -819,6 +925,9 @@ int main(int argc, char *argv[])
for (opcode=0; opcode<NUM_CONTROLS; opcode++) {
COMPAT_TEST_FUNC(ctdb_req_control)(opcode);
}
for (opcode=0; opcode<NUM_CONTROLS; opcode++) {
COMPAT_TEST_FUNC(ctdb_reply_control)(opcode);
}
return 0;
}

View File

@ -296,53 +296,8 @@ PROTOCOL_CTDB2_TEST(struct ctdb_reply_control_data, ctdb_reply_control_data);
PROTOCOL_CTDB5_TEST(struct ctdb_req_control, ctdb_req_control,
CTDB_REQ_CONTROL);
static void test_ctdb_reply_control(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_control c, c2;
uint32_t opcode;
printf("ctdb_reply_control\n");
fflush(stdout);
ctdb_req_header_fill(&h, GENERATION, CTDB_REPLY_CONTROL,
DESTNODE, SRCNODE, REQID);
for (opcode=0; opcode<NUM_CONTROLS; opcode++) {
mem_ctx = talloc_new(NULL);
assert(mem_ctx != NULL);
printf("%u.. ", opcode);
fflush(stdout);
fill_ctdb_reply_control(mem_ctx, &c, opcode);
datalen = ctdb_reply_control_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_control_push(&h, &c, pkt, &len);
assert(ret == EMSGSIZE);
assert(len == datalen);
ret = ctdb_reply_control_push(&h, &c, pkt, &pkt_len);
assert(ret == 0);
ret = ctdb_reply_control_pull(pkt, pkt_len, opcode, &h2, mem_ctx, &c2);
assert(ret == 0);
verify_ctdb_req_header(&h, &h2);
assert(h2.length == pkt_len);
verify_ctdb_reply_control(&c, &c2);
talloc_free(mem_ctx);
}
printf("\n");
fflush(stdout);
}
PROTOCOL_CTDB6_TEST(struct ctdb_reply_control, ctdb_reply_control,
CTDB_REPLY_CONTROL);
static void test_ctdb_req_message_data(void)
{
@ -410,7 +365,9 @@ int main(int argc, char *argv[])
for (opcode=0; opcode<NUM_CONTROLS; opcode++) {
TEST_FUNC(ctdb_req_control)(opcode);
}
test_ctdb_reply_control();
for (opcode=0; opcode<NUM_CONTROLS; opcode++) {
TEST_FUNC(ctdb_reply_control)(opcode);
}
test_ctdb_req_message_data();