diff --git a/ctdb/protocol/protocol_control.c b/ctdb/protocol/protocol_control.c index eaaf471b2f8..621290ce1a1 100644 --- a/ctdb/protocol/protocol_control.c +++ b/ctdb/protocol/protocol_control.c @@ -539,7 +539,7 @@ static void ctdb_req_control_data_push(struct ctdb_req_control_data *cd, break; case CTDB_CONTROL_SET_TCP_TICKLE_LIST: - ctdb_tickle_list_push(cd->data.tickles, buf); + ctdb_tickle_list_push(cd->data.tickles, buf, &np); break; case CTDB_CONTROL_DB_ATTACH_PERSISTENT: @@ -838,7 +838,7 @@ static int ctdb_req_control_data_pull(uint8_t *buf, size_t buflen, case CTDB_CONTROL_SET_TCP_TICKLE_LIST: ret = ctdb_tickle_list_pull(buf, buflen, mem_ctx, - &cd->data.tickles); + &cd->data.tickles, &np); break; case CTDB_CONTROL_DB_ATTACH_PERSISTENT: @@ -1480,7 +1480,7 @@ static void ctdb_reply_control_data_push(struct ctdb_reply_control_data *cd, break; case CTDB_CONTROL_GET_TCP_TICKLE_LIST: - ctdb_tickle_list_push(cd->data.tickles, buf); + ctdb_tickle_list_push(cd->data.tickles, buf, &np); break; case CTDB_CONTROL_DB_ATTACH_PERSISTENT: @@ -1654,7 +1654,7 @@ static int ctdb_reply_control_data_pull(uint8_t *buf, size_t buflen, case CTDB_CONTROL_GET_TCP_TICKLE_LIST: ret = ctdb_tickle_list_pull(buf, buflen, mem_ctx, - &cd->data.tickles); + &cd->data.tickles, &np); break; case CTDB_CONTROL_DB_ATTACH_PERSISTENT: diff --git a/ctdb/protocol/protocol_private.h b/ctdb/protocol/protocol_private.h index 84f26501461..037819ac9e3 100644 --- a/ctdb/protocol/protocol_private.h +++ b/ctdb/protocol/protocol_private.h @@ -209,10 +209,11 @@ void ctdb_tunable_list_push(struct ctdb_tunable_list *in, uint8_t *buf, int ctdb_tunable_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx, struct ctdb_tunable_list **out, size_t *npull); -size_t ctdb_tickle_list_len(struct ctdb_tickle_list *tickles); -void ctdb_tickle_list_push(struct ctdb_tickle_list *tickles, uint8_t *buf); +size_t ctdb_tickle_list_len(struct ctdb_tickle_list *in); +void ctdb_tickle_list_push(struct ctdb_tickle_list *in, uint8_t *buf, + size_t *npush); int ctdb_tickle_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx, - struct ctdb_tickle_list **out); + struct ctdb_tickle_list **out, size_t *npull); size_t ctdb_addr_info_len(struct ctdb_addr_info *addr_info); void ctdb_addr_info_push(struct ctdb_addr_info *addr_info, uint8_t *buf); diff --git a/ctdb/protocol/protocol_types.c b/ctdb/protocol/protocol_types.c index 285de5fb6fb..ec9d7d5eb81 100644 --- a/ctdb/protocol/protocol_types.c +++ b/ctdb/protocol/protocol_types.c @@ -3105,88 +3105,93 @@ int ctdb_tunable_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx, return 0; } -struct ctdb_tickle_list_wire { - ctdb_sock_addr addr; - uint32_t num; - struct ctdb_connection conn[1]; -}; - -size_t ctdb_tickle_list_len(struct ctdb_tickle_list *tickles) +size_t ctdb_tickle_list_len(struct ctdb_tickle_list *in) { - return offsetof(struct ctdb_tickle_list, conn) + - tickles->num * sizeof(struct ctdb_connection); + size_t len; + + len = ctdb_sock_addr_len(&in->addr) + + ctdb_uint32_len(&in->num); + if (in->num > 0) { + len += in->num * ctdb_connection_len(&in->conn[0]); + } + + return len; } -void ctdb_tickle_list_push(struct ctdb_tickle_list *tickles, uint8_t *buf) +void ctdb_tickle_list_push(struct ctdb_tickle_list *in, uint8_t *buf, + size_t *npush) { - struct ctdb_tickle_list_wire *wire = - (struct ctdb_tickle_list_wire *)buf; - size_t offset, np; - int i; + size_t offset = 0, np; + uint32_t i; - memcpy(&wire->addr, &tickles->addr, sizeof(ctdb_sock_addr)); - wire->num = tickles->num; + ctdb_sock_addr_push(&in->addr, buf+offset, &np); + offset += np; - offset = offsetof(struct ctdb_tickle_list_wire, conn); - for (i=0; inum; i++) { - ctdb_connection_push(&tickles->conn[i], &buf[offset], &np); + ctdb_uint32_push(&in->num, buf+offset, &np); + offset += np; + + for (i=0; inum; i++) { + ctdb_connection_push(&in->conn[i], buf+offset, &np); offset += np; } + + *npush = offset; } int ctdb_tickle_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx, - struct ctdb_tickle_list **out) + struct ctdb_tickle_list **out, size_t *npull) { - struct ctdb_tickle_list *tickles; - struct ctdb_tickle_list_wire *wire = - (struct ctdb_tickle_list_wire *)buf; - size_t offset, np; - int i, ret; + struct ctdb_tickle_list *val; + size_t offset = 0, np; + uint32_t i; + int ret; - if (buflen < offsetof(struct ctdb_tickle_list_wire, conn)) { - return EMSGSIZE; - } - if (wire->num > buflen / sizeof(struct ctdb_connection)) { - return EMSGSIZE; - } - if (offsetof(struct ctdb_tickle_list_wire, conn) + - wire->num * sizeof(struct ctdb_connection) < - offsetof(struct ctdb_tickle_list_wire, conn)) { - return EMSGSIZE; - } - if (buflen < offsetof(struct ctdb_tickle_list_wire, conn) + - wire->num * sizeof(struct ctdb_connection)) { - return EMSGSIZE; - } - - tickles = talloc(mem_ctx, struct ctdb_tickle_list); - if (tickles == NULL) { + val = talloc(mem_ctx, struct ctdb_tickle_list); + if (val == NULL) { return ENOMEM; } - offset = offsetof(struct ctdb_tickle_list, conn); - memcpy(tickles, wire, offset); + ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset, val, + &val->addr, &np); + if (ret != 0) { + goto fail; + } + offset += np; - tickles->conn = talloc_array(tickles, struct ctdb_connection, - wire->num); - if (tickles->conn == NULL) { - talloc_free(tickles); - return ENOMEM; + ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->num, &np); + if (ret != 0) { + goto fail; + } + offset += np; + + if (val->num == 0) { + val->conn = NULL; + goto done; } - for (i=0; inum; i++) { - ret = ctdb_connection_pull_elems(&buf[offset], buflen-offset, - tickles->conn, - &tickles->conn[i], &np); + val->conn = talloc_array(val, struct ctdb_connection, val->num); + if (val->conn == NULL) { + ret = ENOMEM; + goto fail; + } + + for (i=0; inum; i++) { + ret = ctdb_connection_pull_elems(buf+offset, buflen-offset, + val, &val->conn[i], &np); if (ret != 0) { - talloc_free(tickles); - return ret; + goto fail; } offset += np; } - *out = tickles; +done: + *out = val; + *npull = offset; return 0; + +fail: + talloc_free(val); + return ret; } struct ctdb_addr_info_wire { diff --git a/ctdb/tests/src/protocol_types_compat_test.c b/ctdb/tests/src/protocol_types_compat_test.c index 215757a77ff..cb651e37fb3 100644 --- a/ctdb/tests/src/protocol_types_compat_test.c +++ b/ctdb/tests/src/protocol_types_compat_test.c @@ -947,6 +947,92 @@ static int ctdb_tunable_list_pull_old(uint8_t *buf, size_t buflen, return 0; } +struct ctdb_tickle_list_wire { + ctdb_sock_addr addr; + uint32_t num; + struct ctdb_connection conn[1]; +}; + +static size_t ctdb_tickle_list_len_old(struct ctdb_tickle_list *in) +{ + return offsetof(struct ctdb_tickle_list, conn) + + in->num * sizeof(struct ctdb_connection); +} + +static void ctdb_tickle_list_push_old(struct ctdb_tickle_list *in, + uint8_t *buf) +{ + struct ctdb_tickle_list_wire *wire = + (struct ctdb_tickle_list_wire *)buf; + size_t offset; + int i; + + memcpy(&wire->addr, &in->addr, sizeof(ctdb_sock_addr)); + wire->num = in->num; + + offset = offsetof(struct ctdb_tickle_list_wire, conn); + for (i=0; inum; i++) { + ctdb_connection_push_old(&in->conn[i], &buf[offset]); + offset += ctdb_connection_len_old(&in->conn[i]); + } +} + +static int ctdb_tickle_list_pull_old(uint8_t *buf, size_t buflen, + TALLOC_CTX *mem_ctx, + struct ctdb_tickle_list **out) +{ + struct ctdb_tickle_list *val; + struct ctdb_tickle_list_wire *wire = + (struct ctdb_tickle_list_wire *)buf; + size_t offset; + int i, ret; + + if (buflen < offsetof(struct ctdb_tickle_list_wire, conn)) { + return EMSGSIZE; + } + if (wire->num > buflen / sizeof(struct ctdb_connection)) { + return EMSGSIZE; + } + if (offsetof(struct ctdb_tickle_list_wire, conn) + + wire->num * sizeof(struct ctdb_connection) < + offsetof(struct ctdb_tickle_list_wire, conn)) { + return EMSGSIZE; + } + if (buflen < offsetof(struct ctdb_tickle_list_wire, conn) + + wire->num * sizeof(struct ctdb_connection)) { + return EMSGSIZE; + } + + val = talloc(mem_ctx, struct ctdb_tickle_list); + if (val == NULL) { + return ENOMEM; + } + + offset = offsetof(struct ctdb_tickle_list, conn); + memcpy(val, wire, offset); + + val->conn = talloc_array(val, struct ctdb_connection, wire->num); + if (val->conn == NULL) { + talloc_free(val); + return ENOMEM; + } + + for (i=0; inum; i++) { + ret = ctdb_connection_pull_elems_old(&buf[offset], + buflen-offset, + val->conn, + &val->conn[i]); + if (ret != 0) { + talloc_free(val); + return ret; + } + offset += ctdb_connection_len_old(&val->conn[i]); + } + + *out = val; + return 0; +} + COMPAT_TYPE3_TEST(struct ctdb_statistics, ctdb_statistics); COMPAT_TYPE3_TEST(struct ctdb_vnn_map, ctdb_vnn_map); @@ -968,6 +1054,7 @@ COMPAT_TYPE3_TEST(struct ctdb_tunable, ctdb_tunable); COMPAT_TYPE3_TEST(struct ctdb_node_flag_change, ctdb_node_flag_change); COMPAT_TYPE3_TEST(struct ctdb_var_list, ctdb_var_list); COMPAT_TYPE3_TEST(struct ctdb_tunable_list, ctdb_tunable_list); +COMPAT_TYPE3_TEST(struct ctdb_tickle_list, ctdb_tickle_list); int main(int argc, char *argv[]) { @@ -994,6 +1081,7 @@ int main(int argc, char *argv[]) COMPAT_TEST_FUNC(ctdb_node_flag_change)(); COMPAT_TEST_FUNC(ctdb_var_list)(); COMPAT_TEST_FUNC(ctdb_tunable_list)(); + COMPAT_TEST_FUNC(ctdb_tickle_list)(); return 0; } diff --git a/ctdb/tests/src/protocol_types_test.c b/ctdb/tests/src/protocol_types_test.c index 695a591e57e..e0468408a61 100644 --- a/ctdb/tests/src/protocol_types_test.c +++ b/ctdb/tests/src/protocol_types_test.c @@ -66,7 +66,7 @@ PROTOCOL_TYPE3_TEST(struct ctdb_tunable, ctdb_tunable); PROTOCOL_TYPE3_TEST(struct ctdb_node_flag_change, ctdb_node_flag_change); PROTOCOL_TYPE3_TEST(struct ctdb_var_list, ctdb_var_list); PROTOCOL_TYPE3_TEST(struct ctdb_tunable_list, ctdb_tunable_list); -DEFINE_TEST(struct ctdb_tickle_list, ctdb_tickle_list); +PROTOCOL_TYPE3_TEST(struct ctdb_tickle_list, ctdb_tickle_list); DEFINE_TEST(struct ctdb_addr_info, ctdb_addr_info); DEFINE_TEST(struct ctdb_transdb, ctdb_transdb); DEFINE_TEST(struct ctdb_uptime, ctdb_uptime);