ctdb-protocol: Fix marshalling for ctdb_script_list
authorAmitay Isaacs <amitay@gmail.com>
Wed, 12 Jul 2017 08:18:29 +0000 (18:18 +1000)
committerMartin Schwenke <martins@samba.org>
Wed, 30 Aug 2017 12:59:24 +0000 (14:59 +0200)
Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
ctdb/protocol/protocol_event.c
ctdb/protocol/protocol_private.h
ctdb/protocol/protocol_types.c
ctdb/tests/src/protocol_common.c
ctdb/tests/src/protocol_types_compat_test.c
ctdb/tests/src/protocol_types_test.c

index 26e514aefed519c40ed3e368e40d06f2bf301128..d9eb83dd0a6f31f917a572aa79f5dbf19b9d30d8 100644 (file)
@@ -549,7 +549,7 @@ static void ctdb_event_reply_status_push(struct ctdb_event_reply_status *in,
        ctdb_int32_push(&in->status, buf, &np);
        offset += np;
 
-       ctdb_script_list_push(in->script_list, buf+offset);
+       ctdb_script_list_push(in->script_list, buf+offset, &np);
 }
 
 static int ctdb_event_reply_status_pull(uint8_t *buf, size_t buflen,
@@ -573,7 +573,7 @@ static int ctdb_event_reply_status_pull(uint8_t *buf, size_t buflen,
        offset += np;
 
        ret = ctdb_script_list_pull(buf+offset, buflen-offset,
-                                   rdata, &rdata->script_list);
+                                   rdata, &rdata->script_list, &np);
        if (ret != 0) {
                talloc_free(rdata);
                return ret;
@@ -593,7 +593,9 @@ static void ctdb_event_reply_script_list_push(
                                struct ctdb_event_reply_script_list *in,
                                uint8_t *buf)
 {
-       ctdb_script_list_push(in->script_list, buf);
+       size_t np;
+
+       ctdb_script_list_push(in->script_list, buf, &np);
 }
 
 static int ctdb_event_reply_script_list_pull(
@@ -602,6 +604,7 @@ static int ctdb_event_reply_script_list_pull(
                                struct ctdb_event_reply_script_list **out)
 {
        struct ctdb_event_reply_script_list *rdata;
+       size_t np;
        int ret;
 
        rdata = talloc(mem_ctx, struct ctdb_event_reply_script_list);
@@ -609,7 +612,8 @@ static int ctdb_event_reply_script_list_pull(
                return ENOMEM;
        }
 
-       ret = ctdb_script_list_pull(buf, buflen, rdata, &rdata->script_list);
+       ret = ctdb_script_list_pull(buf, buflen, rdata, &rdata->script_list,
+                                   &np);
        if (ret != 0) {
                talloc_free(rdata);
                return ret;
index 295ae71e2290fa0737c5904eeb170345945177ac..a6f4f3a1ac581267a48de3b5bc10d91903f50611 100644 (file)
@@ -259,10 +259,11 @@ void ctdb_script_push(struct ctdb_script *in, uint8_t *buf, size_t *npush);
 int ctdb_script_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
                     struct ctdb_script **out, size_t *npull);
 
-size_t ctdb_script_list_len(struct ctdb_script_list *script_list);
-void ctdb_script_list_push(struct ctdb_script_list *script_list, uint8_t *buf);
+size_t ctdb_script_list_len(struct ctdb_script_list *in);
+void ctdb_script_list_push(struct ctdb_script_list *in, uint8_t *buf,
+                          size_t *npush);
 int ctdb_script_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
-                         struct ctdb_script_list **out);
+                         struct ctdb_script_list **out, size_t *npull);
 
 size_t ctdb_ban_state_len(struct ctdb_ban_state *ban_state);
 void ctdb_ban_state_push(struct ctdb_ban_state *ban_state, uint8_t *buf);
index b1a729e186b862780002e75358afdf26b51064a1..b0409e42070375c501201043470f73837db67548 100644 (file)
@@ -3797,105 +3797,107 @@ int ctdb_script_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-struct ctdb_script_list_wire {
-       uint32_t num_scripts;
-       struct ctdb_script script[1];
-};
-
-size_t ctdb_script_list_len(struct ctdb_script_list *script_list)
+size_t ctdb_script_list_len(struct ctdb_script_list *in)
 {
-       int i;
        size_t len;
 
-       if (script_list == NULL) {
+       if (in == NULL) {
                return 0;
        }
 
-       len = offsetof(struct ctdb_script_list_wire, script);
-       for (i=0; i<script_list->num_scripts; i++) {
-               len += ctdb_script_len(&script_list->script[i]);
+       len = ctdb_uint32_len(&in->num_scripts) + ctdb_padding_len(4);
+       if (in->num_scripts > 0) {
+               len += in->num_scripts * ctdb_script_len(&in->script[0]);
        }
+
        return len;
 }
 
-void ctdb_script_list_push(struct ctdb_script_list *script_list, uint8_t *buf)
+void ctdb_script_list_push(struct ctdb_script_list *in, uint8_t *buf,
+                          size_t *npush)
 {
-       struct ctdb_script_list_wire *wire =
-               (struct ctdb_script_list_wire *)buf;
-       size_t offset, np;
-       int i;
+       size_t offset = 0, np;
+       uint32_t i;
 
-       if (script_list == NULL) {
+       if (in == NULL) {
+               *npush = 0;
                return;
        }
 
-       wire->num_scripts = script_list->num_scripts;
+       ctdb_uint32_push(&in->num_scripts, buf+offset, &np);
+       offset += np;
 
-       offset = offsetof(struct ctdb_script_list_wire, script);
-       for (i=0; i<script_list->num_scripts; i++) {
-               ctdb_script_push(&script_list->script[i], &buf[offset], &np);
+       ctdb_padding_push(4, buf+offset, &np);
+       offset += np;
+
+       for (i=0; i<in->num_scripts; i++) {
+               ctdb_script_push(&in->script[i], buf+offset, &np);
                offset += np;
        }
+
+       *npush = offset;
 }
 
 int ctdb_script_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
-                         struct ctdb_script_list **out)
+                         struct ctdb_script_list **out, size_t *npull)
 {
-       struct ctdb_script_list *script_list;
-       struct ctdb_script_list_wire *wire =
-               (struct ctdb_script_list_wire *)buf;
-       size_t offset, np;
-       int i;
-       bool ret;
+       struct ctdb_script_list *val;
+       size_t offset = 0, np;
+       uint32_t i;
+       int ret;
 
        /* If event scripts have never been run, the result will be NULL */
        if (buflen == 0) {
-               *out = NULL;
-               return 0;
+               val = NULL;
+               goto done;
        }
 
-       offset = offsetof(struct ctdb_script_list_wire, script);
-
-       if (buflen < offset) {
-               return EMSGSIZE;
-       }
-       if (wire->num_scripts > buflen / sizeof(struct ctdb_script)) {
-               return EMSGSIZE;
-       }
-       if (offset + wire->num_scripts * sizeof(struct ctdb_script) < offset) {
-               return EMSGSIZE;
+       val = talloc(mem_ctx, struct ctdb_script_list);
+       if (val == NULL) {
+               return ENOMEM;
        }
-       if (buflen < offset + wire->num_scripts * sizeof(struct ctdb_script)) {
-               return EMSGSIZE;
+
+       ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num_scripts,
+                              &np);
+       if (ret != 0) {
+               goto fail;
        }
+       offset += np;
 
-       script_list = talloc(mem_ctx, struct ctdb_script_list);
-       if (script_list == NULL) {
-               return ENOMEM;
+       ret = ctdb_padding_pull(buf+offset, buflen-offset, 4, &np);
+       if (ret != 0) {
+               goto fail;
+       }
+       offset += np;
 
+       if (val->num_scripts == 0) {
+               goto done;
+               val->script = NULL;
        }
 
-       script_list->num_scripts = wire->num_scripts;
-       script_list->script = talloc_array(script_list, struct ctdb_script,
-                                          wire->num_scripts);
-       if (script_list->script == NULL) {
-               talloc_free(script_list);
-               return ENOMEM;
+       val->script = talloc_array(val, struct ctdb_script, val->num_scripts);
+       if (val->script == NULL) {
+               ret = ENOMEM;
+               goto fail;
        }
 
-       for (i=0; i<wire->num_scripts; i++) {
-               ret = ctdb_script_pull_elems(&buf[offset], buflen-offset,
-                                            script_list->script,
-                                            &script_list->script[i], &np);
+       for (i=0; i<val->num_scripts; i++) {
+               ret = ctdb_script_pull_elems(buf+offset, buflen-offset,
+                                            val, &val->script[i], &np);
                if (ret != 0) {
-                       talloc_free(script_list);
-                       return ret;
+                       goto fail;
                }
                offset += np;
        }
 
-       *out = script_list;
+done:
+       *out = val;
+       *npull = offset;
        return 0;
+
+fail:
+       talloc_free(val);
+       return ret;
 }
 
 size_t ctdb_ban_state_len(struct ctdb_ban_state *ban_state)
index 4956b4e585bb851d92857e6ee81b8011138eeffd..d4f2f03d6496271dad4706ac1778ff07c1605eb5 100644 (file)
@@ -1075,8 +1075,8 @@ void fill_ctdb_script_list(TALLOC_CTX *mem_ctx, struct ctdb_script_list *p)
 
        p->num_scripts = rand_int(32);
        if (p->num_scripts > 0) {
-               p->script = talloc_array(mem_ctx, struct ctdb_script,
-                                        p->num_scripts);
+               p->script = talloc_zero_array(mem_ctx, struct ctdb_script,
+                                             p->num_scripts);
                assert(p->script != NULL);
                for (i=0; i<p->num_scripts; i++) {
                        fill_ctdb_script(mem_ctx, &p->script[i]);
index 1e8de018ce70d538f45074b867c642faba6aebb9..9b3fc9e1512cf5a42e3a17fae91e6e6553700271 100644 (file)
@@ -1475,6 +1475,108 @@ static int ctdb_script_pull_old(uint8_t *buf, size_t buflen,
        return ret;
 }
 
+struct ctdb_script_list_wire {
+       uint32_t num_scripts;
+       struct ctdb_script script[1];
+};
+
+static size_t ctdb_script_list_len_old(struct ctdb_script_list *in)
+{
+       int i;
+       size_t len;
+
+       if (in == NULL) {
+               return 0;
+       }
+
+       len = offsetof(struct ctdb_script_list_wire, script);
+       for (i=0; i<in->num_scripts; i++) {
+               len += ctdb_script_len_old(&in->script[i]);
+       }
+       return len;
+}
+
+static void ctdb_script_list_push_old(struct ctdb_script_list *in,
+                                     uint8_t *buf)
+{
+       struct ctdb_script_list_wire *wire =
+               (struct ctdb_script_list_wire *)buf;
+       size_t offset;
+       int i;
+
+       if (in == NULL) {
+               return;
+       }
+
+       wire->num_scripts = in->num_scripts;
+
+       offset = offsetof(struct ctdb_script_list_wire, script);
+       for (i=0; i<in->num_scripts; i++) {
+               ctdb_script_push_old(&in->script[i], &buf[offset]);
+               offset += ctdb_script_len_old(&in->script[i]);
+       }
+}
+
+static int ctdb_script_list_pull_old(uint8_t *buf, size_t buflen,
+                                    TALLOC_CTX *mem_ctx,
+                                    struct ctdb_script_list **out)
+{
+       struct ctdb_script_list *val;
+       struct ctdb_script_list_wire *wire =
+               (struct ctdb_script_list_wire *)buf;
+       size_t offset;
+       int i;
+       bool ret;
+
+       /* If event scripts have never been run, the result will be NULL */
+       if (buflen == 0) {
+               *out = NULL;
+               return 0;
+       }
+
+       offset = offsetof(struct ctdb_script_list_wire, script);
+
+       if (buflen < offset) {
+               return EMSGSIZE;
+       }
+       if (wire->num_scripts > buflen / sizeof(struct ctdb_script)) {
+               return EMSGSIZE;
+       }
+       if (offset + wire->num_scripts * sizeof(struct ctdb_script) < offset) {
+               return EMSGSIZE;
+       }
+       if (buflen < offset + wire->num_scripts * sizeof(struct ctdb_script)) {
+               return EMSGSIZE;
+       }
+
+       val = talloc(mem_ctx, struct ctdb_script_list);
+       if (val == NULL) {
+               return ENOMEM;
+
+       }
+
+       val->num_scripts = wire->num_scripts;
+       val->script = talloc_array(val, struct ctdb_script, wire->num_scripts);
+       if (val->script == NULL) {
+               talloc_free(val);
+               return ENOMEM;
+       }
+
+       for (i=0; i<wire->num_scripts; i++) {
+               ret = ctdb_script_pull_elems_old(&buf[offset], buflen-offset,
+                                                val->script,
+                                                &val->script[i]);
+               if (ret != 0) {
+                       talloc_free(val);
+                       return ret;
+               }
+               offset += ctdb_script_len_old(&val->script[i]);
+       }
+
+       *out = val;
+       return 0;
+}
+
 
 COMPAT_TYPE3_TEST(struct ctdb_statistics, ctdb_statistics);
 COMPAT_TYPE3_TEST(struct ctdb_vnn_map, ctdb_vnn_map);
@@ -1505,6 +1607,7 @@ COMPAT_TYPE3_TEST(struct ctdb_public_ip_list, ctdb_public_ip_list);
 COMPAT_TYPE3_TEST(struct ctdb_node_and_flags, ctdb_node_and_flags);
 COMPAT_TYPE3_TEST(struct ctdb_node_map, ctdb_node_map);
 COMPAT_TYPE3_TEST(struct ctdb_script, ctdb_script);
+COMPAT_TYPE3_TEST(struct ctdb_script_list, ctdb_script_list);
 
 int main(int argc, char *argv[])
 {
@@ -1540,6 +1643,7 @@ int main(int argc, char *argv[])
        COMPAT_TEST_FUNC(ctdb_node_and_flags)();
        COMPAT_TEST_FUNC(ctdb_node_map)();
        COMPAT_TEST_FUNC(ctdb_script)();
+       COMPAT_TEST_FUNC(ctdb_script_list)();
 
        return 0;
 }
index 435d89281f9944b0820d758ed13b06c533abae7c..19f167e41a90196c1f7a7716003f7adc2e013bb8 100644 (file)
@@ -75,7 +75,7 @@ PROTOCOL_TYPE3_TEST(struct ctdb_public_ip_list, ctdb_public_ip_list);
 PROTOCOL_TYPE3_TEST(struct ctdb_node_and_flags, ctdb_node_and_flags);
 PROTOCOL_TYPE3_TEST(struct ctdb_node_map, ctdb_node_map);
 PROTOCOL_TYPE3_TEST(struct ctdb_script, ctdb_script);
-DEFINE_TEST(struct ctdb_script_list, ctdb_script_list);
+PROTOCOL_TYPE3_TEST(struct ctdb_script_list, ctdb_script_list);
 DEFINE_TEST(struct ctdb_ban_state, ctdb_ban_state);
 DEFINE_TEST(struct ctdb_notify_data, ctdb_notify_data);
 DEFINE_TEST(struct ctdb_iface, ctdb_iface);