ctdb-protocol: Fix marshalling for ctdb_req_dmaster
authorAmitay Isaacs <amitay@gmail.com>
Wed, 19 Jul 2017 04:58:21 +0000 (14:58 +1000)
committerMartin Schwenke <martins@samba.org>
Wed, 30 Aug 2017 12:59:25 +0000 (14:59 +0200)
Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
ctdb/protocol/protocol_call.c
ctdb/tests/src/protocol_ctdb_compat_test.c
ctdb/tests/src/protocol_ctdb_test.c

index b6bd0a88dad251a04da73151fd66b7a69d7f43e9..b1805155f6388f952562f472f02e5f27b6abf83e 100644 (file)
 #include "protocol_api.h"
 #include "protocol_private.h"
 
-struct ctdb_req_dmaster_wire {
-       struct ctdb_req_header hdr;
-       uint32_t db_id;
-       uint64_t rsn;
-       uint32_t dmaster;
-       uint32_t keylen;
-       uint32_t datalen;
-       uint8_t  data[1];
-};
-
 struct ctdb_reply_dmaster_wire {
        struct ctdb_req_header hdr;
        uint32_t db_id;
@@ -329,17 +319,21 @@ int ctdb_reply_error_pull(uint8_t *buf, size_t buflen,
 size_t ctdb_req_dmaster_len(struct ctdb_req_header *h,
                            struct ctdb_req_dmaster *c)
 {
-       return offsetof(struct ctdb_req_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_uint32_len(&c->dmaster) +
+               ctdb_tdb_datan_len(&c->key) +
+               ctdb_tdb_datan_len(&c->data);
 }
 
 int ctdb_req_dmaster_push(struct ctdb_req_header *h, struct ctdb_req_dmaster *c,
                          uint8_t *buf, size_t *buflen)
 {
-       struct ctdb_req_dmaster_wire *wire =
-               (struct ctdb_req_dmaster_wire *)buf;
-       size_t length, np;
+       size_t offset = 0, np;
+       size_t length;
+       uint32_t u32;
 
        length = ctdb_req_dmaster_len(h, c);
        if (*buflen < length) {
@@ -348,15 +342,34 @@ int ctdb_req_dmaster_push(struct ctdb_req_header *h, struct ctdb_req_dmaster *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->db_id = c->db_id;
-       wire->rsn = c->rsn;
-       wire->dmaster = c->dmaster;
-       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;
+
+       ctdb_uint32_push(&c->dmaster, 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;
 }
@@ -366,51 +379,80 @@ int ctdb_req_dmaster_pull(uint8_t *buf, size_t buflen,
                          TALLOC_CTX *mem_ctx,
                          struct ctdb_req_dmaster *c)
 {
-       struct ctdb_req_dmaster_wire *wire =
-               (struct ctdb_req_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_req_dmaster_wire, data);
-       if (buflen < length) {
-               return EMSGSIZE;
+       ret = ctdb_req_header_pull(buf+offset, buflen-offset, &header, &np);
+       if (ret != 0) {
+               return ret;
        }
-       if (wire->keylen > buflen || wire->datalen > buflen) {
-               return EMSGSIZE;
+       offset += np;
+
+       if (h != NULL) {
+               *h = header;
        }
-       if (length + wire->keylen < length) {
-               return EMSGSIZE;
+
+       ret = ctdb_uint32_pull(buf+offset, buflen-offset, &c->db_id, &np);
+       if (ret != 0) {
+               return ret;
        }
-       if (length + wire->keylen + wire->datalen < length) {
-               return EMSGSIZE;
+       offset += np;
+
+       ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
+       if (ret != 0) {
+               return ret;
        }
-       if (buflen < length + wire->keylen + wire->datalen) {
-               return EMSGSIZE;
+       offset += np;
+
+       ret = ctdb_uint64_pull(buf+offset, buflen-offset, &c->rsn, &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;
-               }
+       ret = ctdb_uint32_pull(buf+offset, buflen-offset, &c->dmaster, &np);
+       if (ret != 0) {
+               return ret;
        }
+       offset += np;
 
-       c->db_id = wire->db_id;
-       c->rsn = wire->rsn;
-       c->dmaster = wire->dmaster;
+       ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
+       if (ret != 0) {
+               return ret;
+       }
+       offset += np;
+       c->key.dsize = u32;
 
-       ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key,
+       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;
+
+       if (buflen-offset < c->data.dsize) {
+               return EMSGSIZE;
+       }
 
-       ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->datalen,
-                                mem_ctx, &c->data, &np);
+       ret = ctdb_tdb_data_pull(buf+offset, c->data.dsize, mem_ctx, &c->data,
+                                &np);
        if (ret != 0) {
                return ret;
        }
+       offset += np;
 
        return 0;
 }
index 884bc9eb5209da5b7a60c978e82c5c12376de458..5a751d47626670249d877b529110ce28b9de1f6b 100644 (file)
@@ -496,12 +496,112 @@ static int ctdb_reply_error_pull_old(uint8_t *buf, size_t buflen,
        return 0;
 }
 
+struct ctdb_req_dmaster_wire {
+       struct ctdb_req_header hdr;
+       uint32_t db_id;
+       uint64_t rsn;
+       uint32_t dmaster;
+       uint32_t keylen;
+       uint32_t datalen;
+       uint8_t  data[1];
+};
+
+static size_t ctdb_req_dmaster_len_old(struct ctdb_req_header *h,
+                                      struct ctdb_req_dmaster *c)
+{
+       return offsetof(struct ctdb_req_dmaster_wire, data) +
+               ctdb_tdb_data_len(&c->key) + ctdb_tdb_data_len(&c->data);
+}
+
+static int ctdb_req_dmaster_push_old(struct ctdb_req_header *h,
+                                    struct ctdb_req_dmaster *c,
+                                    uint8_t *buf, size_t *buflen)
+{
+       struct ctdb_req_dmaster_wire *wire =
+               (struct ctdb_req_dmaster_wire *)buf;
+       size_t length, np;
+
+       length = ctdb_req_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->dmaster = c->dmaster;
+       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_req_dmaster_pull_old(uint8_t *buf, size_t buflen,
+                                    struct ctdb_req_header *h,
+                                    TALLOC_CTX *mem_ctx,
+                                    struct ctdb_req_dmaster *c)
+{
+       struct ctdb_req_dmaster_wire *wire =
+               (struct ctdb_req_dmaster_wire *)buf;
+       size_t length, np;
+       int ret;
+
+       length = offsetof(struct ctdb_req_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;
+       c->dmaster = wire->dmaster;
+
+       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);
 
 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);
 
 int main(int argc, char *argv[])
 {
@@ -515,6 +615,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)();
+       COMPAT_TEST_FUNC(ctdb_req_dmaster)();
 
        return 0;
 }
index 7ccc90fbc64f3e26891ddd5ffc3abca6d8f2b25d..539d3dd577770fbf7943b48878957b99d7ef2762 100644 (file)
@@ -284,45 +284,8 @@ 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);
 PROTOCOL_CTDB4_TEST(struct ctdb_reply_error, ctdb_reply_error,
                        CTDB_REPLY_ERROR);
-
-static void test_ctdb_req_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_req_dmaster c, c2;
-
-       printf("ctdb_req_dmaster\n");
-       fflush(stdout);
-
-       mem_ctx = talloc_new(NULL);
-       assert(mem_ctx != NULL);
-
-       ctdb_req_header_fill(&h, GENERATION, CTDB_REQ_DMASTER,
-                            DESTNODE, SRCNODE, REQID);
-
-       fill_ctdb_req_dmaster(mem_ctx, &c);
-       datalen = ctdb_req_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_req_dmaster_push(&h, &c, pkt, &len);
-       assert(ret == EMSGSIZE);
-       assert(len == datalen);
-       ret = ctdb_req_dmaster_push(&h, &c, pkt, &pkt_len);
-       assert(ret == 0);
-       ret = ctdb_req_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_req_dmaster(&c, &c2);
-
-       talloc_free(mem_ctx);
-}
+PROTOCOL_CTDB4_TEST(struct ctdb_req_dmaster, ctdb_req_dmaster,
+                       CTDB_REQ_DMASTER);
 
 static void test_ctdb_reply_dmaster(void)
 {
@@ -570,7 +533,7 @@ int main(int argc, char *argv[])
        TEST_FUNC(ctdb_req_call)();
        TEST_FUNC(ctdb_reply_call)();
        TEST_FUNC(ctdb_reply_error)();
-       test_ctdb_req_dmaster();
+       TEST_FUNC(ctdb_req_dmaster)();
        test_ctdb_reply_dmaster();
 
        test_ctdb_req_control_data();