| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970 |
- /*
- * Copyright (c) 2015-2020 Red Hat, Inc.
- *
- * All rights reserved.
- *
- * Author: Jan Friesse (jfriesse@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * - Neither the name of the Red Hat, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "log.h"
- #include "log-common.h"
- #include "qdevice-net-algorithm.h"
- #include "qdevice-net-cast-vote-timer.h"
- #include "qdevice-net-heuristics.h"
- #include "qdevice-net-msg-received.h"
- #include "qdevice-net-send.h"
- #include "qdevice-net-votequorum.h"
- #include "qdevice-net-echo-request-timer.h"
- #include "msg.h"
- #include "utils.h"
- /*
- * -1 - Incompatible tls combination
- * 0 - Don't use TLS
- * 1 - Use TLS
- */
- static int
- qdevice_net_msg_received_check_tls_compatibility(enum tlv_tls_supported server_tls,
- enum tlv_tls_supported client_tls)
- {
- int res;
- res = -1;
- switch (server_tls) {
- case TLV_TLS_UNSUPPORTED:
- switch (client_tls) {
- case TLV_TLS_UNSUPPORTED: res = 0; break;
- case TLV_TLS_SUPPORTED: res = 0; break;
- case TLV_TLS_REQUIRED: res = -1; break;
- }
- break;
- case TLV_TLS_SUPPORTED:
- switch (client_tls) {
- case TLV_TLS_UNSUPPORTED: res = 0; break;
- case TLV_TLS_SUPPORTED: res = 1; break;
- case TLV_TLS_REQUIRED: res = 1; break;
- }
- break;
- case TLV_TLS_REQUIRED:
- switch (client_tls) {
- case TLV_TLS_UNSUPPORTED: res = -1; break;
- case TLV_TLS_SUPPORTED: res = 1; break;
- case TLV_TLS_REQUIRED: res = 1; break;
- }
- break;
- }
- return (res);
- }
- static int
- qdevice_net_msg_received_unexpected_msg(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg, const char *msg_str)
- {
- log(LOG_ERR, "Received unexpected %s message. Disconnecting from server",
- msg_str);
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
- return (-1);
- }
- static int
- qdevice_net_msg_received_init(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- return (qdevice_net_msg_received_unexpected_msg(instance, msg, "init"));
- }
- static int
- qdevice_net_msg_received_preinit(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- return (qdevice_net_msg_received_unexpected_msg(instance, msg, "preinit"));
- }
- static int
- qdevice_net_msg_check_seq_number(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- if (!msg->seq_number_set || msg->seq_number != instance->last_msg_seq_num) {
- log(LOG_ERR, "Received message doesn't contain seq_number or "
- "it's not expected one.");
- return (-1);
- }
- return (0);
- }
- static int
- qdevice_net_msg_received_preinit_reply(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- int res;
- struct send_buffer_list_entry *send_buffer;
- log(LOG_DEBUG, "Received preinit reply msg");
- if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_PREINIT_REPLY) {
- log(LOG_ERR, "Received unexpected preinit reply message. "
- "Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
- return (-1);
- }
- if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- /*
- * Check TLS support
- */
- if (!msg->tls_supported_set || !msg->tls_client_cert_required_set) {
- log(LOG_ERR, "Required tls_supported or tls_client_cert_required "
- "option is unset");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- res = qdevice_net_msg_received_check_tls_compatibility(msg->tls_supported, instance->tls_supported);
- if (res == -1) {
- log(LOG_ERR, "Incompatible tls configuration (server %u client %u)",
- msg->tls_supported, instance->tls_supported);
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_INCOMPATIBLE_TLS;
- return (-1);
- } else if (res == 1) {
- /*
- * Start TLS
- */
- send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
- if (send_buffer == NULL) {
- log(LOG_ERR, "Can't allocate send list buffer for "
- "starttls msg");
- instance->disconnect_reason =
- QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
- return (-1);
- }
- instance->last_msg_seq_num++;
- if (msg_create_starttls(&send_buffer->buffer, 1,
- instance->last_msg_seq_num) == 0) {
- log(LOG_ERR, "Can't allocate send buffer for starttls msg");
- instance->disconnect_reason =
- QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
- send_buffer_list_discard_new(&instance->send_buffer_list, send_buffer);
- return (-1);
- }
- send_buffer_list_put(&instance->send_buffer_list, send_buffer);
- instance->state = QDEVICE_NET_INSTANCE_STATE_WAITING_STARTTLS_BEING_SENT;
- } else if (res == 0) {
- if (qdevice_net_send_init(instance) != 0) {
- instance->disconnect_reason =
- QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
- return (-1);
- }
- }
- return (0);
- }
- static int
- qdevice_net_msg_received_init_reply(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- size_t zi;
- int res;
- enum qdevice_heuristics_mode active_heuristics_mode;
- log(LOG_DEBUG, "Received init reply msg");
- if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_INIT_REPLY) {
- log(LOG_ERR, "Received unexpected init reply message. "
- "Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
- return (-1);
- }
- if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- if (!msg->reply_error_code_set) {
- log(LOG_ERR, "Received init reply message without error code."
- "Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- if (msg->reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
- log(LOG_ERR, "Received init reply message with error code %"PRIu16". "
- "Disconnecting from server", msg->reply_error_code);
- if (msg->reply_error_code == TLV_REPLY_ERROR_CODE_DUPLICATE_NODE_ID) {
- log(LOG_ERR, "Duplicate node id may be result of server not yet "
- "accepted this node disconnect. Retry again.");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_DUPLICATE_NODE_ID_ERROR;
- } else if (msg->reply_error_code == TLV_REPLY_ERROR_CODE_TIE_BREAKER_DIFFERS_FROM_OTHER_NODES) {
- log(LOG_ERR, "Configured tie-breaker differs in cluster. This may be "
- "result of server not yet accepted this node disconnect. Retry again.");
- instance->disconnect_reason =
- QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_TIE_BREAKER_DIFFERS_FROM_OTHER_NODES_ERROR;
- } else if (msg->reply_error_code == TLV_REPLY_ERROR_CODE_ALGORITHM_DIFFERS_FROM_OTHER_NODES) {
- log(LOG_ERR, "Configured algorithm differs in cluster. This may be "
- "result of server not yet accepted this node disconnect. Retry again.");
- instance->disconnect_reason =
- QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_ALGORITHM_DIFFERS_FROM_OTHER_NODES_ERROR;
- } else {
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_ERROR;
- }
- return (-1);
- }
- if (!msg->server_maximum_request_size_set || !msg->server_maximum_reply_size_set) {
- log(LOG_ERR, "Required maximum_request_size or maximum_reply_size "
- "option is unset");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- if (msg->supported_messages == NULL || msg->supported_options == NULL) {
- log(LOG_ERR, "Required supported messages or supported options "
- "option is unset");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- if (msg->supported_decision_algorithms == NULL) {
- log(LOG_ERR, "Required supported decision algorithms option is unset");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- if (msg->server_maximum_request_size < instance->advanced_settings->net_min_msg_send_size) {
- log(LOG_ERR,
- "Server accepts maximum %zu bytes message but this client minimum "
- "is %zu bytes.", msg->server_maximum_request_size,
- instance->advanced_settings->net_min_msg_send_size);
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_INCOMPATIBLE_MSG_SIZE;
- return (-1);
- }
- if (msg->server_maximum_reply_size > instance->advanced_settings->net_max_msg_receive_size) {
- log(LOG_ERR,
- "Server may send message up to %zu bytes message but this client maximum "
- "is %zu bytes.", msg->server_maximum_reply_size,
- instance->advanced_settings->net_max_msg_receive_size);
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_INCOMPATIBLE_MSG_SIZE;
- return (-1);
- }
- /*
- * Change buffer sizes
- */
- dynar_set_max_size(&instance->receive_buffer, msg->server_maximum_reply_size);
- send_buffer_list_set_max_buffer_size(&instance->send_buffer_list,
- msg->server_maximum_request_size);
- /*
- * Check if server supports decision algorithm we need
- */
- res = 0;
- for (zi = 0; zi < msg->no_supported_decision_algorithms && !res; zi++) {
- if (msg->supported_decision_algorithms[zi] == instance->decision_algorithm) {
- res = 1;
- }
- }
- if (!res) {
- log(LOG_ERR, "Server doesn't support required decision algorithm");
- instance->disconnect_reason =
- QDEVICE_NET_DISCONNECT_REASON_SERVER_DOESNT_SUPPORT_REQUIRED_ALGORITHM;
- return (-1);
- }
- /*
- * Check if server supports heuristics/keep active partition tie breaker
- */
- instance->server_supports_heuristics = 0;
- instance->server_supports_keep_active_partition_tie_breaker = 0;
- for (zi = 0; zi < msg->no_supported_options; zi++) {
- if (msg->supported_options[zi] == TLV_OPT_HEURISTICS) {
- instance->server_supports_heuristics = 1;
- }
- if (msg->supported_options[zi] == TLV_OPT_KEEP_ACTIVE_PARTITION_TIE_BREAKER) {
- instance->server_supports_keep_active_partition_tie_breaker = 1;
- }
- }
- if (!instance->server_supports_heuristics) {
- active_heuristics_mode = instance->qdevice_instance_ptr->heuristics_instance.mode;
- if (active_heuristics_mode == QDEVICE_HEURISTICS_MODE_ENABLED ||
- active_heuristics_mode == QDEVICE_HEURISTICS_MODE_SYNC) {
- log(LOG_ERR, "Heuristics are enabled but not supported by server");
- instance->disconnect_reason =
- QDEVICE_NET_DISCONNECT_REASON_SERVER_DOESNT_SUPPORT_REQUIRED_OPT;
- return (-1);
- }
- }
- /*
- * Finally fully connected so it's possible to remove connection timer
- */
- if (instance->connect_timer != NULL) {
- timer_list_entry_delete(
- pr_poll_loop_get_timer_list(&instance->qdevice_instance_ptr->main_poll_loop),
- instance->connect_timer);
- instance->connect_timer = NULL;
- }
- /*
- * Server accepted heartbeat interval -> schedule regular sending of echo request
- */
- if (qdevice_net_echo_request_timer_schedule(instance) != 0) {
- return (-1);
- }
- /*
- * Run heuristics (even when it is disabled, undefined result is ok, rest of sending
- * is handled by qdevice_net_connect_heuristics_exec_result_callback
- */
- if (qdevice_net_heuristics_exec_after_connect(instance) != 0) {
- return (-1);
- }
- return (0);
- }
- static int
- qdevice_net_msg_received_starttls(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- return (qdevice_net_msg_received_unexpected_msg(instance, msg, "starttls"));
- }
- static int
- qdevice_net_msg_received_server_error(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- if (!msg->reply_error_code_set) {
- log(LOG_ERR, "Received server error without error code set. "
- "Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- } else {
- log(LOG_ERR, "Received server error %"PRIu16". "
- "Disconnecting from server", msg->reply_error_code);
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_ERROR;
- }
- return (-1);
- }
- static int
- qdevice_net_msg_received_set_option(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- return (qdevice_net_msg_received_unexpected_msg(instance, msg, "set option"));
- }
- static int
- qdevice_net_msg_received_set_option_reply(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) {
- log(LOG_ERR, "Received unexpected set option reply message. "
- "Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
- return (-1);
- }
- log(LOG_DEBUG, "Received set option reply seq(%u) = "UTILS_PRI_MSG_SEQ ", "
- "HB(%u) = %" PRIu32 "ms, KAP Tie-breaker(%u) = %s",
- msg->seq_number_set, msg->seq_number,
- msg->heartbeat_interval_set, msg->heartbeat_interval,
- msg->keep_active_partition_tie_breaker_set,
- tlv_keep_active_partition_tie_breaker_to_str(msg->keep_active_partition_tie_breaker));
- if (msg->heartbeat_interval_set) {
- if (qdevice_net_echo_request_timer_schedule(instance) != 0) {
- return (-1);
- }
- }
- return (0);
- }
- static int
- qdevice_net_msg_received_echo_request(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- return (qdevice_net_msg_received_unexpected_msg(instance, msg, "echo request"));
- }
- static int
- qdevice_net_msg_received_echo_reply(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- if (!msg->seq_number_set) {
- log(LOG_ERR, "Received echo reply message doesn't contain seq_number.");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- if (msg->seq_number != instance->echo_request_expected_msg_seq_num) {
- log(LOG_WARNING, "Received echo reply message seq_number is not expected one.");
- }
- if (qdevice_net_algorithm_echo_reply_received(instance, msg->seq_number,
- msg->seq_number == instance->echo_request_expected_msg_seq_num) != 0) {
- log(LOG_DEBUG, "Algorithm returned error. Disconnecting");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_ECHO_REPLY_RECEIVED_ERR;
- return (-1);
- }
- instance->echo_reply_received_msg_seq_num = msg->seq_number;
- instance->last_echo_reply_received_time = time(NULL);
- return (0);
- }
- static int
- qdevice_net_msg_received_node_list(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- return (qdevice_net_msg_received_unexpected_msg(instance, msg, "node list"));
- }
- static int
- qdevice_net_msg_received_node_list_reply(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- const char *str;
- enum tlv_vote result_vote;
- int res;
- int case_processed;
- int ring_id_is_valid;
- if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) {
- log(LOG_ERR, "Received unexpected node list reply message. "
- "Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
- return (-1);
- }
- if (!msg->vote_set || !msg->seq_number_set || !msg->node_list_type_set) {
- log(LOG_ERR, "Received node list reply message without "
- "required options. Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- if (!msg->ring_id_set) {
- log(LOG_ERR, "Received node list reply message "
- "without ring id set. Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- str = NULL;
- switch (msg->node_list_type) {
- case TLV_NODE_LIST_TYPE_INITIAL_CONFIG: str = "initial config"; break;
- case TLV_NODE_LIST_TYPE_CHANGED_CONFIG: str = "changed config"; break;
- case TLV_NODE_LIST_TYPE_MEMBERSHIP: str ="membership"; break;
- case TLV_NODE_LIST_TYPE_QUORUM: str ="quorum"; break;
- /*
- * Default is not defined intentionally. Compiler shows warning when new node list type
- * is added
- */
- }
- if (str == NULL) {
- log(LOG_CRIT, "qdevice_net_msg_received_node_list_reply fatal error. "
- "Unhandled node_list_type (debug output)");
- exit(EXIT_FAILURE);
- }
- log(LOG_DEBUG, "Received %s node list reply", str);
- log(LOG_DEBUG, " seq = "UTILS_PRI_MSG_SEQ, msg->seq_number);
- log(LOG_DEBUG, " vote = %s", tlv_vote_to_str(msg->vote));
- log(LOG_DEBUG, " ring id = ("UTILS_PRI_RING_ID")",
- msg->ring_id.node_id, msg->ring_id.seq);
- /*
- * Call algorithm
- */
- result_vote = msg->vote;
- if (!tlv_ring_id_eq(&msg->ring_id, &instance->last_sent_ring_id)) {
- ring_id_is_valid = 0;
- log(LOG_DEBUG, "Received node list reply with old ring id.");
- } else {
- ring_id_is_valid = 1;
- }
- case_processed = 0;
- switch (msg->node_list_type) {
- case TLV_NODE_LIST_TYPE_INITIAL_CONFIG:
- case TLV_NODE_LIST_TYPE_CHANGED_CONFIG:
- case_processed = 1;
- res = qdevice_net_algorithm_config_node_list_reply_received(instance,
- msg->seq_number, (msg->node_list_type == TLV_NODE_LIST_TYPE_INITIAL_CONFIG),
- &msg->ring_id, ring_id_is_valid, &result_vote);
- break;
- case TLV_NODE_LIST_TYPE_MEMBERSHIP:
- case_processed = 1;
- res = qdevice_net_algorithm_membership_node_list_reply_received(instance,
- msg->seq_number, &msg->ring_id, ring_id_is_valid, &result_vote);
- break;
- case TLV_NODE_LIST_TYPE_QUORUM:
- case_processed = 1;
- res = qdevice_net_algorithm_quorum_node_list_reply_received(instance,
- msg->seq_number, &msg->ring_id, ring_id_is_valid, &result_vote);
- break;
- /*
- * Default is not defined intentionally. Compiler shows warning when new node list type
- * is added
- */
- }
- if (!case_processed) {
- log(LOG_CRIT, "qdevice_net_msg_received_node_list_reply fatal error. "
- "Unhandled node_list_type (algorithm call)");
- exit(EXIT_FAILURE);
- }
- if (res != 0) {
- log(LOG_DEBUG, "Algorithm returned error. Disconnecting.");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_NODE_LIST_REPLY_ERR;
- return (-1);
- } else {
- log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
- }
- if (qdevice_net_cast_vote_timer_update(instance, result_vote) != 0) {
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER;
- return (-1);
- }
- return (0);
- }
- static int
- qdevice_net_msg_received_ask_for_vote(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- return (qdevice_net_msg_received_unexpected_msg(instance, msg, "ask for vote"));
- }
- static int
- qdevice_net_msg_received_ask_for_vote_reply(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- enum tlv_vote result_vote;
- int ring_id_is_valid;
- if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) {
- log(LOG_ERR, "Received unexpected ask for vote reply message. "
- "Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
- return (-1);
- }
- if (!msg->vote_set || !msg->seq_number_set || !msg->ring_id_set) {
- log(LOG_ERR, "Received ask for vote reply message without "
- "required options. Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- log(LOG_DEBUG, "Received ask for vote reply");
- log(LOG_DEBUG, " seq = "UTILS_PRI_MSG_SEQ, msg->seq_number);
- log(LOG_DEBUG, " vote = %s", tlv_vote_to_str(msg->vote));
- log(LOG_DEBUG, " ring id = ("UTILS_PRI_RING_ID")",
- msg->ring_id.node_id, msg->ring_id.seq);
- result_vote = msg->vote;
- if (!tlv_ring_id_eq(&msg->ring_id, &instance->last_sent_ring_id)) {
- ring_id_is_valid = 0;
- log(LOG_DEBUG, "Received ask for vote reply with old ring id.");
- } else {
- ring_id_is_valid = 1;
- }
- if (qdevice_net_algorithm_ask_for_vote_reply_received(instance, msg->seq_number,
- &msg->ring_id, ring_id_is_valid, &result_vote) != 0) {
- log(LOG_DEBUG, "Algorithm returned error. Disconnecting.");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_ASK_FOR_VOTE_REPLY_ERR;
- return (-1);
- } else {
- log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
- }
- if (qdevice_net_cast_vote_timer_update(instance, result_vote) != 0) {
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER;
- return (-1);
- }
- return (0);
- }
- static int
- qdevice_net_msg_received_vote_info(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- struct send_buffer_list_entry *send_buffer;
- enum tlv_vote result_vote;
- int ring_id_is_valid;
- if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) {
- log(LOG_ERR, "Received unexpected vote info message. "
- "Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
- return (-1);
- }
- if (!msg->vote_set || !msg->seq_number_set || !msg->ring_id_set) {
- log(LOG_ERR, "Received node list reply message without "
- "required options. Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- log(LOG_DEBUG, "Received vote info");
- log(LOG_DEBUG, " seq = "UTILS_PRI_MSG_SEQ, msg->seq_number);
- log(LOG_DEBUG, " vote = %s", tlv_vote_to_str(msg->vote));
- log(LOG_DEBUG, " ring id = ("UTILS_PRI_RING_ID")",
- msg->ring_id.node_id, msg->ring_id.seq);
- result_vote = msg->vote;
- if (!tlv_ring_id_eq(&msg->ring_id, &instance->last_sent_ring_id)) {
- ring_id_is_valid = 0;
- log(LOG_DEBUG, "Received vote info with old ring id.");
- } else {
- ring_id_is_valid = 1;
- }
- if (qdevice_net_algorithm_vote_info_received(instance, msg->seq_number,
- &msg->ring_id, ring_id_is_valid, &result_vote) != 0) {
- log(LOG_DEBUG, "Algorithm returned error. Disconnecting.");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_VOTE_INFO_ERR;
- return (-1);
- } else {
- log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
- }
- if (qdevice_net_cast_vote_timer_update(instance, result_vote) != 0) {
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER;
- return (-1);
- }
- /*
- * Create reply message
- */
- send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
- if (send_buffer == NULL) {
- log(LOG_ERR, "Can't allocate send list buffer for "
- "vote info reply msg");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
- return (-1);
- }
- if (msg_create_vote_info_reply(&send_buffer->buffer, msg->seq_number) == 0) {
- log(LOG_ERR, "Can't allocate send buffer for "
- "vote info reply list msg");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
- send_buffer_list_discard_new(&instance->send_buffer_list, send_buffer);
- return (-1);
- }
- send_buffer_list_put(&instance->send_buffer_list, send_buffer);
- return (0);
- }
- static int
- qdevice_net_msg_received_vote_info_reply(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- return (qdevice_net_msg_received_unexpected_msg(instance, msg, "vote info reply"));
- }
- static int
- qdevice_net_msg_received_heuristics_change(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- return (qdevice_net_msg_received_unexpected_msg(instance, msg, "heuristics change"));
- }
- static int
- qdevice_net_msg_received_heuristics_change_reply(struct qdevice_net_instance *instance,
- const struct msg_decoded *msg)
- {
- enum tlv_vote result_vote;
- int ring_id_is_valid;
- if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) {
- log(LOG_ERR, "Received unexpected heuristics change reply message. "
- "Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
- return (-1);
- }
- if (!msg->vote_set || !msg->seq_number_set || !msg->ring_id_set ||
- msg->heuristics == TLV_HEURISTICS_UNDEFINED) {
- log(LOG_ERR, "Received heuristics change reply message without "
- "required options. Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
- return (-1);
- }
- log(LOG_DEBUG, "Received heuristics change reply");
- log(LOG_DEBUG, " seq = "UTILS_PRI_MSG_SEQ, msg->seq_number);
- log(LOG_DEBUG, " vote = %s", tlv_vote_to_str(msg->vote));
- log(LOG_DEBUG, " ring id = ("UTILS_PRI_RING_ID")",
- msg->ring_id.node_id, msg->ring_id.seq);
- log(LOG_DEBUG, " heuristics = %s", tlv_heuristics_to_str(msg->heuristics));
- result_vote = msg->vote;
- if (!tlv_ring_id_eq(&msg->ring_id, &instance->last_sent_ring_id)) {
- ring_id_is_valid = 0;
- log(LOG_DEBUG, "Received heuristics change reply with old ring id.");
- } else {
- ring_id_is_valid = 1;
- }
- if (qdevice_net_algorithm_heuristics_change_reply_received(instance, msg->seq_number,
- &msg->ring_id, ring_id_is_valid, msg->heuristics, &result_vote) != 0) {
- log(LOG_DEBUG, "Algorithm returned error. Disconnecting.");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_HEURISTICS_CHANGE_REPLY_ERR;
- return (-1);
- } else {
- log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
- }
- if (qdevice_net_cast_vote_timer_update(instance, result_vote) != 0) {
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER;
- return (-1);
- }
- return (0);
- }
- int
- qdevice_net_msg_received(struct qdevice_net_instance *instance)
- {
- struct msg_decoded msg;
- int res;
- int ret_val;
- int msg_processed;
- msg_decoded_init(&msg);
- res = msg_decode(&instance->receive_buffer, &msg);
- if (res != 0) {
- /*
- * Error occurred. Disconnect.
- */
- log_common_msg_decode_error(res);
- log(LOG_ERR, "Disconnecting from server");
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_MSG_DECODE_ERROR;
- return (-1);
- }
- ret_val = 0;
- msg_processed = 0;
- switch (msg.type) {
- case MSG_TYPE_INIT:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_init(instance, &msg);
- break;
- case MSG_TYPE_PREINIT:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_preinit(instance, &msg);
- break;
- case MSG_TYPE_PREINIT_REPLY:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_preinit_reply(instance, &msg);
- break;
- case MSG_TYPE_STARTTLS:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_starttls(instance, &msg);
- break;
- case MSG_TYPE_SERVER_ERROR:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_server_error(instance, &msg);
- break;
- case MSG_TYPE_INIT_REPLY:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_init_reply(instance, &msg);
- break;
- case MSG_TYPE_SET_OPTION:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_set_option(instance, &msg);
- break;
- case MSG_TYPE_SET_OPTION_REPLY:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_set_option_reply(instance, &msg);
- break;
- case MSG_TYPE_ECHO_REQUEST:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_echo_request(instance, &msg);
- break;
- case MSG_TYPE_ECHO_REPLY:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_echo_reply(instance, &msg);
- break;
- case MSG_TYPE_NODE_LIST:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_node_list(instance, &msg);
- break;
- case MSG_TYPE_NODE_LIST_REPLY:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_node_list_reply(instance, &msg);
- break;
- case MSG_TYPE_ASK_FOR_VOTE:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_ask_for_vote(instance, &msg);
- break;
- case MSG_TYPE_ASK_FOR_VOTE_REPLY:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_ask_for_vote_reply(instance, &msg);
- break;
- case MSG_TYPE_VOTE_INFO:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_vote_info(instance, &msg);
- break;
- case MSG_TYPE_VOTE_INFO_REPLY:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_vote_info_reply(instance, &msg);
- break;
- case MSG_TYPE_HEURISTICS_CHANGE:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_heuristics_change(instance, &msg);
- break;
- case MSG_TYPE_HEURISTICS_CHANGE_REPLY:
- msg_processed = 1;
- ret_val = qdevice_net_msg_received_heuristics_change_reply(instance, &msg);
- /*
- * Default is not defined intentionally. Compiler shows warning when msg type is added
- */
- }
- if (!msg_processed) {
- log(LOG_ERR, "Received unsupported message %u. "
- "Disconnecting from server", msg.type);
- instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
- ret_val = -1;
- }
- msg_decoded_destroy(&msg);
- return (ret_val);
- }
|