diff options
Diffstat (limited to '')
-rw-r--r-- | ctdb/event/event_protocol.c | 1123 |
1 files changed, 1123 insertions, 0 deletions
diff --git a/ctdb/event/event_protocol.c b/ctdb/event/event_protocol.c new file mode 100644 index 0000000..baa9e1e --- /dev/null +++ b/ctdb/event/event_protocol.c @@ -0,0 +1,1123 @@ +/* + CTDB event daemon protocol + + Copyright (C) Amitay Isaacs 2018 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" + +#include <talloc.h> + +#include "protocol/protocol_basic.h" + +#include "event_protocol.h" +#include "event_protocol_api.h" + +static size_t ctdb_event_script_action_len(enum ctdb_event_script_action in) +{ + uint32_t u32 = in; + + return ctdb_uint32_len(&u32); +} + +static void ctdb_event_script_action_push(enum ctdb_event_script_action in, + uint8_t *buf, + size_t *npush) +{ + uint32_t u32 = in; + + ctdb_uint32_push(&u32, buf, npush); +} + +static int ctdb_event_script_action_pull(uint8_t *buf, + size_t buflen, + enum ctdb_event_script_action *out, + size_t *npull) +{ + enum ctdb_event_script_action value; + uint32_t u32; + size_t np; + int ret; + + ret = ctdb_uint32_pull(buf, buflen, &u32, &np); + if (ret != 0) { + return ret; + } + + switch (u32) { + case 0: + value = CTDB_EVENT_SCRIPT_DISABLE; + break; + + case 1: + value = CTDB_EVENT_SCRIPT_ENABLE; + break; + + default: + return EINVAL; + } + + *out = value; + *npull = np; + + return 0; +} + +static size_t ctdb_event_command_len(enum ctdb_event_command in) +{ + uint32_t u32 = in; + + return ctdb_uint32_len(&u32); +} + +static void ctdb_event_command_push(enum ctdb_event_command in, + uint8_t *buf, + size_t *npush) +{ + uint32_t u32 = in; + + ctdb_uint32_push(&u32, buf, npush); +} + +static int ctdb_event_command_pull(uint8_t *buf, + size_t buflen, + enum ctdb_event_command *out, + size_t *npull) +{ + enum ctdb_event_command value; + uint32_t u32; + size_t np; + int ret; + + ret = ctdb_uint32_pull(buf, buflen, &u32, &np); + if (ret != 0) { + return ret; + } + + switch (u32) { + case 1: + value = CTDB_EVENT_CMD_RUN; + break; + + case 2: + value = CTDB_EVENT_CMD_STATUS; + break; + + case 3: + value = CTDB_EVENT_CMD_SCRIPT; + break; + + default: + return EINVAL; + } + + *out = value; + *npull = np; + + return 0; +} + +static size_t ctdb_event_script_len(struct ctdb_event_script *in) +{ + return ctdb_stringn_len(&in->name) + + ctdb_timeval_len(&in->begin) + + ctdb_timeval_len(&in->end) + + ctdb_int32_len(&in->result) + + ctdb_stringn_len(&in->output); +} + +static void ctdb_event_script_push(struct ctdb_event_script *in, + uint8_t *buf, + size_t *npush) +{ + size_t offset = 0, np; + + ctdb_stringn_push(&in->name, buf+offset, &np); + offset += np; + + ctdb_timeval_push(&in->begin, buf+offset, &np); + offset += np; + + ctdb_timeval_push(&in->end, buf+offset, &np); + offset += np; + + ctdb_int32_push(&in->result, buf+offset, &np); + offset += np; + + ctdb_stringn_push(&in->output, buf+offset, &np); + offset += np; + + *npush = offset; +} + +static int ctdb_event_script_pull_elems(uint8_t *buf, + size_t buflen, + TALLOC_CTX *mem_ctx, + struct ctdb_event_script *value, + size_t *npull) +{ + size_t offset = 0, np; + int ret; + + ret = ctdb_stringn_pull(buf+offset, + buflen-offset, + mem_ctx, + &value->name, + &np); + if (ret != 0) { + return ret; + } + offset += np; + + ret = ctdb_timeval_pull(buf+offset, + buflen-offset, + &value->begin, + &np); + if (ret != 0) { + return ret; + } + offset += np; + + ret = ctdb_timeval_pull(buf+offset, + buflen-offset, + &value->end, + &np); + if (ret != 0) { + return ret; + } + offset += np; + + ret = ctdb_int32_pull(buf+offset, + buflen-offset, + &value->result, + &np); + if (ret != 0) { + return ret; + } + offset += np; + + ret = ctdb_stringn_pull(buf+offset, + buflen-offset, + mem_ctx, + &value->output, + &np); + if (ret != 0) { + return ret; + } + offset += np; + + *npull = offset; + + return 0; +} + +#ifdef EVENT_PROTOCOL_TEST +static int ctdb_event_script_pull(uint8_t *buf, + size_t buflen, + TALLOC_CTX *mem_ctx, + struct ctdb_event_script **out, + size_t *npull) +{ + struct ctdb_event_script *value; + int ret; + + value = talloc(mem_ctx, struct ctdb_event_script); + if (value == NULL) { + return ENOMEM; + } + + ret = ctdb_event_script_pull_elems(buf, buflen, value, value, npull); + if (ret != 0) { + talloc_free(value); + return ret; + } + + *out = value; + + return 0; +} +#endif + +static size_t ctdb_event_script_list_len(struct ctdb_event_script_list *in) +{ + size_t len; + int i; + + len = ctdb_int32_len(&in->num_scripts); + + for (i=0; i<in->num_scripts; i++) { + len += ctdb_event_script_len(&in->script[i]); + } + + return len; +} + +static void ctdb_event_script_list_push(struct ctdb_event_script_list *in, + uint8_t *buf, + size_t *npush) +{ + size_t offset = 0, np; + int i; + + ctdb_int32_push(&in->num_scripts, buf+offset, &np); + offset += np; + + for (i=0; i<in->num_scripts; i++) { + ctdb_event_script_push(&in->script[i], buf+offset, &np); + offset += np; + } + + *npush = offset; +} + +static int ctdb_event_script_list_pull(uint8_t *buf, + size_t buflen, + TALLOC_CTX *mem_ctx, + struct ctdb_event_script_list **out, + size_t *npull) +{ + struct ctdb_event_script_list *value = NULL; + size_t offset = 0, np; + int num_scripts; + int ret, i; + + ret = ctdb_int32_pull(buf+offset, buflen-offset, &num_scripts, &np); + if (ret != 0) { + return ret; + } + offset += np; + + if (num_scripts < 0) { + return EINVAL; + } + + value = talloc_zero(mem_ctx, struct ctdb_event_script_list); + if (value == NULL) { + return ENOMEM; + } + + value->num_scripts = num_scripts; + if (num_scripts == 0) { + goto done; + } + + value->script = talloc_array(value, struct ctdb_event_script, + num_scripts); + if (value->script == NULL) { + ret = ENOMEM; + goto fail; + } + + for (i=0; i<num_scripts; i++) { + ret = ctdb_event_script_pull_elems(buf+offset, + buflen-offset, + value, + &value->script[i], + &np); + if (ret != 0) { + goto fail; + } + offset += np; + } + +done: + *out = value; + *npull = offset; + + return 0; + +fail: + talloc_free(value); + return ret; +} + +static size_t ctdb_event_request_run_len(struct ctdb_event_request_run *in) +{ + return ctdb_stringn_len(&in->component) + + ctdb_stringn_len(&in->event) + + ctdb_stringn_len(&in->args) + + ctdb_uint32_len(&in->timeout) + + ctdb_uint32_len(&in->flags); +} + +static void ctdb_event_request_run_push(struct ctdb_event_request_run *in, + uint8_t *buf, + size_t *npush) +{ + size_t offset = 0, np; + + ctdb_stringn_push(&in->component, buf+offset, &np); + offset += np; + + ctdb_stringn_push(&in->event, buf+offset, &np); + offset += np; + + ctdb_stringn_push(&in->args, buf+offset, &np); + offset += np; + + ctdb_uint32_push(&in->timeout, buf+offset, &np); + offset += np; + + ctdb_uint32_push(&in->flags, buf+offset, &np); + offset += np; + + *npush = offset; +} + +static int ctdb_event_request_run_pull(uint8_t *buf, + size_t buflen, + TALLOC_CTX *mem_ctx, + struct ctdb_event_request_run **out, + size_t *npull) +{ + struct ctdb_event_request_run *value; + size_t offset = 0, np; + int ret; + + value = talloc(mem_ctx, struct ctdb_event_request_run); + if (value == NULL) { + return ENOMEM; + } + + ret = ctdb_stringn_pull(buf+offset, + buflen-offset, + value, + &value->component, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + ret = ctdb_stringn_pull(buf+offset, + buflen-offset, + value, + &value->event, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + ret = ctdb_stringn_pull(buf+offset, + buflen-offset, + value, + &value->args, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + ret = ctdb_uint32_pull(buf+offset, + buflen-offset, + &value->timeout, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + ret = ctdb_uint32_pull(buf+offset, + buflen-offset, + &value->flags, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + *out = value; + *npull = offset; + + return 0; + +fail: + talloc_free(value); + return ret; +} + +static size_t ctdb_event_request_status_len( + struct ctdb_event_request_status *in) +{ + return ctdb_stringn_len(&in->component) + + ctdb_stringn_len(&in->event); +} + +static void ctdb_event_request_status_push( + struct ctdb_event_request_status *in, + uint8_t *buf, + size_t *npush) +{ + size_t offset = 0, np; + + ctdb_stringn_push(&in->component, buf+offset, &np); + offset += np; + + ctdb_stringn_push(&in->event, buf+offset, &np); + offset += np; + + *npush = offset; +} + +static int ctdb_event_request_status_pull( + uint8_t *buf, + size_t buflen, + TALLOC_CTX *mem_ctx, + struct ctdb_event_request_status **out, + size_t *npull) +{ + struct ctdb_event_request_status *value; + size_t offset = 0, np; + int ret; + + value = talloc(mem_ctx, struct ctdb_event_request_status); + if (value == NULL) { + return ENOMEM; + } + + ret = ctdb_stringn_pull(buf+offset, + buflen-offset, + value, + &value->component, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + ret = ctdb_stringn_pull(buf+offset, + buflen-offset, + value, + &value->event, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + *out = value; + *npull = offset; + + return 0; + +fail: + talloc_free(value); + return ret; +} + +static size_t ctdb_event_request_script_len( + struct ctdb_event_request_script *in) +{ + return ctdb_stringn_len(&in->component) + + ctdb_stringn_len(&in->script) + + ctdb_event_script_action_len(in->action); +} + +static void ctdb_event_request_script_push( + struct ctdb_event_request_script *in, + uint8_t *buf, + size_t *npush) +{ + size_t offset = 0, np; + + ctdb_stringn_push(&in->component, buf+offset, &np); + offset += np; + + ctdb_stringn_push(&in->script, buf+offset, &np); + offset += np; + + ctdb_event_script_action_push(in->action, buf+offset, &np); + offset += np; + + *npush = offset; +} + +static int ctdb_event_request_script_pull( + uint8_t *buf, + size_t buflen, + TALLOC_CTX *mem_ctx, + struct ctdb_event_request_script **out, + size_t *npull) +{ + struct ctdb_event_request_script *value; + size_t offset = 0, np; + int ret; + + value = talloc(mem_ctx, struct ctdb_event_request_script); + if (value == NULL) { + return ENOMEM; + } + + ret = ctdb_stringn_pull(buf+offset, + buflen-offset, + value, + &value->component, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + ret = ctdb_stringn_pull(buf+offset, + buflen-offset, + value, + &value->script, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + ret = ctdb_event_script_action_pull(buf+offset, + buflen-offset, + &value->action, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + *out = value; + *npull = offset; + + return 0; + +fail: + talloc_free(value); + return ret; +} + +static size_t ctdb_event_reply_status_len( + struct ctdb_event_reply_status *in) +{ + return ctdb_int32_len(&in->summary) + + ctdb_event_script_list_len(in->script_list); +} + +static void ctdb_event_reply_status_push( + struct ctdb_event_reply_status *in, + uint8_t *buf, + size_t *npush) +{ + size_t offset = 0, np; + + ctdb_int32_push(&in->summary, buf+offset, &np); + offset += np; + + ctdb_event_script_list_push(in->script_list, buf+offset, &np); + offset += np; + + *npush = offset; +} + +static int ctdb_event_reply_status_pull( + uint8_t *buf, + size_t buflen, + TALLOC_CTX *mem_ctx, + struct ctdb_event_reply_status **out, + size_t *npull) +{ + struct ctdb_event_reply_status *value; + size_t offset = 0, np; + int ret; + + value = talloc(mem_ctx, struct ctdb_event_reply_status); + if (value == NULL) { + return ENOMEM; + } + + ret = ctdb_int32_pull(buf+offset, buflen-offset, &value->summary, &np); + if (ret != 0) { + goto fail; + } + offset += np; + + ret = ctdb_event_script_list_pull(buf+offset, + buflen-offset, + value, + &value->script_list, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + *out = value; + *npull = offset; + + return 0; + +fail: + talloc_free(value); + return ret; +} + +static size_t ctdb_event_header_len(struct ctdb_event_header *in) +{ + return ctdb_uint32_len(&in->length) + + ctdb_uint32_len(&in->version) + + ctdb_uint32_len(&in->reqid); +} + +static void ctdb_event_header_push(struct ctdb_event_header *in, + uint8_t *buf, + size_t *npush) +{ + size_t offset = 0, np; + + ctdb_uint32_push(&in->length, buf+offset, &np); + offset += np; + + ctdb_uint32_push(&in->version, buf+offset, &np); + offset += np; + + ctdb_uint32_push(&in->reqid, buf+offset, &np); + offset += np; + + *npush = offset; +} + +static int ctdb_event_header_pull(uint8_t *buf, + size_t buflen, + struct ctdb_event_header *value, + size_t *npull) +{ + size_t offset = 0, np; + int ret; + + ret = ctdb_uint32_pull(buf+offset, + buflen-offset, + &value->length, + &np); + if (ret != 0) { + return ret; + } + offset += np; + + ret = ctdb_uint32_pull(buf+offset, + buflen-offset, + &value->version, + &np); + if (ret != 0) { + return ret; + } + offset += np; + + ret = ctdb_uint32_pull(buf+offset, + buflen-offset, + &value->reqid, + &np); + if (ret != 0) { + return ret; + } + offset += np; + + *npull = offset; + + return 0; +} + +int ctdb_event_header_extract(uint8_t *buf, + size_t buflen, + struct ctdb_event_header *value) +{ + size_t np; + + return ctdb_event_header_pull(buf, buflen, value, &np); +} + +static size_t ctdb_event_request_data_len(struct ctdb_event_request *in) +{ + size_t len; + + len = ctdb_event_command_len(in->cmd); + + switch (in->cmd) { + case CTDB_EVENT_CMD_RUN: + len += ctdb_event_request_run_len(in->data.run); + break; + + case CTDB_EVENT_CMD_STATUS: + len += ctdb_event_request_status_len(in->data.status); + break; + + case CTDB_EVENT_CMD_SCRIPT: + len += ctdb_event_request_script_len(in->data.script); + break; + + default: + break; + } + + return len; +} + +static void ctdb_event_request_data_push(struct ctdb_event_request *in, + uint8_t *buf, + size_t *npush) +{ + size_t offset = 0, np; + + ctdb_event_command_push(in->cmd, buf+offset, &np); + offset += np; + + switch (in->cmd) { + case CTDB_EVENT_CMD_RUN: + ctdb_event_request_run_push(in->data.run, buf+offset, &np); + break; + + case CTDB_EVENT_CMD_STATUS: + ctdb_event_request_status_push(in->data.status, + buf+offset, + &np); + break; + + case CTDB_EVENT_CMD_SCRIPT: + ctdb_event_request_script_push(in->data.script, + buf+offset, + &np); + break; + default: + np = 0; + break; + } + offset += np; + + *npush = offset; +} + +static int ctdb_event_request_data_pull(uint8_t *buf, + size_t buflen, + TALLOC_CTX *mem_ctx, + struct ctdb_event_request **out, + size_t *npull) +{ + struct ctdb_event_request *value; + size_t offset = 0, np; + int ret; + + value = talloc(mem_ctx, struct ctdb_event_request); + if (value == NULL) { + return ENOMEM; + } + + ret = ctdb_event_command_pull(buf+offset, + buflen-offset, + &value->cmd, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + switch (value->cmd) { + case CTDB_EVENT_CMD_RUN: + ret = ctdb_event_request_run_pull(buf+offset, + buflen-offset, + value, + &value->data.run, + &np); + break; + + case CTDB_EVENT_CMD_STATUS: + ret = ctdb_event_request_status_pull(buf+offset, + buflen-offset, + value, + &value->data.status, + &np); + break; + + case CTDB_EVENT_CMD_SCRIPT: + ret = ctdb_event_request_script_pull(buf+offset, + buflen-offset, + value, + &value->data.script, + &np); + break; + + default: + np = 0; + break; + } + + if (ret != 0) { + goto fail; + } + offset += np; + + *out = value; + *npull = offset; + + return 0; + +fail: + talloc_free(value); + return ret; +} + +static size_t ctdb_event_reply_data_len(struct ctdb_event_reply *in) +{ + size_t len; + + len = ctdb_event_command_len(in->cmd) + + ctdb_int32_len(&in->result); + + if (in->result != 0) { + goto done; + } + + switch (in->cmd) { + case CTDB_EVENT_CMD_STATUS: + len += ctdb_event_reply_status_len(in->data.status); + break; + + default: + break; + } + +done: + return len; +} + +static void ctdb_event_reply_data_push(struct ctdb_event_reply *in, + uint8_t *buf, + size_t *npush) +{ + size_t offset = 0, np; + + ctdb_event_command_push(in->cmd, buf+offset, &np); + offset += np; + + ctdb_int32_push(&in->result, buf+offset, &np); + offset += np; + + if (in->result != 0) { + goto done; + } + + switch (in->cmd) { + case CTDB_EVENT_CMD_STATUS: + ctdb_event_reply_status_push(in->data.status, buf+offset, &np); + break; + + default: + np = 0; + break; + } + offset += np; + +done: + *npush = offset; +} + +static int ctdb_event_reply_data_pull(uint8_t *buf, + size_t buflen, + TALLOC_CTX *mem_ctx, + struct ctdb_event_reply **out, + size_t *npull) +{ + struct ctdb_event_reply *value; + size_t offset = 0, np; + int ret; + + value = talloc(mem_ctx, struct ctdb_event_reply); + if (value == NULL) { + return ENOMEM; + } + + ret = ctdb_event_command_pull(buf+offset, + buflen-offset, + &value->cmd, + &np); + if (ret != 0) { + goto fail; + } + offset += np; + + ret = ctdb_int32_pull(buf+offset, buflen-offset, &value->result, &np); + if (ret != 0) { + goto fail; + } + offset += np; + + if (value->result != 0) { + goto done; + } + + switch (value->cmd) { + case CTDB_EVENT_CMD_STATUS: + ret = ctdb_event_reply_status_pull(buf+offset, + buflen-offset, + value, + &value->data.status, + &np); + break; + + default: + np = 0; + break; + } + + if (ret != 0) { + goto fail; + } + offset += np; + +done: + *out = value; + *npull = offset; + + return 0; + +fail: + talloc_free(value); + return ret; +} + +size_t ctdb_event_request_len(struct ctdb_event_header *h, + struct ctdb_event_request *in) +{ + return ctdb_event_header_len(h) + + ctdb_event_request_data_len(in); +} + +int ctdb_event_request_push(struct ctdb_event_header *h, + struct ctdb_event_request *in, + uint8_t *buf, + size_t *buflen) +{ + size_t len, offset = 0, np; + + len = ctdb_event_request_len(h, in); + if (*buflen < len) { + *buflen = len; + return EMSGSIZE; + } + + h->length = *buflen; + + ctdb_event_header_push(h, buf+offset, &np); + offset += np; + + ctdb_event_request_data_push(in, buf+offset, &np); + offset += np; + + if (offset > *buflen) { + return EMSGSIZE; + } + + return 0; +} + +int ctdb_event_request_pull(uint8_t *buf, + size_t buflen, + struct ctdb_event_header *h, + TALLOC_CTX *mem_ctx, + struct ctdb_event_request **out) +{ + size_t offset = 0, np; + int ret; + + ret = ctdb_event_header_pull(buf+offset, buflen-offset, h, &np); + if (ret != 0) { + return ret; + } + offset += np; + + ret = ctdb_event_request_data_pull(buf+offset, + buflen-offset, + mem_ctx, + out, + &np); + if (ret != 0) { + return ret; + } + offset += np; + + if (offset > buflen) { + return EMSGSIZE; + } + + return 0; +} + +size_t ctdb_event_reply_len(struct ctdb_event_header *h, + struct ctdb_event_reply *in) +{ + return ctdb_event_header_len(h) + + ctdb_event_reply_data_len(in); +} + +int ctdb_event_reply_push(struct ctdb_event_header *h, + struct ctdb_event_reply *in, + uint8_t *buf, + size_t *buflen) +{ + size_t len, offset = 0, np; + + len = ctdb_event_reply_len(h, in); + if (*buflen < len) { + *buflen = len; + return EMSGSIZE; + } + + h->length = *buflen; + + ctdb_event_header_push(h, buf+offset, &np); + offset += np; + + ctdb_event_reply_data_push(in, buf+offset, &np); + offset += np; + + if (offset > *buflen) { + return EMSGSIZE; + } + + return 0; +} + +int ctdb_event_reply_pull(uint8_t *buf, + size_t buflen, + struct ctdb_event_header *h, + TALLOC_CTX *mem_ctx, + struct ctdb_event_reply **out) +{ + size_t offset = 0, np; + int ret; + + ret = ctdb_event_header_pull(buf+offset, buflen-offset, h, &np); + if (ret != 0) { + return ret; + } + offset += np; + + ret = ctdb_event_reply_data_pull(buf+offset, + buflen-offset, + mem_ctx, + out, + &np); + if (ret != 0) { + return ret; + } + offset += np; + + if (offset > buflen) { + return EMSGSIZE; + } + + return 0; +} |