qnetd-client-msg-received.c 36 KB

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