2 * Copyright (c) 2015-2019 Red Hat, Inc.
6 * Author: Jan Friesse (jfriesse@redhat.com)
8 * This software licensed under BSD license, the text of which follows:
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of the Red Hat, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/types.h>
38 #include "qnetd-algorithm.h"
39 #include "qnetd-instance.h"
40 #include "qnetd-log-debug.h"
41 #include "qnetd-client-send.h"
45 #include "qnetd-client-msg-received.h"
49 * -1 - Disconnect client
50 * -2 - Error reply sent, but no need to disconnect client
53 qnetd_client_msg_received_check_tls(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
54 const struct msg_decoded
*msg
)
56 int check_certificate
;
58 CERTCertificate
*peer_cert
;
61 check_certificate
= 0;
66 switch (instance
->tls_supported
) {
67 case TLV_TLS_UNSUPPORTED
:
70 check_certificate
= 0;
72 case TLV_TLS_SUPPORTED
:
76 if (client
->tls_started
&& instance
->tls_client_cert_required
&&
77 !client
->tls_peer_certificate_verified
) {
78 check_certificate
= 1;
81 case TLV_TLS_REQUIRED
:
85 if (instance
->tls_client_cert_required
&& !client
->tls_peer_certificate_verified
) {
86 check_certificate
= 1;
90 * Default is not defined intentionally. Compiler shows warning when new
91 * tls supported is added
95 if (!case_processed
) {
96 log(LOG_ERR
, "Unhandled instance tls supported %u", instance
->tls_supported
);
100 if (tls_required
&& !client
->tls_started
) {
101 log(LOG_ERR
, "TLS is required but doesn't started yet. "
102 "Sending back error message");
104 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
105 TLV_REPLY_ERROR_CODE_TLS_REQUIRED
) != 0) {
112 if (check_certificate
) {
113 peer_cert
= SSL_PeerCertificate(client
->socket
);
115 if (peer_cert
== NULL
) {
116 log(LOG_ERR
, "Client doesn't sent valid certificate. "
117 "Disconnecting client");
122 if (CERT_VerifyCertName(peer_cert
, client
->cluster_name
) != SECSuccess
) {
123 log(LOG_ERR
, "Client doesn't sent certificate with valid CN. "
124 "Disconnecting client");
126 CERT_DestroyCertificate(peer_cert
);
131 CERT_DestroyCertificate(peer_cert
);
133 client
->tls_peer_certificate_verified
= 1;
140 qnetd_client_msg_received_preinit(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
141 const struct msg_decoded
*msg
)
143 struct send_buffer_list_entry
*send_buffer
;
145 if (msg
->cluster_name
== NULL
) {
146 log(LOG_ERR
, "Received preinit message without cluster name. "
147 "Sending error reply.");
149 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
150 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
) != 0) {
157 client
->cluster_name
= malloc(msg
->cluster_name_len
+ 1);
158 if (client
->cluster_name
== NULL
) {
159 log(LOG_ERR
, "Can't allocate cluster name. Sending error reply.");
161 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
162 TLV_REPLY_ERROR_CODE_INTERNAL_ERROR
) != 0) {
168 memset(client
->cluster_name
, 0, msg
->cluster_name_len
+ 1);
169 memcpy(client
->cluster_name
, msg
->cluster_name
, msg
->cluster_name_len
);
171 client
->cluster_name_len
= msg
->cluster_name_len
;
172 client
->preinit_received
= 1;
174 send_buffer
= send_buffer_list_get_new(&client
->send_buffer_list
);
175 if (send_buffer
== NULL
) {
176 log(LOG_ERR
, "Can't alloc preinit reply msg from list. "
177 "Disconnecting client connection.");
182 if (msg_create_preinit_reply(&send_buffer
->buffer
, msg
->seq_number_set
, msg
->seq_number
,
183 instance
->tls_supported
, instance
->tls_client_cert_required
) == 0) {
184 log(LOG_ERR
, "Can't alloc preinit reply msg. "
185 "Disconnecting client connection.");
187 send_buffer_list_discard_new(&client
->send_buffer_list
, send_buffer
);
192 send_buffer_list_put(&client
->send_buffer_list
, send_buffer
);
198 qnetd_client_msg_received_unexpected_msg(struct qnetd_client
*client
,
199 const struct msg_decoded
*msg
, const char *msg_str
)
202 log(LOG_ERR
, "Received %s message. Sending back error message", msg_str
);
204 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
205 TLV_REPLY_ERROR_CODE_UNEXPECTED_MESSAGE
) != 0) {
213 qnetd_client_msg_received_preinit_reply(struct qnetd_instance
*instance
,
214 struct qnetd_client
*client
, const struct msg_decoded
*msg
)
217 return (qnetd_client_msg_received_unexpected_msg(client
, msg
, "preinit reply"));
221 qnetd_client_msg_received_starttls(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
222 const struct msg_decoded
*msg
)
224 PRFileDesc
*new_pr_fd
;
226 if (!client
->preinit_received
) {
227 log(LOG_ERR
, "Received starttls before preinit message. "
228 "Sending error reply.");
230 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
231 TLV_REPLY_ERROR_CODE_PREINIT_REQUIRED
) != 0) {
238 if ((new_pr_fd
= nss_sock_start_ssl_as_server(client
->socket
, instance
->server
.cert
,
239 instance
->server
.private_key
, instance
->tls_client_cert_required
, 0, NULL
)) == NULL
) {
240 log_nss(LOG_ERR
, "Can't start TLS. Disconnecting client.");
245 client
->tls_started
= 1;
246 client
->tls_peer_certificate_verified
= 0;
247 client
->socket
= new_pr_fd
;
253 qnetd_client_msg_received_server_error(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
254 const struct msg_decoded
*msg
)
257 return (qnetd_client_msg_received_unexpected_msg(client
, msg
, "server error"));
261 * Checks if new client send information are valid. It means:
262 * - in cluster is no duplicate node with same nodeid
263 * - it has same tie_breaker as other nodes in cluster
264 * - it has same algorithm as other nodes in cluster
266 static enum tlv_reply_error_code
267 qnetd_client_msg_received_init_check_new_client(struct qnetd_instance
*instance
,
268 struct qnetd_client
*new_client
)
270 struct qnetd_cluster
*cluster
;
271 struct qnetd_client
*client
;
273 cluster
= qnetd_cluster_list_find_by_name(&instance
->clusters
, new_client
->cluster_name
,
274 new_client
->cluster_name_len
);
276 if (cluster
== NULL
) {
277 return (TLV_REPLY_ERROR_CODE_NO_ERROR
);
280 TAILQ_FOREACH(client
, &cluster
->client_list
, cluster_entries
) {
281 if (!tlv_tie_breaker_eq(&new_client
->tie_breaker
, &client
->tie_breaker
)) {
282 log(LOG_ERR
, "Received init message contains tie-breaker which "
283 "differs from rest of cluster. Sending error reply");
285 return (TLV_REPLY_ERROR_CODE_TIE_BREAKER_DIFFERS_FROM_OTHER_NODES
);
288 if (new_client
->decision_algorithm
!= client
->decision_algorithm
) {
289 log(LOG_ERR
, "Received init message contains algorithm which "
290 "differs from rest of cluster. Sending error reply");
292 return (TLV_REPLY_ERROR_CODE_ALGORITHM_DIFFERS_FROM_OTHER_NODES
);
295 if (new_client
->node_id
== client
->node_id
) {
296 log(LOG_ERR
, "Received init message contains node id which is "
297 "duplicate of other node in cluster. Sending error reply");
299 return (TLV_REPLY_ERROR_CODE_DUPLICATE_NODE_ID
);
303 return (TLV_REPLY_ERROR_CODE_NO_ERROR
);
307 qnetd_client_msg_received_init(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
308 const struct msg_decoded
*msg
)
312 enum msg_type
*supported_msgs
;
313 size_t no_supported_msgs
;
314 enum tlv_opt_type
*supported_opts
;
315 size_t no_supported_opts
;
316 struct send_buffer_list_entry
*send_buffer
;
317 enum tlv_reply_error_code reply_error_code
;
318 struct qnetd_cluster
*cluster
;
320 supported_msgs
= NULL
;
321 supported_opts
= NULL
;
322 no_supported_msgs
= 0;
323 no_supported_opts
= 0;
325 reply_error_code
= TLV_REPLY_ERROR_CODE_NO_ERROR
;
327 if ((res
= qnetd_client_msg_received_check_tls(instance
, client
, msg
)) != 0) {
328 return (res
== -1 ? -1 : 0);
331 if (!client
->preinit_received
) {
332 log(LOG_ERR
, "Received init before preinit message. Sending error reply.");
334 reply_error_code
= TLV_REPLY_ERROR_CODE_PREINIT_REQUIRED
;
337 if (reply_error_code
== TLV_REPLY_ERROR_CODE_NO_ERROR
&& !msg
->node_id_set
) {
338 log(LOG_ERR
, "Received init message without node id set. "
339 "Sending error reply.");
341 reply_error_code
= TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
;
343 client
->node_id_set
= 1;
344 client
->node_id
= msg
->node_id
;
347 if (reply_error_code
== TLV_REPLY_ERROR_CODE_NO_ERROR
&& !msg
->ring_id_set
) {
348 log(LOG_ERR
, "Received init message without ring id set. "
349 "Sending error reply.");
351 reply_error_code
= TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
;
353 memcpy(&client
->last_ring_id
, &msg
->ring_id
, sizeof(struct tlv_ring_id
));
356 if (reply_error_code
== TLV_REPLY_ERROR_CODE_NO_ERROR
&& !msg
->heartbeat_interval_set
) {
357 log(LOG_ERR
, "Received init message without heartbeat interval set. "
358 "Sending error reply.");
360 reply_error_code
= TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
;
362 if (msg
->heartbeat_interval
< instance
->advanced_settings
->heartbeat_interval_min
||
363 msg
->heartbeat_interval
> instance
->advanced_settings
->heartbeat_interval_max
) {
364 log(LOG_ERR
, "Client requested invalid heartbeat interval %u. "
365 "Sending error reply.", msg
->heartbeat_interval
);
367 reply_error_code
= TLV_REPLY_ERROR_CODE_INVALID_HEARTBEAT_INTERVAL
;
369 client
->heartbeat_interval
= msg
->heartbeat_interval
;
373 if (reply_error_code
== TLV_REPLY_ERROR_CODE_NO_ERROR
&& !msg
->tie_breaker_set
) {
374 log(LOG_ERR
, "Received init message without tie-breaker set. "
375 "Sending error reply.");
377 reply_error_code
= TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
;
379 memcpy(&client
->tie_breaker
, &msg
->tie_breaker
, sizeof(msg
->tie_breaker
));
382 if (msg
->supported_messages
!= NULL
) {
384 * Client sent supported messages. For now this is ignored but in the future
385 * this may be used to ensure backward compatibility.
388 for (i = 0; i < msg->no_supported_messages; i++) {
389 log(LOG_DEBUG, "Client supports %u message",
390 (int)msg->supported_messages[i]);
395 * Sent back supported messages
397 msg_get_supported_messages(&supported_msgs
, &no_supported_msgs
);
400 if (msg
->supported_options
!= NULL
) {
402 * Client sent supported options. For now this is ignored but in the future
403 * this may be used to ensure backward compatibility.
406 for (i = 0; i < msg->no_supported_options; i++) {
407 log(LOG_DEBUG, "Client supports %u option",
408 (int)msg->supported_messages[i]);
413 * Send back supported options
415 tlv_get_supported_options(&supported_opts
, &no_supported_opts
);
418 if (reply_error_code
== TLV_REPLY_ERROR_CODE_NO_ERROR
&& !msg
->decision_algorithm_set
) {
419 log(LOG_ERR
, "Received init message without decision algorithm. "
420 "Sending error reply.");
422 reply_error_code
= TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
;
425 * Check if decision algorithm requested by client is supported
429 for (zi
= 0; zi
< QNETD_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE
&& !res
; zi
++) {
430 if (qnetd_static_supported_decision_algorithms
[zi
] ==
431 msg
->decision_algorithm
) {
437 log(LOG_ERR
, "Client requested unsupported decision algorithm %u. "
438 "Sending error reply.", msg
->decision_algorithm
);
440 reply_error_code
= TLV_REPLY_ERROR_CODE_UNSUPPORTED_DECISION_ALGORITHM
;
443 client
->decision_algorithm
= msg
->decision_algorithm
;
446 if (reply_error_code
== TLV_REPLY_ERROR_CODE_NO_ERROR
) {
447 reply_error_code
= qnetd_client_msg_received_init_check_new_client(instance
,
451 if (reply_error_code
== TLV_REPLY_ERROR_CODE_NO_ERROR
) {
452 cluster
= qnetd_cluster_list_add_client(&instance
->clusters
, client
);
453 if (cluster
== NULL
) {
454 log(LOG_ERR
, "Can't add client to cluster list. "
455 "Sending error reply.");
457 reply_error_code
= TLV_REPLY_ERROR_CODE_INTERNAL_ERROR
;
459 client
->cluster
= cluster
;
460 client
->cluster_list
= &instance
->clusters
;
464 if (reply_error_code
== TLV_REPLY_ERROR_CODE_NO_ERROR
) {
465 qnetd_log_debug_new_client_connected(client
);
467 reply_error_code
= qnetd_algorithm_client_init(client
);
470 if (reply_error_code
== TLV_REPLY_ERROR_CODE_NO_ERROR
) {
472 * Correct init received
474 client
->init_received
= 1;
476 log(LOG_ERR
, "Algorithm returned error code. Sending error reply.");
479 send_buffer
= send_buffer_list_get_new(&client
->send_buffer_list
);
480 if (send_buffer
== NULL
) {
481 log(LOG_ERR
, "Can't alloc init reply msg from list. "
482 "Disconnecting client connection.");
487 if (msg_create_init_reply(&send_buffer
->buffer
, msg
->seq_number_set
, msg
->seq_number
,
489 supported_msgs
, no_supported_msgs
, supported_opts
, no_supported_opts
,
490 instance
->advanced_settings
->max_client_receive_size
,
491 instance
->advanced_settings
->max_client_send_size
,
492 qnetd_static_supported_decision_algorithms
,
493 QNETD_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE
) == 0) {
494 log(LOG_ERR
, "Can't alloc init reply msg. Disconnecting client connection.");
496 send_buffer_list_discard_new(&client
->send_buffer_list
, send_buffer
);
501 send_buffer_list_put(&client
->send_buffer_list
, send_buffer
);
507 qnetd_client_msg_received_init_reply(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
508 const struct msg_decoded
*msg
)
511 return (qnetd_client_msg_received_unexpected_msg(client
, msg
, "init reply"));
515 qnetd_client_msg_received_set_option_reply(struct qnetd_instance
*instance
,
516 struct qnetd_client
*client
, const struct msg_decoded
*msg
)
519 return (qnetd_client_msg_received_unexpected_msg(client
, msg
, "set option reply"));
523 qnetd_client_msg_received_set_option(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
524 const struct msg_decoded
*msg
)
527 struct send_buffer_list_entry
*send_buffer
;
529 if ((res
= qnetd_client_msg_received_check_tls(instance
, client
, msg
)) != 0) {
530 return (res
== -1 ? -1 : 0);
533 if (!client
->init_received
) {
534 log(LOG_ERR
, "Received set option message before init message. "
535 "Sending error reply.");
537 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
538 TLV_REPLY_ERROR_CODE_INIT_REQUIRED
) != 0) {
545 if (msg
->heartbeat_interval_set
) {
547 * Check if heartbeat interval is valid
549 if (msg
->heartbeat_interval
< instance
->advanced_settings
->heartbeat_interval_min
||
550 msg
->heartbeat_interval
> instance
->advanced_settings
->heartbeat_interval_max
) {
551 log(LOG_ERR
, "Client requested invalid heartbeat interval %u. "
552 "Sending error reply.", msg
->heartbeat_interval
);
554 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
555 TLV_REPLY_ERROR_CODE_INVALID_HEARTBEAT_INTERVAL
) != 0) {
562 client
->heartbeat_interval
= msg
->heartbeat_interval
;
565 send_buffer
= send_buffer_list_get_new(&client
->send_buffer_list
);
566 if (send_buffer
== NULL
) {
567 log(LOG_ERR
, "Can't alloc set option reply msg from list. "
568 "Disconnecting client connection.");
573 if (msg_create_set_option_reply(&send_buffer
->buffer
, msg
->seq_number_set
, msg
->seq_number
,
574 client
->heartbeat_interval
) == 0) {
575 log(LOG_ERR
, "Can't alloc set option reply msg. "
576 "Disconnecting client connection.");
578 send_buffer_list_discard_new(&client
->send_buffer_list
, send_buffer
);
583 send_buffer_list_put(&client
->send_buffer_list
, send_buffer
);
589 qnetd_client_msg_received_echo_reply(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
590 const struct msg_decoded
*msg
)
593 return (qnetd_client_msg_received_unexpected_msg(client
, msg
, "echo reply"));
597 qnetd_client_msg_received_echo_request(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
598 const struct msg_decoded
*msg
, const struct dynar
*msg_orig
)
601 struct send_buffer_list_entry
*send_buffer
;
603 if ((res
= qnetd_client_msg_received_check_tls(instance
, client
, msg
)) != 0) {
604 return (res
== -1 ? -1 : 0);
607 if (!client
->init_received
) {
608 log(LOG_ERR
, "Received echo request before init message. "
609 "Sending error reply.");
611 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
612 TLV_REPLY_ERROR_CODE_INIT_REQUIRED
) != 0) {
619 send_buffer
= send_buffer_list_get_new(&client
->send_buffer_list
);
620 if (send_buffer
== NULL
) {
621 log(LOG_ERR
, "Can't alloc echo reply msg from list. "
622 "Disconnecting client connection.");
627 if (msg_create_echo_reply(&send_buffer
->buffer
, msg_orig
) == 0) {
628 log(LOG_ERR
, "Can't alloc echo reply msg. Disconnecting client connection.");
630 send_buffer_list_discard_new(&client
->send_buffer_list
, send_buffer
);
635 send_buffer_list_put(&client
->send_buffer_list
, send_buffer
);
641 qnetd_client_msg_received_node_list(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
642 const struct msg_decoded
*msg
)
645 struct send_buffer_list_entry
*send_buffer
;
646 enum tlv_reply_error_code reply_error_code
;
647 enum tlv_vote result_vote
;
650 reply_error_code
= TLV_REPLY_ERROR_CODE_NO_ERROR
;
652 if ((res
= qnetd_client_msg_received_check_tls(instance
, client
, msg
)) != 0) {
653 return (res
== -1 ? -1 : 0);
656 if (!client
->init_received
) {
657 log(LOG_ERR
, "Received node list message before init message. "
658 "Sending error reply.");
660 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
661 TLV_REPLY_ERROR_CODE_INIT_REQUIRED
) != 0) {
668 if (!msg
->node_list_type_set
) {
669 log(LOG_ERR
, "Received node list message without node list type set. "
670 "Sending error reply.");
672 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
673 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
) != 0) {
680 if (!msg
->seq_number_set
) {
681 log(LOG_ERR
, "Received node list message without seq number set. "
682 "Sending error reply.");
684 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
685 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
) != 0) {
692 result_vote
= TLV_VOTE_NO_CHANGE
;
695 switch (msg
->node_list_type
) {
696 case TLV_NODE_LIST_TYPE_INITIAL_CONFIG
:
697 case TLV_NODE_LIST_TYPE_CHANGED_CONFIG
:
699 qnetd_log_debug_config_node_list_received(client
, msg
->seq_number
,
700 msg
->config_version_set
, msg
->config_version
, &msg
->nodes
,
701 (msg
->node_list_type
== TLV_NODE_LIST_TYPE_INITIAL_CONFIG
));
703 reply_error_code
= qnetd_algorithm_config_node_list_received(client
,
704 msg
->seq_number
, msg
->config_version_set
, msg
->config_version
,
706 (msg
->node_list_type
== TLV_NODE_LIST_TYPE_INITIAL_CONFIG
),
709 case TLV_NODE_LIST_TYPE_MEMBERSHIP
:
711 if (!msg
->ring_id_set
) {
712 log(LOG_ERR
, "Received node list message without ring id number set. "
713 "Sending error reply.");
715 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
716 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
) != 0) {
723 qnetd_log_debug_membership_node_list_received(client
, msg
->seq_number
, &msg
->ring_id
,
724 msg
->heuristics
, &msg
->nodes
);
726 reply_error_code
= qnetd_algorithm_membership_node_list_received(client
,
727 msg
->seq_number
, &msg
->ring_id
, &msg
->nodes
, msg
->heuristics
, &result_vote
);
729 case TLV_NODE_LIST_TYPE_QUORUM
:
731 if (!msg
->quorate_set
) {
732 log(LOG_ERR
, "Received quorum list message without quorate set. "
733 "Sending error reply.");
735 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
736 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
) != 0) {
743 qnetd_log_debug_quorum_node_list_received(client
, msg
->seq_number
,msg
->quorate
,
746 reply_error_code
= qnetd_algorithm_quorum_node_list_received(client
,
747 msg
->seq_number
,msg
->quorate
, &msg
->nodes
, &result_vote
);
750 * Default is not defined intentionally. Compiler shows warning when new
751 * node list type is added
755 if (!case_processed
) {
756 log(LOG_ERR
, "qnetd_client_msg_received_node_list fatal error. "
757 "Unhandled node_list_type");
761 if (reply_error_code
!= TLV_REPLY_ERROR_CODE_NO_ERROR
) {
762 log(LOG_ERR
, "Algorithm returned error code. "
763 "Sending error reply.");
765 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
766 reply_error_code
) != 0) {
772 log(LOG_DEBUG
, "Algorithm result vote is %s", tlv_vote_to_str(result_vote
));
776 * Store node list for future use
779 switch (msg
->node_list_type
) {
780 case TLV_NODE_LIST_TYPE_INITIAL_CONFIG
:
781 case TLV_NODE_LIST_TYPE_CHANGED_CONFIG
:
783 node_list_free(&client
->configuration_node_list
);
784 if (node_list_clone(&client
->configuration_node_list
, &msg
->nodes
) == -1) {
785 log(LOG_ERR
, "Can't alloc config node list clone. "
786 "Disconnecting client connection.");
790 client
->config_version_set
= msg
->config_version_set
;
791 client
->config_version
= msg
->config_version
;
794 case TLV_NODE_LIST_TYPE_MEMBERSHIP
:
796 node_list_free(&client
->last_membership_node_list
);
797 if (node_list_clone(&client
->last_membership_node_list
, &msg
->nodes
) == -1) {
798 log(LOG_ERR
, "Can't alloc membership node list clone. "
799 "Disconnecting client connection.");
803 memcpy(&client
->last_ring_id
, &msg
->ring_id
, sizeof(struct tlv_ring_id
));
804 client
->last_membership_heuristics
= msg
->heuristics
;
805 client
->last_heuristics
= msg
->heuristics
;
807 case TLV_NODE_LIST_TYPE_QUORUM
:
809 node_list_free(&client
->last_quorum_node_list
);
810 if (node_list_clone(&client
->last_quorum_node_list
, &msg
->nodes
) == -1) {
811 log(LOG_ERR
, "Can't alloc quorum node list clone. "
812 "Disconnecting client connection.");
818 * Default is not defined intentionally. Compiler shows warning when new
819 * node list type is added
823 if (!case_processed
) {
824 log(LOG_ERR
, "qnetd_client_msg_received_node_list fatal error. "
825 "Unhandled node_list_type");
832 client
->last_sent_vote
= result_vote
;
833 if (result_vote
== TLV_VOTE_ACK
|| result_vote
== TLV_VOTE_NACK
) {
834 client
->last_sent_ack_nack_vote
= result_vote
;
837 send_buffer
= send_buffer_list_get_new(&client
->send_buffer_list
);
838 if (send_buffer
== NULL
) {
839 log(LOG_ERR
, "Can't alloc node list reply msg from list. "
840 "Disconnecting client connection.");
845 if (msg_create_node_list_reply(&send_buffer
->buffer
, msg
->seq_number
, msg
->node_list_type
,
846 &client
->last_ring_id
, result_vote
) == 0) {
847 log(LOG_ERR
, "Can't alloc node list reply msg. "
848 "Disconnecting client connection.");
850 send_buffer_list_discard_new(&client
->send_buffer_list
, send_buffer
);
855 send_buffer_list_put(&client
->send_buffer_list
, send_buffer
);
861 qnetd_client_msg_received_node_list_reply(struct qnetd_instance
*instance
,
862 struct qnetd_client
*client
, const struct msg_decoded
*msg
)
865 return (qnetd_client_msg_received_unexpected_msg(client
, msg
, "node list reply"));
869 qnetd_client_msg_received_ask_for_vote(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
870 const struct msg_decoded
*msg
)
873 struct send_buffer_list_entry
*send_buffer
;
874 enum tlv_reply_error_code reply_error_code
;
875 enum tlv_vote result_vote
;
877 reply_error_code
= TLV_REPLY_ERROR_CODE_NO_ERROR
;
879 if ((res
= qnetd_client_msg_received_check_tls(instance
, client
, msg
)) != 0) {
880 return (res
== -1 ? -1 : 0);
883 if (!client
->init_received
) {
884 log(LOG_ERR
, "Received ask for vote message before init message. "
885 "Sending error reply.");
887 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
888 TLV_REPLY_ERROR_CODE_INIT_REQUIRED
) != 0) {
895 if (!msg
->seq_number_set
) {
896 log(LOG_ERR
, "Received ask for vote message without seq number set. "
897 "Sending error reply.");
899 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
900 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
) != 0) {
907 qnetd_log_debug_ask_for_vote_received(client
, msg
->seq_number
);
909 reply_error_code
= qnetd_algorithm_ask_for_vote_received(client
, msg
->seq_number
,
912 if (reply_error_code
!= TLV_REPLY_ERROR_CODE_NO_ERROR
) {
913 log(LOG_ERR
, "Algorithm returned error code. "
914 "Sending error reply.");
916 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
917 reply_error_code
) != 0) {
923 log(LOG_DEBUG
, "Algorithm result vote is %s", tlv_vote_to_str(result_vote
));
929 client
->last_sent_vote
= result_vote
;
930 if (result_vote
== TLV_VOTE_ACK
|| result_vote
== TLV_VOTE_NACK
) {
931 client
->last_sent_ack_nack_vote
= result_vote
;
934 send_buffer
= send_buffer_list_get_new(&client
->send_buffer_list
);
935 if (send_buffer
== NULL
) {
936 log(LOG_ERR
, "Can't alloc ask for vote reply msg from list. "
937 "Disconnecting client connection.");
942 if (msg_create_ask_for_vote_reply(&send_buffer
->buffer
, msg
->seq_number
,
943 &client
->last_ring_id
, result_vote
) == 0) {
944 log(LOG_ERR
, "Can't alloc ask for vote reply msg. "
945 "Disconnecting client connection.");
947 send_buffer_list_discard_new(&client
->send_buffer_list
, send_buffer
);
952 send_buffer_list_put(&client
->send_buffer_list
, send_buffer
);
958 qnetd_client_msg_received_ask_for_vote_reply(struct qnetd_instance
*instance
,
959 struct qnetd_client
*client
, const struct msg_decoded
*msg
)
962 return (qnetd_client_msg_received_unexpected_msg(client
, msg
, "ask for vote reply"));
966 qnetd_client_msg_received_vote_info(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
967 const struct msg_decoded
*msg
)
970 return (qnetd_client_msg_received_unexpected_msg(client
, msg
, "vote info"));
974 qnetd_client_msg_received_vote_info_reply(struct qnetd_instance
*instance
,
975 struct qnetd_client
*client
, const struct msg_decoded
*msg
)
978 enum tlv_reply_error_code reply_error_code
;
980 reply_error_code
= TLV_REPLY_ERROR_CODE_NO_ERROR
;
982 if ((res
= qnetd_client_msg_received_check_tls(instance
, client
, msg
)) != 0) {
983 return (res
== -1 ? -1 : 0);
986 if (!client
->init_received
) {
987 log(LOG_ERR
, "Received vote info reply before init message. "
988 "Sending error reply.");
990 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
991 TLV_REPLY_ERROR_CODE_INIT_REQUIRED
) != 0) {
998 if (!msg
->seq_number_set
) {
999 log(LOG_ERR
, "Received vote info reply message without seq number set. "
1000 "Sending error reply.");
1002 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
1003 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
) != 0) {
1010 qnetd_log_debug_vote_info_reply_received(client
, msg
->seq_number
);
1012 reply_error_code
= qnetd_algorithm_vote_info_reply_received(client
, msg
->seq_number
);
1014 if (reply_error_code
!= TLV_REPLY_ERROR_CODE_NO_ERROR
) {
1015 log(LOG_ERR
, "Algorithm returned error code. "
1016 "Sending error reply.");
1018 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
1019 reply_error_code
) != 0) {
1030 qnetd_client_msg_received_heuristics_change(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
1031 const struct msg_decoded
*msg
)
1034 struct send_buffer_list_entry
*send_buffer
;
1035 enum tlv_reply_error_code reply_error_code
;
1036 enum tlv_vote result_vote
;
1038 reply_error_code
= TLV_REPLY_ERROR_CODE_NO_ERROR
;
1040 if ((res
= qnetd_client_msg_received_check_tls(instance
, client
, msg
)) != 0) {
1041 return (res
== -1 ? -1 : 0);
1044 if (!client
->init_received
) {
1045 log(LOG_ERR
, "Received heuristics change message before init message. "
1046 "Sending error reply.");
1048 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
1049 TLV_REPLY_ERROR_CODE_INIT_REQUIRED
) != 0) {
1056 if (!msg
->seq_number_set
|| msg
->heuristics
== TLV_HEURISTICS_UNDEFINED
) {
1057 log(LOG_ERR
, "Received heuristics change message without seq number set or "
1058 "with undefined heuristics. Sending error reply.");
1060 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
1061 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION
) != 0) {
1068 qnetd_log_debug_heuristics_change_received(client
, msg
->seq_number
, msg
->heuristics
);
1070 reply_error_code
= qnetd_algorithm_heuristics_change_received(client
, msg
->seq_number
,
1071 msg
->heuristics
, &result_vote
);
1073 if (reply_error_code
!= TLV_REPLY_ERROR_CODE_NO_ERROR
) {
1074 log(LOG_ERR
, "Algorithm returned error code. "
1075 "Sending error reply.");
1077 if (qnetd_client_send_err(client
, msg
->seq_number_set
, msg
->seq_number
,
1078 reply_error_code
) != 0) {
1084 log(LOG_DEBUG
, "Algorithm result vote is %s", tlv_vote_to_str(result_vote
));
1088 * Store result vote and heuristics result
1090 client
->last_sent_vote
= result_vote
;
1091 if (result_vote
== TLV_VOTE_ACK
|| result_vote
== TLV_VOTE_NACK
) {
1092 client
->last_sent_ack_nack_vote
= result_vote
;
1094 client
->last_regular_heuristics
= msg
->heuristics
;
1095 client
->last_heuristics
= msg
->heuristics
;
1097 send_buffer
= send_buffer_list_get_new(&client
->send_buffer_list
);
1098 if (send_buffer
== NULL
) {
1099 log(LOG_ERR
, "Can't alloc heuristics change reply msg from list. "
1100 "Disconnecting client connection.");
1105 if (msg_create_heuristics_change_reply(&send_buffer
->buffer
, msg
->seq_number
,
1106 &client
->last_ring_id
, msg
->heuristics
, result_vote
) == 0) {
1107 log(LOG_ERR
, "Can't alloc heuristics change reply msg. "
1108 "Disconnecting client connection.");
1110 send_buffer_list_discard_new(&client
->send_buffer_list
, send_buffer
);
1115 send_buffer_list_put(&client
->send_buffer_list
, send_buffer
);
1121 qnetd_client_msg_received_heuristics_change_reply(struct qnetd_instance
*instance
, struct qnetd_client
*client
,
1122 const struct msg_decoded
*msg
)
1125 return (qnetd_client_msg_received_unexpected_msg(client
, msg
, "heuristics change reply"));
1129 qnetd_client_msg_received(struct qnetd_instance
*instance
, struct qnetd_client
*client
)
1131 struct msg_decoded msg
;
1136 client
->dpd_msg_received_since_last_check
= 1;
1138 msg_decoded_init(&msg
);
1140 res
= msg_decode(&client
->receive_buffer
, &msg
);
1143 * Error occurred. Send server error.
1145 log_msg_decode_error(res
);
1146 log(LOG_INFO
, "Sending back error message");
1148 if (qnetd_client_send_err(client
, msg
.seq_number_set
, msg
.seq_number
,
1149 TLV_REPLY_ERROR_CODE_ERROR_DECODING_MSG
) != 0) {
1160 case MSG_TYPE_PREINIT
:
1162 ret_val
= qnetd_client_msg_received_preinit(instance
, client
, &msg
);
1164 case MSG_TYPE_PREINIT_REPLY
:
1166 ret_val
= qnetd_client_msg_received_preinit_reply(instance
, client
, &msg
);
1168 case MSG_TYPE_STARTTLS
:
1170 ret_val
= qnetd_client_msg_received_starttls(instance
, client
, &msg
);
1174 ret_val
= qnetd_client_msg_received_init(instance
, client
, &msg
);
1176 case MSG_TYPE_INIT_REPLY
:
1178 ret_val
= qnetd_client_msg_received_init_reply(instance
, client
, &msg
);
1180 case MSG_TYPE_SERVER_ERROR
:
1182 ret_val
= qnetd_client_msg_received_server_error(instance
, client
, &msg
);
1184 case MSG_TYPE_SET_OPTION
:
1186 ret_val
= qnetd_client_msg_received_set_option(instance
, client
, &msg
);
1188 case MSG_TYPE_SET_OPTION_REPLY
:
1190 ret_val
= qnetd_client_msg_received_set_option_reply(instance
, client
, &msg
);
1192 case MSG_TYPE_ECHO_REQUEST
:
1194 ret_val
= qnetd_client_msg_received_echo_request(instance
, client
, &msg
,
1195 &client
->receive_buffer
);
1197 case MSG_TYPE_ECHO_REPLY
:
1199 ret_val
= qnetd_client_msg_received_echo_reply(instance
, client
, &msg
);
1201 case MSG_TYPE_NODE_LIST
:
1203 ret_val
= qnetd_client_msg_received_node_list(instance
, client
, &msg
);
1205 case MSG_TYPE_NODE_LIST_REPLY
:
1207 ret_val
= qnetd_client_msg_received_node_list_reply(instance
, client
, &msg
);
1209 case MSG_TYPE_ASK_FOR_VOTE
:
1211 ret_val
= qnetd_client_msg_received_ask_for_vote(instance
, client
, &msg
);
1213 case MSG_TYPE_ASK_FOR_VOTE_REPLY
:
1215 ret_val
= qnetd_client_msg_received_ask_for_vote_reply(instance
, client
, &msg
);
1217 case MSG_TYPE_VOTE_INFO
:
1219 ret_val
= qnetd_client_msg_received_vote_info(instance
, client
, &msg
);
1221 case MSG_TYPE_VOTE_INFO_REPLY
:
1223 ret_val
= qnetd_client_msg_received_vote_info_reply(instance
, client
, &msg
);
1225 case MSG_TYPE_HEURISTICS_CHANGE
:
1227 ret_val
= qnetd_client_msg_received_heuristics_change(instance
, client
, &msg
);
1229 case MSG_TYPE_HEURISTICS_CHANGE_REPLY
:
1231 ret_val
= qnetd_client_msg_received_heuristics_change_reply(instance
, client
,
1235 * Default is not defined intentionally. Compiler shows warning when new
1236 * msg type is added.
1240 if (!msg_processed
) {
1241 log(LOG_ERR
, "Unsupported message %u received from client. "
1242 "Sending back error message", msg
.type
);
1244 if (qnetd_client_send_err(client
, msg
.seq_number_set
, msg
.seq_number
,
1245 TLV_REPLY_ERROR_CODE_UNSUPPORTED_MESSAGE
) != 0) {
1250 msg_decoded_destroy(&msg
);