]> git.proxmox.com Git - mirror_corosync-qdevice.git/blob - qdevices/qnetd-client-msg-received.c
1cc176328619cef8cdd52f41f70be5b108b4866e
[mirror_corosync-qdevice.git] / qdevices / qnetd-client-msg-received.c
1 /*
2 * Copyright (c) 2015-2019 Red Hat, Inc.
3 *
4 * All rights reserved.
5 *
6 * Author: Jan Friesse (jfriesse@redhat.com)
7 *
8 * This software licensed under BSD license, the text of which follows:
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
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.
21 *
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.
33 */
34
35 #include <sys/types.h>
36
37 #include "log.h"
38 #include "qnetd-algorithm.h"
39 #include "qnetd-instance.h"
40 #include "qnetd-log-debug.h"
41 #include "qnetd-client-send.h"
42 #include "msg.h"
43 #include "nss-sock.h"
44
45 #include "qnetd-client-msg-received.h"
46
47 /*
48 * 0 - Success
49 * -1 - Disconnect client
50 * -2 - Error reply sent, but no need to disconnect client
51 */
52 static int
53 qnetd_client_msg_received_check_tls(struct qnetd_instance *instance, struct qnetd_client *client,
54 const struct msg_decoded *msg)
55 {
56 int check_certificate;
57 int tls_required;
58 CERTCertificate *peer_cert;
59 int case_processed;
60
61 check_certificate = 0;
62 tls_required = 0;
63
64 case_processed = 0;
65
66 switch (instance->tls_supported) {
67 case TLV_TLS_UNSUPPORTED:
68 case_processed = 1;
69 tls_required = 0;
70 check_certificate = 0;
71 break;
72 case TLV_TLS_SUPPORTED:
73 case_processed = 1;
74 tls_required = 0;
75
76 if (client->tls_started && instance->tls_client_cert_required &&
77 !client->tls_peer_certificate_verified) {
78 check_certificate = 1;
79 }
80 break;
81 case TLV_TLS_REQUIRED:
82 case_processed = 1;
83 tls_required = 1;
84
85 if (instance->tls_client_cert_required && !client->tls_peer_certificate_verified) {
86 check_certificate = 1;
87 }
88 break;
89 /*
90 * Default is not defined intentionally. Compiler shows warning when new
91 * tls supported is added
92 */
93 }
94
95 if (!case_processed) {
96 log(LOG_ERR, "Unhandled instance tls supported %u", instance->tls_supported);
97 exit(1);
98 }
99
100 if (tls_required && !client->tls_started) {
101 log(LOG_ERR, "TLS is required but doesn't started yet. "
102 "Sending back error message");
103
104 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
105 TLV_REPLY_ERROR_CODE_TLS_REQUIRED) != 0) {
106 return (-1);
107 }
108
109 return (-2);
110 }
111
112 if (check_certificate) {
113 peer_cert = SSL_PeerCertificate(client->socket);
114
115 if (peer_cert == NULL) {
116 log(LOG_ERR, "Client doesn't sent valid certificate. "
117 "Disconnecting client");
118
119 return (-1);
120 }
121
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");
125
126 CERT_DestroyCertificate(peer_cert);
127
128 return (-1);
129 }
130
131 CERT_DestroyCertificate(peer_cert);
132
133 client->tls_peer_certificate_verified = 1;
134 }
135
136 return (0);
137 }
138
139 static int
140 qnetd_client_msg_received_preinit(struct qnetd_instance *instance, struct qnetd_client *client,
141 const struct msg_decoded *msg)
142 {
143 struct send_buffer_list_entry *send_buffer;
144
145 if (msg->cluster_name == NULL) {
146 log(LOG_ERR, "Received preinit message without cluster name. "
147 "Sending error reply.");
148
149 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
150 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
151 return (-1);
152 }
153
154 return (0);
155 }
156
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.");
160
161 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
162 TLV_REPLY_ERROR_CODE_INTERNAL_ERROR) != 0) {
163 return (-1);
164 }
165
166 return (0);
167 }
168 memset(client->cluster_name, 0, msg->cluster_name_len + 1);
169 memcpy(client->cluster_name, msg->cluster_name, msg->cluster_name_len);
170
171 client->cluster_name_len = msg->cluster_name_len;
172 client->preinit_received = 1;
173
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.");
178
179 return (-1);
180 }
181
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.");
186
187 send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
188
189 return (-1);
190 };
191
192 send_buffer_list_put(&client->send_buffer_list, send_buffer);
193
194 return (0);
195 }
196
197 static int
198 qnetd_client_msg_received_unexpected_msg(struct qnetd_client *client,
199 const struct msg_decoded *msg, const char *msg_str)
200 {
201
202 log(LOG_ERR, "Received %s message. Sending back error message", msg_str);
203
204 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
205 TLV_REPLY_ERROR_CODE_UNEXPECTED_MESSAGE) != 0) {
206 return (-1);
207 }
208
209 return (0);
210 }
211
212 static int
213 qnetd_client_msg_received_preinit_reply(struct qnetd_instance *instance,
214 struct qnetd_client *client, const struct msg_decoded *msg)
215 {
216
217 return (qnetd_client_msg_received_unexpected_msg(client, msg, "preinit reply"));
218 }
219
220 static int
221 qnetd_client_msg_received_starttls(struct qnetd_instance *instance, struct qnetd_client *client,
222 const struct msg_decoded *msg)
223 {
224 PRFileDesc *new_pr_fd;
225
226 if (!client->preinit_received) {
227 log(LOG_ERR, "Received starttls before preinit message. "
228 "Sending error reply.");
229
230 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
231 TLV_REPLY_ERROR_CODE_PREINIT_REQUIRED) != 0) {
232 return (-1);
233 }
234
235 return (0);
236 }
237
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.");
241
242 return (-1);
243 }
244
245 client->tls_started = 1;
246 client->tls_peer_certificate_verified = 0;
247 client->socket = new_pr_fd;
248
249 return (0);
250 }
251
252 static int
253 qnetd_client_msg_received_server_error(struct qnetd_instance *instance, struct qnetd_client *client,
254 const struct msg_decoded *msg)
255 {
256
257 return (qnetd_client_msg_received_unexpected_msg(client, msg, "server error"));
258 }
259
260 /*
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
265 */
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)
269 {
270 struct qnetd_cluster *cluster;
271 struct qnetd_client *client;
272
273 cluster = qnetd_cluster_list_find_by_name(&instance->clusters, new_client->cluster_name,
274 new_client->cluster_name_len);
275
276 if (cluster == NULL) {
277 return (TLV_REPLY_ERROR_CODE_NO_ERROR);
278 }
279
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");
284
285 return (TLV_REPLY_ERROR_CODE_TIE_BREAKER_DIFFERS_FROM_OTHER_NODES);
286 }
287
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");
291
292 return (TLV_REPLY_ERROR_CODE_ALGORITHM_DIFFERS_FROM_OTHER_NODES);
293 }
294
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");
298
299 return (TLV_REPLY_ERROR_CODE_DUPLICATE_NODE_ID);
300 }
301 }
302
303 return (TLV_REPLY_ERROR_CODE_NO_ERROR);
304 }
305
306 static int
307 qnetd_client_msg_received_init(struct qnetd_instance *instance, struct qnetd_client *client,
308 const struct msg_decoded *msg)
309 {
310 int res;
311 size_t zi;
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;
319
320 supported_msgs = NULL;
321 supported_opts = NULL;
322 no_supported_msgs = 0;
323 no_supported_opts = 0;
324
325 reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
326
327 if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
328 return (res == -1 ? -1 : 0);
329 }
330
331 if (!client->preinit_received) {
332 log(LOG_ERR, "Received init before preinit message. Sending error reply.");
333
334 reply_error_code = TLV_REPLY_ERROR_CODE_PREINIT_REQUIRED;
335 }
336
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.");
340
341 reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
342 } else {
343 client->node_id_set = 1;
344 client->node_id = msg->node_id;
345 }
346
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.");
350
351 reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
352 } else {
353 memcpy(&client->last_ring_id, &msg->ring_id, sizeof(struct tlv_ring_id));
354 }
355
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.");
359
360 reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
361 } else {
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);
366
367 reply_error_code = TLV_REPLY_ERROR_CODE_INVALID_HEARTBEAT_INTERVAL;
368 } else {
369 client->heartbeat_interval = msg->heartbeat_interval;
370 }
371 }
372
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.");
376
377 reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
378 } else {
379 memcpy(&client->tie_breaker, &msg->tie_breaker, sizeof(msg->tie_breaker));
380 }
381
382 if (msg->supported_messages != NULL) {
383 /*
384 * Client sent supported messages. For now this is ignored but in the future
385 * this may be used to ensure backward compatibility.
386 */
387 /*
388 for (i = 0; i < msg->no_supported_messages; i++) {
389 log(LOG_DEBUG, "Client supports %u message",
390 (int)msg->supported_messages[i]);
391 }
392 */
393
394 /*
395 * Sent back supported messages
396 */
397 msg_get_supported_messages(&supported_msgs, &no_supported_msgs);
398 }
399
400 if (msg->supported_options != NULL) {
401 /*
402 * Client sent supported options. For now this is ignored but in the future
403 * this may be used to ensure backward compatibility.
404 */
405 /*
406 for (i = 0; i < msg->no_supported_options; i++) {
407 log(LOG_DEBUG, "Client supports %u option",
408 (int)msg->supported_messages[i]);
409 }
410 */
411
412 /*
413 * Send back supported options
414 */
415 tlv_get_supported_options(&supported_opts, &no_supported_opts);
416 }
417
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.");
421
422 reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
423 } else {
424 /*
425 * Check if decision algorithm requested by client is supported
426 */
427 res = 0;
428
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) {
432 res = 1;
433 }
434 }
435
436 if (!res) {
437 log(LOG_ERR, "Client requested unsupported decision algorithm %u. "
438 "Sending error reply.", msg->decision_algorithm);
439
440 reply_error_code = TLV_REPLY_ERROR_CODE_UNSUPPORTED_DECISION_ALGORITHM;
441 }
442
443 client->decision_algorithm = msg->decision_algorithm;
444 }
445
446 if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR) {
447 reply_error_code = qnetd_client_msg_received_init_check_new_client(instance,
448 client);
449 }
450
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.");
456
457 reply_error_code = TLV_REPLY_ERROR_CODE_INTERNAL_ERROR;
458 } else {
459 client->cluster = cluster;
460 client->cluster_list = &instance->clusters;
461 }
462 }
463
464 if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR) {
465 qnetd_log_debug_new_client_connected(client);
466
467 reply_error_code = qnetd_algorithm_client_init(client);
468 }
469
470 if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR) {
471 /*
472 * Correct init received
473 */
474 client->init_received = 1;
475 } else {
476 log(LOG_ERR, "Algorithm returned error code. Sending error reply.");
477 }
478
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.");
483
484 return (-1);
485 }
486
487 if (msg_create_init_reply(&send_buffer->buffer, msg->seq_number_set, msg->seq_number,
488 reply_error_code,
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.");
495
496 send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
497
498 return (-1);
499 }
500
501 send_buffer_list_put(&client->send_buffer_list, send_buffer);
502
503 return (0);
504 }
505
506 static int
507 qnetd_client_msg_received_init_reply(struct qnetd_instance *instance, struct qnetd_client *client,
508 const struct msg_decoded *msg)
509 {
510
511 return (qnetd_client_msg_received_unexpected_msg(client, msg, "init reply"));
512 }
513
514 static int
515 qnetd_client_msg_received_set_option_reply(struct qnetd_instance *instance,
516 struct qnetd_client *client, const struct msg_decoded *msg)
517 {
518
519 return (qnetd_client_msg_received_unexpected_msg(client, msg, "set option reply"));
520 }
521
522 static int
523 qnetd_client_msg_received_set_option(struct qnetd_instance *instance, struct qnetd_client *client,
524 const struct msg_decoded *msg)
525 {
526 int res;
527 struct send_buffer_list_entry *send_buffer;
528
529 if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
530 return (res == -1 ? -1 : 0);
531 }
532
533 if (!client->init_received) {
534 log(LOG_ERR, "Received set option message before init message. "
535 "Sending error reply.");
536
537 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
538 TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
539 return (-1);
540 }
541
542 return (0);
543 }
544
545 if (msg->heartbeat_interval_set) {
546 /*
547 * Check if heartbeat interval is valid
548 */
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);
553
554 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
555 TLV_REPLY_ERROR_CODE_INVALID_HEARTBEAT_INTERVAL) != 0) {
556 return (-1);
557 }
558
559 return (0);
560 }
561
562 client->heartbeat_interval = msg->heartbeat_interval;
563 }
564
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.");
569
570 return (-1);
571 }
572
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.");
577
578 send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
579
580 return (-1);
581 }
582
583 send_buffer_list_put(&client->send_buffer_list, send_buffer);
584
585 return (0);
586 }
587
588 static int
589 qnetd_client_msg_received_echo_reply(struct qnetd_instance *instance, struct qnetd_client *client,
590 const struct msg_decoded *msg)
591 {
592
593 return (qnetd_client_msg_received_unexpected_msg(client, msg, "echo reply"));
594 }
595
596 static int
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)
599 {
600 int res;
601 struct send_buffer_list_entry *send_buffer;
602
603 if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
604 return (res == -1 ? -1 : 0);
605 }
606
607 if (!client->init_received) {
608 log(LOG_ERR, "Received echo request before init message. "
609 "Sending error reply.");
610
611 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
612 TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
613 return (-1);
614 }
615
616 return (0);
617 }
618
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.");
623
624 return (-1);
625 }
626
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.");
629
630 send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
631
632 return (-1);
633 }
634
635 send_buffer_list_put(&client->send_buffer_list, send_buffer);
636
637 return (0);
638 }
639
640 static int
641 qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnetd_client *client,
642 const struct msg_decoded *msg)
643 {
644 int res;
645 struct send_buffer_list_entry *send_buffer;
646 enum tlv_reply_error_code reply_error_code;
647 enum tlv_vote result_vote;
648 int case_processed;
649
650 reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
651
652 if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
653 return (res == -1 ? -1 : 0);
654 }
655
656 if (!client->init_received) {
657 log(LOG_ERR, "Received node list message before init message. "
658 "Sending error reply.");
659
660 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
661 TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
662 return (-1);
663 }
664
665 return (0);
666 }
667
668 if (!msg->node_list_type_set) {
669 log(LOG_ERR, "Received node list message without node list type set. "
670 "Sending error reply.");
671
672 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
673 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
674 return (-1);
675 }
676
677 return (0);
678 }
679
680 if (!msg->seq_number_set) {
681 log(LOG_ERR, "Received node list message without seq number set. "
682 "Sending error reply.");
683
684 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
685 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
686 return (-1);
687 }
688
689 return (0);
690 }
691
692 result_vote = TLV_VOTE_NO_CHANGE;
693
694 case_processed = 0;
695 switch (msg->node_list_type) {
696 case TLV_NODE_LIST_TYPE_INITIAL_CONFIG:
697 case TLV_NODE_LIST_TYPE_CHANGED_CONFIG:
698 case_processed = 1;
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));
702
703 reply_error_code = qnetd_algorithm_config_node_list_received(client,
704 msg->seq_number, msg->config_version_set, msg->config_version,
705 &msg->nodes,
706 (msg->node_list_type == TLV_NODE_LIST_TYPE_INITIAL_CONFIG),
707 &result_vote);
708 break;
709 case TLV_NODE_LIST_TYPE_MEMBERSHIP:
710 case_processed = 1;
711 if (!msg->ring_id_set) {
712 log(LOG_ERR, "Received node list message without ring id number set. "
713 "Sending error reply.");
714
715 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
716 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
717 return (-1);
718 }
719
720 return (0);
721 }
722
723 qnetd_log_debug_membership_node_list_received(client, msg->seq_number, &msg->ring_id,
724 msg->heuristics, &msg->nodes);
725
726 reply_error_code = qnetd_algorithm_membership_node_list_received(client,
727 msg->seq_number, &msg->ring_id, &msg->nodes, msg->heuristics, &result_vote);
728 break;
729 case TLV_NODE_LIST_TYPE_QUORUM:
730 case_processed = 1;
731 if (!msg->quorate_set) {
732 log(LOG_ERR, "Received quorum list message without quorate set. "
733 "Sending error reply.");
734
735 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
736 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
737 return (-1);
738 }
739
740 return (0);
741 }
742
743 qnetd_log_debug_quorum_node_list_received(client, msg->seq_number,msg->quorate,
744 &msg->nodes);
745
746 reply_error_code = qnetd_algorithm_quorum_node_list_received(client,
747 msg->seq_number,msg->quorate, &msg->nodes, &result_vote);
748 break;
749 /*
750 * Default is not defined intentionally. Compiler shows warning when new
751 * node list type is added
752 */
753 }
754
755 if (!case_processed) {
756 log(LOG_ERR, "qnetd_client_msg_received_node_list fatal error. "
757 "Unhandled node_list_type");
758 exit(1);
759 }
760
761 if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
762 log(LOG_ERR, "Algorithm returned error code. "
763 "Sending error reply.");
764
765 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
766 reply_error_code) != 0) {
767 return (-1);
768 }
769
770 return (0);
771 } else {
772 log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
773 }
774
775 /*
776 * Store node list for future use
777 */
778 case_processed = 0;
779 switch (msg->node_list_type) {
780 case TLV_NODE_LIST_TYPE_INITIAL_CONFIG:
781 case TLV_NODE_LIST_TYPE_CHANGED_CONFIG:
782 case_processed = 1;
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.");
787
788 return (-1);
789 }
790 client->config_version_set = msg->config_version_set;
791 client->config_version = msg->config_version;
792
793 break;
794 case TLV_NODE_LIST_TYPE_MEMBERSHIP:
795 case_processed = 1;
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.");
800
801 return (-1);
802 }
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;
806 break;
807 case TLV_NODE_LIST_TYPE_QUORUM:
808 case_processed = 1;
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.");
813
814 return (-1);
815 }
816 break;
817 /*
818 * Default is not defined intentionally. Compiler shows warning when new
819 * node list type is added
820 */
821 }
822
823 if (!case_processed) {
824 log(LOG_ERR, "qnetd_client_msg_received_node_list fatal error. "
825 "Unhandled node_list_type");
826 exit(1);
827 }
828
829 /*
830 * Store result vote
831 */
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;
835 }
836
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.");
841
842 return (-1);
843 }
844
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.");
849
850 send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
851
852 return (-1);
853 }
854
855 send_buffer_list_put(&client->send_buffer_list, send_buffer);
856
857 return (0);
858 }
859
860 static int
861 qnetd_client_msg_received_node_list_reply(struct qnetd_instance *instance,
862 struct qnetd_client *client, const struct msg_decoded *msg)
863 {
864
865 return (qnetd_client_msg_received_unexpected_msg(client, msg, "node list reply"));
866 }
867
868 static int
869 qnetd_client_msg_received_ask_for_vote(struct qnetd_instance *instance, struct qnetd_client *client,
870 const struct msg_decoded *msg)
871 {
872 int res;
873 struct send_buffer_list_entry *send_buffer;
874 enum tlv_reply_error_code reply_error_code;
875 enum tlv_vote result_vote;
876
877 reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
878
879 if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
880 return (res == -1 ? -1 : 0);
881 }
882
883 if (!client->init_received) {
884 log(LOG_ERR, "Received ask for vote message before init message. "
885 "Sending error reply.");
886
887 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
888 TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
889 return (-1);
890 }
891
892 return (0);
893 }
894
895 if (!msg->seq_number_set) {
896 log(LOG_ERR, "Received ask for vote message without seq number set. "
897 "Sending error reply.");
898
899 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
900 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
901 return (-1);
902 }
903
904 return (0);
905 }
906
907 qnetd_log_debug_ask_for_vote_received(client, msg->seq_number);
908
909 reply_error_code = qnetd_algorithm_ask_for_vote_received(client, msg->seq_number,
910 &result_vote);
911
912 if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
913 log(LOG_ERR, "Algorithm returned error code. "
914 "Sending error reply.");
915
916 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
917 reply_error_code) != 0) {
918 return (-1);
919 }
920
921 return (0);
922 } else {
923 log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
924 }
925
926 /*
927 * Store result vote
928 */
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;
932 }
933
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.");
938
939 return (-1);
940 }
941
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.");
946
947 send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
948
949 return (-1);
950 }
951
952 send_buffer_list_put(&client->send_buffer_list, send_buffer);
953
954 return (0);
955 }
956
957 static int
958 qnetd_client_msg_received_ask_for_vote_reply(struct qnetd_instance *instance,
959 struct qnetd_client *client, const struct msg_decoded *msg)
960 {
961
962 return (qnetd_client_msg_received_unexpected_msg(client, msg, "ask for vote reply"));
963 }
964
965 static int
966 qnetd_client_msg_received_vote_info(struct qnetd_instance *instance, struct qnetd_client *client,
967 const struct msg_decoded *msg)
968 {
969
970 return (qnetd_client_msg_received_unexpected_msg(client, msg, "vote info"));
971 }
972
973 static int
974 qnetd_client_msg_received_vote_info_reply(struct qnetd_instance *instance,
975 struct qnetd_client *client, const struct msg_decoded *msg)
976 {
977 int res;
978 enum tlv_reply_error_code reply_error_code;
979
980 reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
981
982 if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
983 return (res == -1 ? -1 : 0);
984 }
985
986 if (!client->init_received) {
987 log(LOG_ERR, "Received vote info reply before init message. "
988 "Sending error reply.");
989
990 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
991 TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
992 return (-1);
993 }
994
995 return (0);
996 }
997
998 if (!msg->seq_number_set) {
999 log(LOG_ERR, "Received vote info reply message without seq number set. "
1000 "Sending error reply.");
1001
1002 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
1003 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
1004 return (-1);
1005 }
1006
1007 return (0);
1008 }
1009
1010 qnetd_log_debug_vote_info_reply_received(client, msg->seq_number);
1011
1012 reply_error_code = qnetd_algorithm_vote_info_reply_received(client, msg->seq_number);
1013
1014 if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
1015 log(LOG_ERR, "Algorithm returned error code. "
1016 "Sending error reply.");
1017
1018 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
1019 reply_error_code) != 0) {
1020 return (-1);
1021 }
1022
1023 return (0);
1024 }
1025
1026 return (0);
1027 }
1028
1029 static int
1030 qnetd_client_msg_received_heuristics_change(struct qnetd_instance *instance, struct qnetd_client *client,
1031 const struct msg_decoded *msg)
1032 {
1033 int res;
1034 struct send_buffer_list_entry *send_buffer;
1035 enum tlv_reply_error_code reply_error_code;
1036 enum tlv_vote result_vote;
1037
1038 reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
1039
1040 if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
1041 return (res == -1 ? -1 : 0);
1042 }
1043
1044 if (!client->init_received) {
1045 log(LOG_ERR, "Received heuristics change message before init message. "
1046 "Sending error reply.");
1047
1048 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
1049 TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
1050 return (-1);
1051 }
1052
1053 return (0);
1054 }
1055
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.");
1059
1060 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
1061 TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
1062 return (-1);
1063 }
1064
1065 return (0);
1066 }
1067
1068 qnetd_log_debug_heuristics_change_received(client, msg->seq_number, msg->heuristics);
1069
1070 reply_error_code = qnetd_algorithm_heuristics_change_received(client, msg->seq_number,
1071 msg->heuristics, &result_vote);
1072
1073 if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
1074 log(LOG_ERR, "Algorithm returned error code. "
1075 "Sending error reply.");
1076
1077 if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
1078 reply_error_code) != 0) {
1079 return (-1);
1080 }
1081
1082 return (0);
1083 } else {
1084 log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
1085 }
1086
1087 /*
1088 * Store result vote and heuristics result
1089 */
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;
1093 }
1094 client->last_regular_heuristics = msg->heuristics;
1095 client->last_heuristics = msg->heuristics;
1096
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.");
1101
1102 return (-1);
1103 }
1104
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.");
1109
1110 send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
1111
1112 return (-1);
1113 }
1114
1115 send_buffer_list_put(&client->send_buffer_list, send_buffer);
1116
1117 return (0);
1118 }
1119
1120 static int
1121 qnetd_client_msg_received_heuristics_change_reply(struct qnetd_instance *instance, struct qnetd_client *client,
1122 const struct msg_decoded *msg)
1123 {
1124
1125 return (qnetd_client_msg_received_unexpected_msg(client, msg, "heuristics change reply"));
1126 }
1127
1128 int
1129 qnetd_client_msg_received(struct qnetd_instance *instance, struct qnetd_client *client)
1130 {
1131 struct msg_decoded msg;
1132 int res;
1133 int ret_val;
1134 int msg_processed;
1135
1136 client->dpd_msg_received_since_last_check = 1;
1137
1138 msg_decoded_init(&msg);
1139
1140 res = msg_decode(&client->receive_buffer, &msg);
1141 if (res != 0) {
1142 /*
1143 * Error occurred. Send server error.
1144 */
1145 log_msg_decode_error(res);
1146 log(LOG_INFO, "Sending back error message");
1147
1148 if (qnetd_client_send_err(client, msg.seq_number_set, msg.seq_number,
1149 TLV_REPLY_ERROR_CODE_ERROR_DECODING_MSG) != 0) {
1150 return (-1);
1151 }
1152
1153 return (0);
1154 }
1155
1156 ret_val = 0;
1157
1158 msg_processed = 0;
1159 switch (msg.type) {
1160 case MSG_TYPE_PREINIT:
1161 msg_processed = 1;
1162 ret_val = qnetd_client_msg_received_preinit(instance, client, &msg);
1163 break;
1164 case MSG_TYPE_PREINIT_REPLY:
1165 msg_processed = 1;
1166 ret_val = qnetd_client_msg_received_preinit_reply(instance, client, &msg);
1167 break;
1168 case MSG_TYPE_STARTTLS:
1169 msg_processed = 1;
1170 ret_val = qnetd_client_msg_received_starttls(instance, client, &msg);
1171 break;
1172 case MSG_TYPE_INIT:
1173 msg_processed = 1;
1174 ret_val = qnetd_client_msg_received_init(instance, client, &msg);
1175 break;
1176 case MSG_TYPE_INIT_REPLY:
1177 msg_processed = 1;
1178 ret_val = qnetd_client_msg_received_init_reply(instance, client, &msg);
1179 break;
1180 case MSG_TYPE_SERVER_ERROR:
1181 msg_processed = 1;
1182 ret_val = qnetd_client_msg_received_server_error(instance, client, &msg);
1183 break;
1184 case MSG_TYPE_SET_OPTION:
1185 msg_processed = 1;
1186 ret_val = qnetd_client_msg_received_set_option(instance, client, &msg);
1187 break;
1188 case MSG_TYPE_SET_OPTION_REPLY:
1189 msg_processed = 1;
1190 ret_val = qnetd_client_msg_received_set_option_reply(instance, client, &msg);
1191 break;
1192 case MSG_TYPE_ECHO_REQUEST:
1193 msg_processed = 1;
1194 ret_val = qnetd_client_msg_received_echo_request(instance, client, &msg,
1195 &client->receive_buffer);
1196 break;
1197 case MSG_TYPE_ECHO_REPLY:
1198 msg_processed = 1;
1199 ret_val = qnetd_client_msg_received_echo_reply(instance, client, &msg);
1200 break;
1201 case MSG_TYPE_NODE_LIST:
1202 msg_processed = 1;
1203 ret_val = qnetd_client_msg_received_node_list(instance, client, &msg);
1204 break;
1205 case MSG_TYPE_NODE_LIST_REPLY:
1206 msg_processed = 1;
1207 ret_val = qnetd_client_msg_received_node_list_reply(instance, client, &msg);
1208 break;
1209 case MSG_TYPE_ASK_FOR_VOTE:
1210 msg_processed = 1;
1211 ret_val = qnetd_client_msg_received_ask_for_vote(instance, client, &msg);
1212 break;
1213 case MSG_TYPE_ASK_FOR_VOTE_REPLY:
1214 msg_processed = 1;
1215 ret_val = qnetd_client_msg_received_ask_for_vote_reply(instance, client, &msg);
1216 break;
1217 case MSG_TYPE_VOTE_INFO:
1218 msg_processed = 1;
1219 ret_val = qnetd_client_msg_received_vote_info(instance, client, &msg);
1220 break;
1221 case MSG_TYPE_VOTE_INFO_REPLY:
1222 msg_processed = 1;
1223 ret_val = qnetd_client_msg_received_vote_info_reply(instance, client, &msg);
1224 break;
1225 case MSG_TYPE_HEURISTICS_CHANGE:
1226 msg_processed = 1;
1227 ret_val = qnetd_client_msg_received_heuristics_change(instance, client, &msg);
1228 break;
1229 case MSG_TYPE_HEURISTICS_CHANGE_REPLY:
1230 msg_processed = 1;
1231 ret_val = qnetd_client_msg_received_heuristics_change_reply(instance, client,
1232 &msg);
1233 break;
1234 /*
1235 * Default is not defined intentionally. Compiler shows warning when new
1236 * msg type is added.
1237 */
1238 }
1239
1240 if (!msg_processed) {
1241 log(LOG_ERR, "Unsupported message %u received from client. "
1242 "Sending back error message", msg.type);
1243
1244 if (qnetd_client_send_err(client, msg.seq_number_set, msg.seq_number,
1245 TLV_REPLY_ERROR_CODE_UNSUPPORTED_MESSAGE) != 0) {
1246 ret_val = -1;
1247 }
1248 }
1249
1250 msg_decoded_destroy(&msg);
1251
1252 return (ret_val);
1253 }