1 /*
2  * Copyright (c) 2015-2017 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 "qnetd-algorithm.h"
38 #include "qnetd-instance.h"
39 #include "qnetd-log.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
qnetd_client_msg_received_check_tls(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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 		qnetd_log(LOG_ERR, "Unhandled instance tls supported %u", instance->tls_supported);
97 		exit(1);
98 	}
99 
100 	if (tls_required && !client->tls_started) {
101 		qnetd_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 			qnetd_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 			qnetd_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
qnetd_client_msg_received_preinit(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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 		qnetd_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 		qnetd_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 		qnetd_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 		qnetd_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
qnetd_client_msg_received_unexpected_msg(struct qnetd_client * client,const struct msg_decoded * msg,const char * msg_str)198 qnetd_client_msg_received_unexpected_msg(struct qnetd_client *client,
199     const struct msg_decoded *msg, const char *msg_str)
200 {
201 
202 	qnetd_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
qnetd_client_msg_received_preinit_reply(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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
qnetd_client_msg_received_starttls(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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 		qnetd_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 		qnetd_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
qnetd_client_msg_received_server_error(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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
qnetd_client_msg_received_init_check_new_client(struct qnetd_instance * instance,struct qnetd_client * new_client)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 			qnetd_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 			qnetd_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 			qnetd_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
qnetd_client_msg_received_init(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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 		qnetd_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 		qnetd_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 		qnetd_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 		qnetd_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 			qnetd_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 		qnetd_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 			qnetd_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 			qnetd_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 		qnetd_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 			qnetd_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 			qnetd_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 		qnetd_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 		qnetd_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 		qnetd_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
qnetd_client_msg_received_init_reply(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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
qnetd_client_msg_received_set_option_reply(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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
qnetd_client_msg_received_set_option(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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 		qnetd_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 			qnetd_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 		qnetd_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 		qnetd_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
qnetd_client_msg_received_echo_reply(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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
qnetd_client_msg_received_echo_request(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg,const struct dynar * msg_orig)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 		qnetd_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 		qnetd_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 		qnetd_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
qnetd_client_msg_received_node_list(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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 		qnetd_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 		qnetd_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 		qnetd_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 			qnetd_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 			qnetd_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 		qnetd_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 		qnetd_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 		qnetd_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 			qnetd_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 			qnetd_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 			qnetd_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 		qnetd_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 		qnetd_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 		qnetd_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
qnetd_client_msg_received_node_list_reply(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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
qnetd_client_msg_received_ask_for_vote(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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 		qnetd_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 		qnetd_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 		qnetd_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 		qnetd_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 		qnetd_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 		qnetd_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
qnetd_client_msg_received_ask_for_vote_reply(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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
qnetd_client_msg_received_vote_info(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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
qnetd_client_msg_received_vote_info_reply(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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 		qnetd_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 		qnetd_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 		qnetd_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
qnetd_client_msg_received_heuristics_change(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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 		qnetd_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 		qnetd_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 		qnetd_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 		qnetd_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 		qnetd_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 		qnetd_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
qnetd_client_msg_received_heuristics_change_reply(struct qnetd_instance * instance,struct qnetd_client * client,const struct msg_decoded * msg)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
qnetd_client_msg_received(struct qnetd_instance * instance,struct qnetd_client * client)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 		qnetd_log_msg_decode_error(res);
1146 		qnetd_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 		qnetd_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 }
1254