qnetd-client-msg-received.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262
  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. #include <sys/types.h>
  35. #include "log.h"
  36. #include "log-common.h"
  37. #include "qnetd-algorithm.h"
  38. #include "qnetd-instance.h"
  39. #include "qnetd-log-debug.h"
  40. #include "qnetd-client-send.h"
  41. #include "msg.h"
  42. #include "nss-sock.h"
  43. #include "qnetd-client-msg-received.h"
  44. /*
  45. * 0 - Success
  46. * -1 - Disconnect client
  47. * -2 - Error reply sent, but no need to disconnect client
  48. */
  49. static int
  50. qnetd_client_msg_received_check_tls(struct qnetd_instance *instance, struct qnetd_client *client,
  51. const struct msg_decoded *msg)
  52. {
  53. int check_certificate;
  54. int tls_required;
  55. CERTCertificate *peer_cert;
  56. int case_processed;
  57. check_certificate = 0;
  58. tls_required = 0;
  59. case_processed = 0;
  60. switch (instance->tls_supported) {
  61. case TLV_TLS_UNSUPPORTED:
  62. case_processed = 1;
  63. tls_required = 0;
  64. check_certificate = 0;
  65. break;
  66. case TLV_TLS_SUPPORTED:
  67. case_processed = 1;
  68. tls_required = 0;
  69. if (client->tls_started && instance->tls_client_cert_required &&
  70. !client->tls_peer_certificate_verified) {
  71. check_certificate = 1;
  72. }
  73. break;
  74. case TLV_TLS_REQUIRED:
  75. case_processed = 1;
  76. tls_required = 1;
  77. if (instance->tls_client_cert_required && !client->tls_peer_certificate_verified) {
  78. check_certificate = 1;
  79. }
  80. break;
  81. /*
  82. * Default is not defined intentionally. Compiler shows warning when new
  83. * tls supported is added
  84. */
  85. }
  86. if (!case_processed) {
  87. log(LOG_ERR, "Unhandled instance tls supported %u", instance->tls_supported);
  88. exit(1);
  89. }
  90. if (tls_required && !client->tls_started) {
  91. log(LOG_ERR, "TLS is required but doesn't started yet. "
  92. "Sending back error message");
  93. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  94. TLV_REPLY_ERROR_CODE_TLS_REQUIRED) != 0) {
  95. return (-1);
  96. }
  97. return (-2);
  98. }
  99. if (check_certificate) {
  100. peer_cert = SSL_PeerCertificate(client->socket);
  101. if (peer_cert == NULL) {
  102. log(LOG_ERR, "Client doesn't sent valid certificate. "
  103. "Disconnecting client");
  104. return (-1);
  105. }
  106. if (CERT_VerifyCertName(peer_cert, client->cluster_name) != SECSuccess) {
  107. log(LOG_ERR, "Client doesn't sent certificate with valid CN. "
  108. "Disconnecting client");
  109. CERT_DestroyCertificate(peer_cert);
  110. return (-1);
  111. }
  112. CERT_DestroyCertificate(peer_cert);
  113. client->tls_peer_certificate_verified = 1;
  114. }
  115. return (0);
  116. }
  117. static int
  118. qnetd_client_msg_received_preinit(struct qnetd_instance *instance, struct qnetd_client *client,
  119. const struct msg_decoded *msg)
  120. {
  121. struct send_buffer_list_entry *send_buffer;
  122. if (msg->cluster_name == NULL) {
  123. log(LOG_ERR, "Received preinit message without cluster name. "
  124. "Sending error reply.");
  125. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  126. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  127. return (-1);
  128. }
  129. return (0);
  130. }
  131. client->cluster_name = malloc(msg->cluster_name_len + 1);
  132. if (client->cluster_name == NULL) {
  133. log(LOG_ERR, "Can't allocate cluster name. Sending error reply.");
  134. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  135. TLV_REPLY_ERROR_CODE_INTERNAL_ERROR) != 0) {
  136. return (-1);
  137. }
  138. return (0);
  139. }
  140. memset(client->cluster_name, 0, msg->cluster_name_len + 1);
  141. memcpy(client->cluster_name, msg->cluster_name, msg->cluster_name_len);
  142. client->cluster_name_len = msg->cluster_name_len;
  143. client->preinit_received = 1;
  144. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  145. if (send_buffer == NULL) {
  146. log(LOG_ERR, "Can't alloc preinit reply msg from list. "
  147. "Disconnecting client connection.");
  148. return (-1);
  149. }
  150. if (msg_create_preinit_reply(&send_buffer->buffer, msg->seq_number_set, msg->seq_number,
  151. instance->tls_supported, instance->tls_client_cert_required) == 0) {
  152. log(LOG_ERR, "Can't alloc preinit reply msg. "
  153. "Disconnecting client connection.");
  154. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  155. return (-1);
  156. };
  157. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  158. return (0);
  159. }
  160. static int
  161. qnetd_client_msg_received_unexpected_msg(struct qnetd_client *client,
  162. const struct msg_decoded *msg, const char *msg_str)
  163. {
  164. log(LOG_ERR, "Received %s message. Sending back error message", msg_str);
  165. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  166. TLV_REPLY_ERROR_CODE_UNEXPECTED_MESSAGE) != 0) {
  167. return (-1);
  168. }
  169. return (0);
  170. }
  171. static int
  172. qnetd_client_msg_received_preinit_reply(struct qnetd_instance *instance,
  173. struct qnetd_client *client, const struct msg_decoded *msg)
  174. {
  175. return (qnetd_client_msg_received_unexpected_msg(client, msg, "preinit reply"));
  176. }
  177. static int
  178. qnetd_client_msg_received_starttls(struct qnetd_instance *instance, struct qnetd_client *client,
  179. const struct msg_decoded *msg)
  180. {
  181. PRFileDesc *new_pr_fd;
  182. if (!client->preinit_received) {
  183. log(LOG_ERR, "Received starttls before preinit message. "
  184. "Sending error reply.");
  185. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  186. TLV_REPLY_ERROR_CODE_PREINIT_REQUIRED) != 0) {
  187. return (-1);
  188. }
  189. return (0);
  190. }
  191. if ((new_pr_fd = nss_sock_start_ssl_as_server(client->socket, instance->server.cert,
  192. instance->server.private_key, instance->tls_client_cert_required, 0, NULL)) == NULL) {
  193. log_nss(LOG_ERR, "Can't start TLS. Disconnecting client.");
  194. return (-1);
  195. }
  196. client->tls_started = 1;
  197. client->tls_peer_certificate_verified = 0;
  198. client->socket = new_pr_fd;
  199. return (0);
  200. }
  201. static int
  202. qnetd_client_msg_received_server_error(struct qnetd_instance *instance, struct qnetd_client *client,
  203. const struct msg_decoded *msg)
  204. {
  205. return (qnetd_client_msg_received_unexpected_msg(client, msg, "server error"));
  206. }
  207. /*
  208. * Checks if new client send information are valid. It means:
  209. * - in cluster is no duplicate node with same nodeid
  210. * - it has same tie_breaker as other nodes in cluster
  211. * - it has same algorithm as other nodes in cluster
  212. */
  213. static enum tlv_reply_error_code
  214. qnetd_client_msg_received_init_check_new_client(struct qnetd_instance *instance,
  215. struct qnetd_client *new_client)
  216. {
  217. struct qnetd_cluster *cluster;
  218. struct qnetd_client *client;
  219. cluster = qnetd_cluster_list_find_by_name(&instance->clusters, new_client->cluster_name,
  220. new_client->cluster_name_len);
  221. if (cluster == NULL) {
  222. return (TLV_REPLY_ERROR_CODE_NO_ERROR);
  223. }
  224. TAILQ_FOREACH(client, &cluster->client_list, cluster_entries) {
  225. if (!tlv_tie_breaker_eq(&new_client->tie_breaker, &client->tie_breaker)) {
  226. log(LOG_ERR, "Received init message contains tie-breaker which "
  227. "differs from rest of cluster. Sending error reply");
  228. return (TLV_REPLY_ERROR_CODE_TIE_BREAKER_DIFFERS_FROM_OTHER_NODES);
  229. }
  230. if (new_client->decision_algorithm != client->decision_algorithm) {
  231. log(LOG_ERR, "Received init message contains algorithm which "
  232. "differs from rest of cluster. Sending error reply");
  233. return (TLV_REPLY_ERROR_CODE_ALGORITHM_DIFFERS_FROM_OTHER_NODES);
  234. }
  235. if (new_client->node_id == client->node_id) {
  236. log(LOG_ERR, "Received init message contains node id which is "
  237. "duplicate of other node in cluster. Sending error reply");
  238. return (TLV_REPLY_ERROR_CODE_DUPLICATE_NODE_ID);
  239. }
  240. }
  241. return (TLV_REPLY_ERROR_CODE_NO_ERROR);
  242. }
  243. static int
  244. qnetd_client_msg_received_init(struct qnetd_instance *instance, struct qnetd_client *client,
  245. const struct msg_decoded *msg)
  246. {
  247. int res;
  248. size_t zi;
  249. enum msg_type *supported_msgs;
  250. size_t no_supported_msgs;
  251. enum tlv_opt_type *supported_opts;
  252. size_t no_supported_opts;
  253. struct send_buffer_list_entry *send_buffer;
  254. enum tlv_reply_error_code reply_error_code;
  255. struct qnetd_cluster *cluster;
  256. supported_msgs = NULL;
  257. supported_opts = NULL;
  258. no_supported_msgs = 0;
  259. no_supported_opts = 0;
  260. reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
  261. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  262. return (res == -1 ? -1 : 0);
  263. }
  264. if (!client->preinit_received) {
  265. log(LOG_ERR, "Received init before preinit message. Sending error reply.");
  266. reply_error_code = TLV_REPLY_ERROR_CODE_PREINIT_REQUIRED;
  267. }
  268. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR && !msg->node_id_set) {
  269. log(LOG_ERR, "Received init message without node id set. "
  270. "Sending error reply.");
  271. reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
  272. } else {
  273. client->node_id_set = 1;
  274. client->node_id = msg->node_id;
  275. }
  276. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR && !msg->ring_id_set) {
  277. log(LOG_ERR, "Received init message without ring id set. "
  278. "Sending error reply.");
  279. reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
  280. } else {
  281. memcpy(&client->last_ring_id, &msg->ring_id, sizeof(struct tlv_ring_id));
  282. }
  283. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR && !msg->heartbeat_interval_set) {
  284. log(LOG_ERR, "Received init message without heartbeat interval set. "
  285. "Sending error reply.");
  286. reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
  287. } else {
  288. if (msg->heartbeat_interval < instance->advanced_settings->heartbeat_interval_min ||
  289. msg->heartbeat_interval > instance->advanced_settings->heartbeat_interval_max) {
  290. log(LOG_ERR, "Client requested invalid heartbeat interval %u. "
  291. "Sending error reply.", msg->heartbeat_interval);
  292. reply_error_code = TLV_REPLY_ERROR_CODE_INVALID_HEARTBEAT_INTERVAL;
  293. } else {
  294. client->heartbeat_interval = msg->heartbeat_interval;
  295. }
  296. }
  297. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR && !msg->tie_breaker_set) {
  298. log(LOG_ERR, "Received init message without tie-breaker set. "
  299. "Sending error reply.");
  300. reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
  301. } else {
  302. memcpy(&client->tie_breaker, &msg->tie_breaker, sizeof(msg->tie_breaker));
  303. }
  304. if (msg->supported_messages != NULL) {
  305. /*
  306. * Client sent supported messages. For now this is ignored but in the future
  307. * this may be used to ensure backward compatibility.
  308. */
  309. /*
  310. for (i = 0; i < msg->no_supported_messages; i++) {
  311. log(LOG_DEBUG, "Client supports %u message",
  312. (int)msg->supported_messages[i]);
  313. }
  314. */
  315. /*
  316. * Sent back supported messages
  317. */
  318. msg_get_supported_messages(&supported_msgs, &no_supported_msgs);
  319. }
  320. if (msg->supported_options != NULL) {
  321. /*
  322. * Client sent supported options. For now this is ignored but in the future
  323. * this may be used to ensure backward compatibility.
  324. */
  325. /*
  326. for (i = 0; i < msg->no_supported_options; i++) {
  327. log(LOG_DEBUG, "Client supports %u option",
  328. (int)msg->supported_messages[i]);
  329. }
  330. */
  331. /*
  332. * Send back supported options
  333. */
  334. tlv_get_supported_options(&supported_opts, &no_supported_opts);
  335. }
  336. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR && !msg->decision_algorithm_set) {
  337. log(LOG_ERR, "Received init message without decision algorithm. "
  338. "Sending error reply.");
  339. reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
  340. } else {
  341. /*
  342. * Check if decision algorithm requested by client is supported
  343. */
  344. res = 0;
  345. for (zi = 0; zi < QNETD_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE && !res; zi++) {
  346. if (qnetd_static_supported_decision_algorithms[zi] ==
  347. msg->decision_algorithm) {
  348. res = 1;
  349. }
  350. }
  351. if (!res) {
  352. log(LOG_ERR, "Client requested unsupported decision algorithm %u. "
  353. "Sending error reply.", msg->decision_algorithm);
  354. reply_error_code = TLV_REPLY_ERROR_CODE_UNSUPPORTED_DECISION_ALGORITHM;
  355. }
  356. client->decision_algorithm = msg->decision_algorithm;
  357. }
  358. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR) {
  359. /*
  360. * Preset keep_active_partition_tie_breaker from default config
  361. */
  362. client->keep_active_partition_tie_breaker =
  363. instance->advanced_settings->keep_active_partition_tie_breaker;
  364. }
  365. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR) {
  366. reply_error_code = qnetd_client_msg_received_init_check_new_client(instance,
  367. client);
  368. }
  369. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR) {
  370. cluster = qnetd_cluster_list_add_client(&instance->clusters, client);
  371. if (cluster == NULL) {
  372. log(LOG_ERR, "Can't add client to cluster list. "
  373. "Sending error reply.");
  374. reply_error_code = TLV_REPLY_ERROR_CODE_INTERNAL_ERROR;
  375. } else {
  376. client->cluster = cluster;
  377. client->cluster_list = &instance->clusters;
  378. }
  379. }
  380. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR) {
  381. qnetd_log_debug_new_client_connected(client);
  382. reply_error_code = qnetd_algorithm_client_init(client);
  383. }
  384. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR) {
  385. /*
  386. * Correct init received
  387. */
  388. client->init_received = 1;
  389. } else {
  390. log(LOG_ERR, "Algorithm returned error code. Sending error reply.");
  391. }
  392. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  393. if (send_buffer == NULL) {
  394. log(LOG_ERR, "Can't alloc init reply msg from list. "
  395. "Disconnecting client connection.");
  396. return (-1);
  397. }
  398. if (msg_create_init_reply(&send_buffer->buffer, msg->seq_number_set, msg->seq_number,
  399. reply_error_code,
  400. supported_msgs, no_supported_msgs, supported_opts, no_supported_opts,
  401. instance->advanced_settings->max_client_receive_size,
  402. instance->advanced_settings->max_client_send_size,
  403. qnetd_static_supported_decision_algorithms,
  404. QNETD_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE) == 0) {
  405. log(LOG_ERR, "Can't alloc init reply msg. Disconnecting client connection.");
  406. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  407. return (-1);
  408. }
  409. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  410. return (0);
  411. }
  412. static int
  413. qnetd_client_msg_received_init_reply(struct qnetd_instance *instance, struct qnetd_client *client,
  414. const struct msg_decoded *msg)
  415. {
  416. return (qnetd_client_msg_received_unexpected_msg(client, msg, "init reply"));
  417. }
  418. static int
  419. qnetd_client_msg_received_set_option_reply(struct qnetd_instance *instance,
  420. struct qnetd_client *client, const struct msg_decoded *msg)
  421. {
  422. return (qnetd_client_msg_received_unexpected_msg(client, msg, "set option reply"));
  423. }
  424. static int
  425. qnetd_client_msg_received_set_option(struct qnetd_instance *instance, struct qnetd_client *client,
  426. const struct msg_decoded *msg)
  427. {
  428. int res;
  429. struct send_buffer_list_entry *send_buffer;
  430. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  431. return (res == -1 ? -1 : 0);
  432. }
  433. if (!client->init_received) {
  434. log(LOG_ERR, "Received set option message before init message. "
  435. "Sending error reply.");
  436. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  437. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  438. return (-1);
  439. }
  440. return (0);
  441. }
  442. if (msg->heartbeat_interval_set) {
  443. /*
  444. * Check if heartbeat interval is valid
  445. */
  446. if (msg->heartbeat_interval < instance->advanced_settings->heartbeat_interval_min ||
  447. msg->heartbeat_interval > instance->advanced_settings->heartbeat_interval_max) {
  448. log(LOG_ERR, "Client requested invalid heartbeat interval %u. "
  449. "Sending error reply.", msg->heartbeat_interval);
  450. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  451. TLV_REPLY_ERROR_CODE_INVALID_HEARTBEAT_INTERVAL) != 0) {
  452. return (-1);
  453. }
  454. return (0);
  455. }
  456. client->heartbeat_interval = msg->heartbeat_interval;
  457. }
  458. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  459. if (send_buffer == NULL) {
  460. log(LOG_ERR, "Can't alloc set option reply msg from list. "
  461. "Disconnecting client connection.");
  462. return (-1);
  463. }
  464. if (msg_create_set_option_reply(&send_buffer->buffer, msg->seq_number_set, msg->seq_number,
  465. client->heartbeat_interval) == 0) {
  466. log(LOG_ERR, "Can't alloc set option reply msg. "
  467. "Disconnecting client connection.");
  468. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  469. return (-1);
  470. }
  471. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  472. return (0);
  473. }
  474. static int
  475. qnetd_client_msg_received_echo_reply(struct qnetd_instance *instance, struct qnetd_client *client,
  476. const struct msg_decoded *msg)
  477. {
  478. return (qnetd_client_msg_received_unexpected_msg(client, msg, "echo reply"));
  479. }
  480. static int
  481. qnetd_client_msg_received_echo_request(struct qnetd_instance *instance, struct qnetd_client *client,
  482. const struct msg_decoded *msg, const struct dynar *msg_orig)
  483. {
  484. int res;
  485. struct send_buffer_list_entry *send_buffer;
  486. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  487. return (res == -1 ? -1 : 0);
  488. }
  489. if (!client->init_received) {
  490. log(LOG_ERR, "Received echo request before init message. "
  491. "Sending error reply.");
  492. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  493. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  494. return (-1);
  495. }
  496. return (0);
  497. }
  498. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  499. if (send_buffer == NULL) {
  500. log(LOG_ERR, "Can't alloc echo reply msg from list. "
  501. "Disconnecting client connection.");
  502. return (-1);
  503. }
  504. if (msg_create_echo_reply(&send_buffer->buffer, msg_orig) == 0) {
  505. log(LOG_ERR, "Can't alloc echo reply msg. Disconnecting client connection.");
  506. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  507. return (-1);
  508. }
  509. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  510. return (0);
  511. }
  512. static int
  513. qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnetd_client *client,
  514. const struct msg_decoded *msg)
  515. {
  516. int res;
  517. struct send_buffer_list_entry *send_buffer;
  518. enum tlv_reply_error_code reply_error_code;
  519. enum tlv_vote result_vote;
  520. int case_processed;
  521. reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
  522. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  523. return (res == -1 ? -1 : 0);
  524. }
  525. if (!client->init_received) {
  526. log(LOG_ERR, "Received node list message before init message. "
  527. "Sending error reply.");
  528. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  529. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  530. return (-1);
  531. }
  532. return (0);
  533. }
  534. if (!msg->node_list_type_set) {
  535. log(LOG_ERR, "Received node list message without node list type set. "
  536. "Sending error reply.");
  537. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  538. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  539. return (-1);
  540. }
  541. return (0);
  542. }
  543. if (!msg->seq_number_set) {
  544. log(LOG_ERR, "Received node list message without seq number set. "
  545. "Sending error reply.");
  546. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  547. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  548. return (-1);
  549. }
  550. return (0);
  551. }
  552. result_vote = TLV_VOTE_NO_CHANGE;
  553. case_processed = 0;
  554. switch (msg->node_list_type) {
  555. case TLV_NODE_LIST_TYPE_INITIAL_CONFIG:
  556. case TLV_NODE_LIST_TYPE_CHANGED_CONFIG:
  557. case_processed = 1;
  558. qnetd_log_debug_config_node_list_received(client, msg->seq_number,
  559. msg->config_version_set, msg->config_version, &msg->nodes,
  560. (msg->node_list_type == TLV_NODE_LIST_TYPE_INITIAL_CONFIG));
  561. reply_error_code = qnetd_algorithm_config_node_list_received(client,
  562. msg->seq_number, msg->config_version_set, msg->config_version,
  563. &msg->nodes,
  564. (msg->node_list_type == TLV_NODE_LIST_TYPE_INITIAL_CONFIG),
  565. &result_vote);
  566. break;
  567. case TLV_NODE_LIST_TYPE_MEMBERSHIP:
  568. case_processed = 1;
  569. if (!msg->ring_id_set) {
  570. log(LOG_ERR, "Received node list message without ring id number set. "
  571. "Sending error reply.");
  572. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  573. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  574. return (-1);
  575. }
  576. return (0);
  577. }
  578. qnetd_log_debug_membership_node_list_received(client, msg->seq_number, &msg->ring_id,
  579. msg->heuristics, &msg->nodes);
  580. reply_error_code = qnetd_algorithm_membership_node_list_received(client,
  581. msg->seq_number, &msg->ring_id, &msg->nodes, msg->heuristics, &result_vote);
  582. break;
  583. case TLV_NODE_LIST_TYPE_QUORUM:
  584. case_processed = 1;
  585. if (!msg->quorate_set) {
  586. log(LOG_ERR, "Received quorum list message without quorate set. "
  587. "Sending error reply.");
  588. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  589. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  590. return (-1);
  591. }
  592. return (0);
  593. }
  594. qnetd_log_debug_quorum_node_list_received(client, msg->seq_number,msg->quorate,
  595. &msg->nodes);
  596. reply_error_code = qnetd_algorithm_quorum_node_list_received(client,
  597. msg->seq_number,msg->quorate, &msg->nodes, &result_vote);
  598. break;
  599. /*
  600. * Default is not defined intentionally. Compiler shows warning when new
  601. * node list type is added
  602. */
  603. }
  604. if (!case_processed) {
  605. log(LOG_ERR, "qnetd_client_msg_received_node_list fatal error. "
  606. "Unhandled node_list_type");
  607. exit(1);
  608. }
  609. if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
  610. log(LOG_ERR, "Algorithm returned error code. "
  611. "Sending error reply.");
  612. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  613. reply_error_code) != 0) {
  614. return (-1);
  615. }
  616. return (0);
  617. } else {
  618. log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
  619. }
  620. /*
  621. * Store node list for future use
  622. */
  623. case_processed = 0;
  624. switch (msg->node_list_type) {
  625. case TLV_NODE_LIST_TYPE_INITIAL_CONFIG:
  626. case TLV_NODE_LIST_TYPE_CHANGED_CONFIG:
  627. case_processed = 1;
  628. node_list_free(&client->configuration_node_list);
  629. if (node_list_clone(&client->configuration_node_list, &msg->nodes) == -1) {
  630. log(LOG_ERR, "Can't alloc config node list clone. "
  631. "Disconnecting client connection.");
  632. return (-1);
  633. }
  634. client->config_version_set = msg->config_version_set;
  635. client->config_version = msg->config_version;
  636. break;
  637. case TLV_NODE_LIST_TYPE_MEMBERSHIP:
  638. case_processed = 1;
  639. node_list_free(&client->last_membership_node_list);
  640. if (node_list_clone(&client->last_membership_node_list, &msg->nodes) == -1) {
  641. log(LOG_ERR, "Can't alloc membership node list clone. "
  642. "Disconnecting client connection.");
  643. return (-1);
  644. }
  645. memcpy(&client->last_ring_id, &msg->ring_id, sizeof(struct tlv_ring_id));
  646. client->last_membership_heuristics = msg->heuristics;
  647. client->last_heuristics = msg->heuristics;
  648. break;
  649. case TLV_NODE_LIST_TYPE_QUORUM:
  650. case_processed = 1;
  651. node_list_free(&client->last_quorum_node_list);
  652. if (node_list_clone(&client->last_quorum_node_list, &msg->nodes) == -1) {
  653. log(LOG_ERR, "Can't alloc quorum node list clone. "
  654. "Disconnecting client connection.");
  655. return (-1);
  656. }
  657. break;
  658. /*
  659. * Default is not defined intentionally. Compiler shows warning when new
  660. * node list type is added
  661. */
  662. }
  663. if (!case_processed) {
  664. log(LOG_ERR, "qnetd_client_msg_received_node_list fatal error. "
  665. "Unhandled node_list_type");
  666. exit(1);
  667. }
  668. /*
  669. * Store result vote
  670. */
  671. client->last_sent_vote = result_vote;
  672. if (result_vote == TLV_VOTE_ACK || result_vote == TLV_VOTE_NACK) {
  673. client->last_sent_ack_nack_vote = result_vote;
  674. }
  675. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  676. if (send_buffer == NULL) {
  677. log(LOG_ERR, "Can't alloc node list reply msg from list. "
  678. "Disconnecting client connection.");
  679. return (-1);
  680. }
  681. if (msg_create_node_list_reply(&send_buffer->buffer, msg->seq_number, msg->node_list_type,
  682. &client->last_ring_id, result_vote) == 0) {
  683. log(LOG_ERR, "Can't alloc node list reply msg. "
  684. "Disconnecting client connection.");
  685. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  686. return (-1);
  687. }
  688. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  689. return (0);
  690. }
  691. static int
  692. qnetd_client_msg_received_node_list_reply(struct qnetd_instance *instance,
  693. struct qnetd_client *client, const struct msg_decoded *msg)
  694. {
  695. return (qnetd_client_msg_received_unexpected_msg(client, msg, "node list reply"));
  696. }
  697. static int
  698. qnetd_client_msg_received_ask_for_vote(struct qnetd_instance *instance, struct qnetd_client *client,
  699. const struct msg_decoded *msg)
  700. {
  701. int res;
  702. struct send_buffer_list_entry *send_buffer;
  703. enum tlv_reply_error_code reply_error_code;
  704. enum tlv_vote result_vote;
  705. reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
  706. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  707. return (res == -1 ? -1 : 0);
  708. }
  709. if (!client->init_received) {
  710. log(LOG_ERR, "Received ask for vote message before init message. "
  711. "Sending error reply.");
  712. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  713. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  714. return (-1);
  715. }
  716. return (0);
  717. }
  718. if (!msg->seq_number_set) {
  719. log(LOG_ERR, "Received ask for vote message without seq number set. "
  720. "Sending error reply.");
  721. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  722. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  723. return (-1);
  724. }
  725. return (0);
  726. }
  727. qnetd_log_debug_ask_for_vote_received(client, msg->seq_number);
  728. reply_error_code = qnetd_algorithm_ask_for_vote_received(client, msg->seq_number,
  729. &result_vote);
  730. if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
  731. log(LOG_ERR, "Algorithm returned error code. "
  732. "Sending error reply.");
  733. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  734. reply_error_code) != 0) {
  735. return (-1);
  736. }
  737. return (0);
  738. } else {
  739. log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
  740. }
  741. /*
  742. * Store result vote
  743. */
  744. client->last_sent_vote = result_vote;
  745. if (result_vote == TLV_VOTE_ACK || result_vote == TLV_VOTE_NACK) {
  746. client->last_sent_ack_nack_vote = result_vote;
  747. }
  748. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  749. if (send_buffer == NULL) {
  750. log(LOG_ERR, "Can't alloc ask for vote reply msg from list. "
  751. "Disconnecting client connection.");
  752. return (-1);
  753. }
  754. if (msg_create_ask_for_vote_reply(&send_buffer->buffer, msg->seq_number,
  755. &client->last_ring_id, result_vote) == 0) {
  756. log(LOG_ERR, "Can't alloc ask for vote reply msg. "
  757. "Disconnecting client connection.");
  758. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  759. return (-1);
  760. }
  761. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  762. return (0);
  763. }
  764. static int
  765. qnetd_client_msg_received_ask_for_vote_reply(struct qnetd_instance *instance,
  766. struct qnetd_client *client, const struct msg_decoded *msg)
  767. {
  768. return (qnetd_client_msg_received_unexpected_msg(client, msg, "ask for vote reply"));
  769. }
  770. static int
  771. qnetd_client_msg_received_vote_info(struct qnetd_instance *instance, struct qnetd_client *client,
  772. const struct msg_decoded *msg)
  773. {
  774. return (qnetd_client_msg_received_unexpected_msg(client, msg, "vote info"));
  775. }
  776. static int
  777. qnetd_client_msg_received_vote_info_reply(struct qnetd_instance *instance,
  778. struct qnetd_client *client, const struct msg_decoded *msg)
  779. {
  780. int res;
  781. enum tlv_reply_error_code reply_error_code;
  782. reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
  783. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  784. return (res == -1 ? -1 : 0);
  785. }
  786. if (!client->init_received) {
  787. log(LOG_ERR, "Received vote info reply before init message. "
  788. "Sending error reply.");
  789. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  790. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  791. return (-1);
  792. }
  793. return (0);
  794. }
  795. if (!msg->seq_number_set) {
  796. log(LOG_ERR, "Received vote info reply message without seq number set. "
  797. "Sending error reply.");
  798. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  799. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  800. return (-1);
  801. }
  802. return (0);
  803. }
  804. qnetd_log_debug_vote_info_reply_received(client, msg->seq_number);
  805. reply_error_code = qnetd_algorithm_vote_info_reply_received(client, msg->seq_number);
  806. if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
  807. log(LOG_ERR, "Algorithm returned error code. "
  808. "Sending error reply.");
  809. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  810. reply_error_code) != 0) {
  811. return (-1);
  812. }
  813. return (0);
  814. }
  815. return (0);
  816. }
  817. static int
  818. qnetd_client_msg_received_heuristics_change(struct qnetd_instance *instance, struct qnetd_client *client,
  819. const struct msg_decoded *msg)
  820. {
  821. int res;
  822. struct send_buffer_list_entry *send_buffer;
  823. enum tlv_reply_error_code reply_error_code;
  824. enum tlv_vote result_vote;
  825. reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
  826. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  827. return (res == -1 ? -1 : 0);
  828. }
  829. if (!client->init_received) {
  830. log(LOG_ERR, "Received heuristics change message before init message. "
  831. "Sending error reply.");
  832. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  833. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  834. return (-1);
  835. }
  836. return (0);
  837. }
  838. if (!msg->seq_number_set || msg->heuristics == TLV_HEURISTICS_UNDEFINED) {
  839. log(LOG_ERR, "Received heuristics change message without seq number set or "
  840. "with undefined heuristics. Sending error reply.");
  841. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  842. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  843. return (-1);
  844. }
  845. return (0);
  846. }
  847. qnetd_log_debug_heuristics_change_received(client, msg->seq_number, msg->heuristics);
  848. reply_error_code = qnetd_algorithm_heuristics_change_received(client, msg->seq_number,
  849. msg->heuristics, &result_vote);
  850. if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
  851. log(LOG_ERR, "Algorithm returned error code. "
  852. "Sending error reply.");
  853. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  854. reply_error_code) != 0) {
  855. return (-1);
  856. }
  857. return (0);
  858. } else {
  859. log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
  860. }
  861. /*
  862. * Store result vote and heuristics result
  863. */
  864. client->last_sent_vote = result_vote;
  865. if (result_vote == TLV_VOTE_ACK || result_vote == TLV_VOTE_NACK) {
  866. client->last_sent_ack_nack_vote = result_vote;
  867. }
  868. client->last_regular_heuristics = msg->heuristics;
  869. client->last_heuristics = msg->heuristics;
  870. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  871. if (send_buffer == NULL) {
  872. log(LOG_ERR, "Can't alloc heuristics change reply msg from list. "
  873. "Disconnecting client connection.");
  874. return (-1);
  875. }
  876. if (msg_create_heuristics_change_reply(&send_buffer->buffer, msg->seq_number,
  877. &client->last_ring_id, msg->heuristics, result_vote) == 0) {
  878. log(LOG_ERR, "Can't alloc heuristics change reply msg. "
  879. "Disconnecting client connection.");
  880. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  881. return (-1);
  882. }
  883. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  884. return (0);
  885. }
  886. static int
  887. qnetd_client_msg_received_heuristics_change_reply(struct qnetd_instance *instance, struct qnetd_client *client,
  888. const struct msg_decoded *msg)
  889. {
  890. return (qnetd_client_msg_received_unexpected_msg(client, msg, "heuristics change reply"));
  891. }
  892. int
  893. qnetd_client_msg_received(struct qnetd_instance *instance, struct qnetd_client *client)
  894. {
  895. struct msg_decoded msg;
  896. int res;
  897. int ret_val;
  898. int msg_processed;
  899. client->dpd_msg_received_since_last_check = 1;
  900. msg_decoded_init(&msg);
  901. res = msg_decode(&client->receive_buffer, &msg);
  902. if (res != 0) {
  903. /*
  904. * Error occurred. Send server error.
  905. */
  906. log_common_msg_decode_error(res);
  907. log(LOG_INFO, "Sending back error message");
  908. if (qnetd_client_send_err(client, msg.seq_number_set, msg.seq_number,
  909. TLV_REPLY_ERROR_CODE_ERROR_DECODING_MSG) != 0) {
  910. return (-1);
  911. }
  912. return (0);
  913. }
  914. ret_val = 0;
  915. msg_processed = 0;
  916. switch (msg.type) {
  917. case MSG_TYPE_PREINIT:
  918. msg_processed = 1;
  919. ret_val = qnetd_client_msg_received_preinit(instance, client, &msg);
  920. break;
  921. case MSG_TYPE_PREINIT_REPLY:
  922. msg_processed = 1;
  923. ret_val = qnetd_client_msg_received_preinit_reply(instance, client, &msg);
  924. break;
  925. case MSG_TYPE_STARTTLS:
  926. msg_processed = 1;
  927. ret_val = qnetd_client_msg_received_starttls(instance, client, &msg);
  928. break;
  929. case MSG_TYPE_INIT:
  930. msg_processed = 1;
  931. ret_val = qnetd_client_msg_received_init(instance, client, &msg);
  932. break;
  933. case MSG_TYPE_INIT_REPLY:
  934. msg_processed = 1;
  935. ret_val = qnetd_client_msg_received_init_reply(instance, client, &msg);
  936. break;
  937. case MSG_TYPE_SERVER_ERROR:
  938. msg_processed = 1;
  939. ret_val = qnetd_client_msg_received_server_error(instance, client, &msg);
  940. break;
  941. case MSG_TYPE_SET_OPTION:
  942. msg_processed = 1;
  943. ret_val = qnetd_client_msg_received_set_option(instance, client, &msg);
  944. break;
  945. case MSG_TYPE_SET_OPTION_REPLY:
  946. msg_processed = 1;
  947. ret_val = qnetd_client_msg_received_set_option_reply(instance, client, &msg);
  948. break;
  949. case MSG_TYPE_ECHO_REQUEST:
  950. msg_processed = 1;
  951. ret_val = qnetd_client_msg_received_echo_request(instance, client, &msg,
  952. &client->receive_buffer);
  953. break;
  954. case MSG_TYPE_ECHO_REPLY:
  955. msg_processed = 1;
  956. ret_val = qnetd_client_msg_received_echo_reply(instance, client, &msg);
  957. break;
  958. case MSG_TYPE_NODE_LIST:
  959. msg_processed = 1;
  960. ret_val = qnetd_client_msg_received_node_list(instance, client, &msg);
  961. break;
  962. case MSG_TYPE_NODE_LIST_REPLY:
  963. msg_processed = 1;
  964. ret_val = qnetd_client_msg_received_node_list_reply(instance, client, &msg);
  965. break;
  966. case MSG_TYPE_ASK_FOR_VOTE:
  967. msg_processed = 1;
  968. ret_val = qnetd_client_msg_received_ask_for_vote(instance, client, &msg);
  969. break;
  970. case MSG_TYPE_ASK_FOR_VOTE_REPLY:
  971. msg_processed = 1;
  972. ret_val = qnetd_client_msg_received_ask_for_vote_reply(instance, client, &msg);
  973. break;
  974. case MSG_TYPE_VOTE_INFO:
  975. msg_processed = 1;
  976. ret_val = qnetd_client_msg_received_vote_info(instance, client, &msg);
  977. break;
  978. case MSG_TYPE_VOTE_INFO_REPLY:
  979. msg_processed = 1;
  980. ret_val = qnetd_client_msg_received_vote_info_reply(instance, client, &msg);
  981. break;
  982. case MSG_TYPE_HEURISTICS_CHANGE:
  983. msg_processed = 1;
  984. ret_val = qnetd_client_msg_received_heuristics_change(instance, client, &msg);
  985. break;
  986. case MSG_TYPE_HEURISTICS_CHANGE_REPLY:
  987. msg_processed = 1;
  988. ret_val = qnetd_client_msg_received_heuristics_change_reply(instance, client,
  989. &msg);
  990. break;
  991. /*
  992. * Default is not defined intentionally. Compiler shows warning when new
  993. * msg type is added.
  994. */
  995. }
  996. if (!msg_processed) {
  997. log(LOG_ERR, "Unsupported message %u received from client. "
  998. "Sending back error message", msg.type);
  999. if (qnetd_client_send_err(client, msg.seq_number_set, msg.seq_number,
  1000. TLV_REPLY_ERROR_CODE_UNSUPPORTED_MESSAGE) != 0) {
  1001. ret_val = -1;
  1002. }
  1003. }
  1004. msg_decoded_destroy(&msg);
  1005. return (ret_val);
  1006. }