qnetd-client-msg-received.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254
  1. /*
  2. * Copyright (c) 2015-2020 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(EXIT_FAILURE);
  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. reply_error_code = qnetd_client_msg_received_init_check_new_client(instance,
  360. client);
  361. }
  362. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR) {
  363. cluster = qnetd_cluster_list_add_client(&instance->clusters, client);
  364. if (cluster == NULL) {
  365. log(LOG_ERR, "Can't add client to cluster list. "
  366. "Sending error reply.");
  367. reply_error_code = TLV_REPLY_ERROR_CODE_INTERNAL_ERROR;
  368. } else {
  369. client->cluster = cluster;
  370. client->cluster_list = &instance->clusters;
  371. }
  372. }
  373. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR) {
  374. qnetd_log_debug_new_client_connected(client);
  375. reply_error_code = qnetd_algorithm_client_init(client);
  376. }
  377. if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR) {
  378. /*
  379. * Correct init received
  380. */
  381. client->init_received = 1;
  382. } else {
  383. log(LOG_ERR, "Algorithm returned error code. Sending error reply.");
  384. }
  385. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  386. if (send_buffer == NULL) {
  387. log(LOG_ERR, "Can't alloc init reply msg from list. "
  388. "Disconnecting client connection.");
  389. return (-1);
  390. }
  391. if (msg_create_init_reply(&send_buffer->buffer, msg->seq_number_set, msg->seq_number,
  392. reply_error_code,
  393. supported_msgs, no_supported_msgs, supported_opts, no_supported_opts,
  394. instance->advanced_settings->max_client_receive_size,
  395. instance->advanced_settings->max_client_send_size,
  396. qnetd_static_supported_decision_algorithms,
  397. QNETD_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE) == 0) {
  398. log(LOG_ERR, "Can't alloc init reply msg. Disconnecting client connection.");
  399. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  400. return (-1);
  401. }
  402. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  403. return (0);
  404. }
  405. static int
  406. qnetd_client_msg_received_init_reply(struct qnetd_instance *instance, struct qnetd_client *client,
  407. const struct msg_decoded *msg)
  408. {
  409. return (qnetd_client_msg_received_unexpected_msg(client, msg, "init reply"));
  410. }
  411. static int
  412. qnetd_client_msg_received_set_option_reply(struct qnetd_instance *instance,
  413. struct qnetd_client *client, const struct msg_decoded *msg)
  414. {
  415. return (qnetd_client_msg_received_unexpected_msg(client, msg, "set option reply"));
  416. }
  417. static int
  418. qnetd_client_msg_received_set_option(struct qnetd_instance *instance, struct qnetd_client *client,
  419. const struct msg_decoded *msg)
  420. {
  421. int res;
  422. struct send_buffer_list_entry *send_buffer;
  423. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  424. return (res == -1 ? -1 : 0);
  425. }
  426. if (!client->init_received) {
  427. log(LOG_ERR, "Received set option message before init message. "
  428. "Sending error reply.");
  429. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  430. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  431. return (-1);
  432. }
  433. return (0);
  434. }
  435. if (msg->heartbeat_interval_set) {
  436. /*
  437. * Check if heartbeat interval is valid
  438. */
  439. if (msg->heartbeat_interval < instance->advanced_settings->heartbeat_interval_min ||
  440. msg->heartbeat_interval > instance->advanced_settings->heartbeat_interval_max) {
  441. log(LOG_ERR, "Client requested invalid heartbeat interval %u. "
  442. "Sending error reply.", msg->heartbeat_interval);
  443. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  444. TLV_REPLY_ERROR_CODE_INVALID_HEARTBEAT_INTERVAL) != 0) {
  445. return (-1);
  446. }
  447. return (0);
  448. }
  449. client->heartbeat_interval = msg->heartbeat_interval;
  450. }
  451. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  452. if (send_buffer == NULL) {
  453. log(LOG_ERR, "Can't alloc set option reply msg from list. "
  454. "Disconnecting client connection.");
  455. return (-1);
  456. }
  457. if (msg_create_set_option_reply(&send_buffer->buffer, msg->seq_number_set, msg->seq_number,
  458. client->heartbeat_interval) == 0) {
  459. log(LOG_ERR, "Can't alloc set option reply msg. "
  460. "Disconnecting client connection.");
  461. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  462. return (-1);
  463. }
  464. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  465. return (0);
  466. }
  467. static int
  468. qnetd_client_msg_received_echo_reply(struct qnetd_instance *instance, struct qnetd_client *client,
  469. const struct msg_decoded *msg)
  470. {
  471. return (qnetd_client_msg_received_unexpected_msg(client, msg, "echo reply"));
  472. }
  473. static int
  474. qnetd_client_msg_received_echo_request(struct qnetd_instance *instance, struct qnetd_client *client,
  475. const struct msg_decoded *msg, const struct dynar *msg_orig)
  476. {
  477. int res;
  478. struct send_buffer_list_entry *send_buffer;
  479. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  480. return (res == -1 ? -1 : 0);
  481. }
  482. if (!client->init_received) {
  483. log(LOG_ERR, "Received echo request before init message. "
  484. "Sending error reply.");
  485. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  486. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  487. return (-1);
  488. }
  489. return (0);
  490. }
  491. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  492. if (send_buffer == NULL) {
  493. log(LOG_ERR, "Can't alloc echo reply msg from list. "
  494. "Disconnecting client connection.");
  495. return (-1);
  496. }
  497. if (msg_create_echo_reply(&send_buffer->buffer, msg_orig) == 0) {
  498. log(LOG_ERR, "Can't alloc echo reply msg. Disconnecting client connection.");
  499. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  500. return (-1);
  501. }
  502. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  503. return (0);
  504. }
  505. static int
  506. qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnetd_client *client,
  507. const struct msg_decoded *msg)
  508. {
  509. int res;
  510. struct send_buffer_list_entry *send_buffer;
  511. enum tlv_reply_error_code reply_error_code;
  512. enum tlv_vote result_vote;
  513. int case_processed;
  514. reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
  515. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  516. return (res == -1 ? -1 : 0);
  517. }
  518. if (!client->init_received) {
  519. log(LOG_ERR, "Received node list message before init message. "
  520. "Sending error reply.");
  521. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  522. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  523. return (-1);
  524. }
  525. return (0);
  526. }
  527. if (!msg->node_list_type_set) {
  528. log(LOG_ERR, "Received node list message without node list type set. "
  529. "Sending error reply.");
  530. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  531. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  532. return (-1);
  533. }
  534. return (0);
  535. }
  536. if (!msg->seq_number_set) {
  537. log(LOG_ERR, "Received node list message without seq number set. "
  538. "Sending error reply.");
  539. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  540. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  541. return (-1);
  542. }
  543. return (0);
  544. }
  545. result_vote = TLV_VOTE_NO_CHANGE;
  546. case_processed = 0;
  547. switch (msg->node_list_type) {
  548. case TLV_NODE_LIST_TYPE_INITIAL_CONFIG:
  549. case TLV_NODE_LIST_TYPE_CHANGED_CONFIG:
  550. case_processed = 1;
  551. qnetd_log_debug_config_node_list_received(client, msg->seq_number,
  552. msg->config_version_set, msg->config_version, &msg->nodes,
  553. (msg->node_list_type == TLV_NODE_LIST_TYPE_INITIAL_CONFIG));
  554. reply_error_code = qnetd_algorithm_config_node_list_received(client,
  555. msg->seq_number, msg->config_version_set, msg->config_version,
  556. &msg->nodes,
  557. (msg->node_list_type == TLV_NODE_LIST_TYPE_INITIAL_CONFIG),
  558. &result_vote);
  559. break;
  560. case TLV_NODE_LIST_TYPE_MEMBERSHIP:
  561. case_processed = 1;
  562. if (!msg->ring_id_set) {
  563. log(LOG_ERR, "Received node list message without ring id number set. "
  564. "Sending error reply.");
  565. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  566. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  567. return (-1);
  568. }
  569. return (0);
  570. }
  571. qnetd_log_debug_membership_node_list_received(client, msg->seq_number, &msg->ring_id,
  572. msg->heuristics, &msg->nodes);
  573. reply_error_code = qnetd_algorithm_membership_node_list_received(client,
  574. msg->seq_number, &msg->ring_id, &msg->nodes, msg->heuristics, &result_vote);
  575. break;
  576. case TLV_NODE_LIST_TYPE_QUORUM:
  577. case_processed = 1;
  578. if (!msg->quorate_set) {
  579. log(LOG_ERR, "Received quorum list message without quorate set. "
  580. "Sending error reply.");
  581. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  582. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  583. return (-1);
  584. }
  585. return (0);
  586. }
  587. qnetd_log_debug_quorum_node_list_received(client, msg->seq_number,msg->quorate,
  588. &msg->nodes);
  589. reply_error_code = qnetd_algorithm_quorum_node_list_received(client,
  590. msg->seq_number,msg->quorate, &msg->nodes, &result_vote);
  591. break;
  592. /*
  593. * Default is not defined intentionally. Compiler shows warning when new
  594. * node list type is added
  595. */
  596. }
  597. if (!case_processed) {
  598. log(LOG_ERR, "qnetd_client_msg_received_node_list fatal error. "
  599. "Unhandled node_list_type");
  600. exit(EXIT_FAILURE);
  601. }
  602. if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
  603. log(LOG_ERR, "Algorithm returned error code. "
  604. "Sending error reply.");
  605. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  606. reply_error_code) != 0) {
  607. return (-1);
  608. }
  609. return (0);
  610. } else {
  611. log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
  612. }
  613. /*
  614. * Store node list for future use
  615. */
  616. case_processed = 0;
  617. switch (msg->node_list_type) {
  618. case TLV_NODE_LIST_TYPE_INITIAL_CONFIG:
  619. case TLV_NODE_LIST_TYPE_CHANGED_CONFIG:
  620. case_processed = 1;
  621. node_list_free(&client->configuration_node_list);
  622. if (node_list_clone(&client->configuration_node_list, &msg->nodes) == -1) {
  623. log(LOG_ERR, "Can't alloc config node list clone. "
  624. "Disconnecting client connection.");
  625. return (-1);
  626. }
  627. client->config_version_set = msg->config_version_set;
  628. client->config_version = msg->config_version;
  629. break;
  630. case TLV_NODE_LIST_TYPE_MEMBERSHIP:
  631. case_processed = 1;
  632. node_list_free(&client->last_membership_node_list);
  633. if (node_list_clone(&client->last_membership_node_list, &msg->nodes) == -1) {
  634. log(LOG_ERR, "Can't alloc membership node list clone. "
  635. "Disconnecting client connection.");
  636. return (-1);
  637. }
  638. memcpy(&client->last_ring_id, &msg->ring_id, sizeof(struct tlv_ring_id));
  639. client->last_membership_heuristics = msg->heuristics;
  640. client->last_heuristics = msg->heuristics;
  641. break;
  642. case TLV_NODE_LIST_TYPE_QUORUM:
  643. case_processed = 1;
  644. node_list_free(&client->last_quorum_node_list);
  645. if (node_list_clone(&client->last_quorum_node_list, &msg->nodes) == -1) {
  646. log(LOG_ERR, "Can't alloc quorum node list clone. "
  647. "Disconnecting client connection.");
  648. return (-1);
  649. }
  650. break;
  651. /*
  652. * Default is not defined intentionally. Compiler shows warning when new
  653. * node list type is added
  654. */
  655. }
  656. if (!case_processed) {
  657. log(LOG_ERR, "qnetd_client_msg_received_node_list fatal error. "
  658. "Unhandled node_list_type");
  659. exit(EXIT_FAILURE);
  660. }
  661. /*
  662. * Store result vote
  663. */
  664. client->last_sent_vote = result_vote;
  665. if (result_vote == TLV_VOTE_ACK || result_vote == TLV_VOTE_NACK) {
  666. client->last_sent_ack_nack_vote = result_vote;
  667. }
  668. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  669. if (send_buffer == NULL) {
  670. log(LOG_ERR, "Can't alloc node list reply msg from list. "
  671. "Disconnecting client connection.");
  672. return (-1);
  673. }
  674. if (msg_create_node_list_reply(&send_buffer->buffer, msg->seq_number, msg->node_list_type,
  675. &client->last_ring_id, result_vote) == 0) {
  676. log(LOG_ERR, "Can't alloc node list reply msg. "
  677. "Disconnecting client connection.");
  678. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  679. return (-1);
  680. }
  681. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  682. return (0);
  683. }
  684. static int
  685. qnetd_client_msg_received_node_list_reply(struct qnetd_instance *instance,
  686. struct qnetd_client *client, const struct msg_decoded *msg)
  687. {
  688. return (qnetd_client_msg_received_unexpected_msg(client, msg, "node list reply"));
  689. }
  690. static int
  691. qnetd_client_msg_received_ask_for_vote(struct qnetd_instance *instance, struct qnetd_client *client,
  692. const struct msg_decoded *msg)
  693. {
  694. int res;
  695. struct send_buffer_list_entry *send_buffer;
  696. enum tlv_reply_error_code reply_error_code;
  697. enum tlv_vote result_vote;
  698. reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
  699. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  700. return (res == -1 ? -1 : 0);
  701. }
  702. if (!client->init_received) {
  703. log(LOG_ERR, "Received ask for vote message before init message. "
  704. "Sending error reply.");
  705. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  706. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  707. return (-1);
  708. }
  709. return (0);
  710. }
  711. if (!msg->seq_number_set) {
  712. log(LOG_ERR, "Received ask for vote message without seq number set. "
  713. "Sending error reply.");
  714. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  715. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  716. return (-1);
  717. }
  718. return (0);
  719. }
  720. qnetd_log_debug_ask_for_vote_received(client, msg->seq_number);
  721. reply_error_code = qnetd_algorithm_ask_for_vote_received(client, msg->seq_number,
  722. &result_vote);
  723. if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
  724. log(LOG_ERR, "Algorithm returned error code. "
  725. "Sending error reply.");
  726. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  727. reply_error_code) != 0) {
  728. return (-1);
  729. }
  730. return (0);
  731. } else {
  732. log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
  733. }
  734. /*
  735. * Store result vote
  736. */
  737. client->last_sent_vote = result_vote;
  738. if (result_vote == TLV_VOTE_ACK || result_vote == TLV_VOTE_NACK) {
  739. client->last_sent_ack_nack_vote = result_vote;
  740. }
  741. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  742. if (send_buffer == NULL) {
  743. log(LOG_ERR, "Can't alloc ask for vote reply msg from list. "
  744. "Disconnecting client connection.");
  745. return (-1);
  746. }
  747. if (msg_create_ask_for_vote_reply(&send_buffer->buffer, msg->seq_number,
  748. &client->last_ring_id, result_vote) == 0) {
  749. log(LOG_ERR, "Can't alloc ask for vote reply msg. "
  750. "Disconnecting client connection.");
  751. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  752. return (-1);
  753. }
  754. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  755. return (0);
  756. }
  757. static int
  758. qnetd_client_msg_received_ask_for_vote_reply(struct qnetd_instance *instance,
  759. struct qnetd_client *client, const struct msg_decoded *msg)
  760. {
  761. return (qnetd_client_msg_received_unexpected_msg(client, msg, "ask for vote reply"));
  762. }
  763. static int
  764. qnetd_client_msg_received_vote_info(struct qnetd_instance *instance, struct qnetd_client *client,
  765. const struct msg_decoded *msg)
  766. {
  767. return (qnetd_client_msg_received_unexpected_msg(client, msg, "vote info"));
  768. }
  769. static int
  770. qnetd_client_msg_received_vote_info_reply(struct qnetd_instance *instance,
  771. struct qnetd_client *client, const struct msg_decoded *msg)
  772. {
  773. int res;
  774. enum tlv_reply_error_code reply_error_code;
  775. reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
  776. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  777. return (res == -1 ? -1 : 0);
  778. }
  779. if (!client->init_received) {
  780. log(LOG_ERR, "Received vote info reply before init message. "
  781. "Sending error reply.");
  782. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  783. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  784. return (-1);
  785. }
  786. return (0);
  787. }
  788. if (!msg->seq_number_set) {
  789. log(LOG_ERR, "Received vote info reply message without seq number set. "
  790. "Sending error reply.");
  791. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  792. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  793. return (-1);
  794. }
  795. return (0);
  796. }
  797. qnetd_log_debug_vote_info_reply_received(client, msg->seq_number);
  798. reply_error_code = qnetd_algorithm_vote_info_reply_received(client, msg->seq_number);
  799. if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
  800. log(LOG_ERR, "Algorithm returned error code. "
  801. "Sending error reply.");
  802. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  803. reply_error_code) != 0) {
  804. return (-1);
  805. }
  806. return (0);
  807. }
  808. return (0);
  809. }
  810. static int
  811. qnetd_client_msg_received_heuristics_change(struct qnetd_instance *instance, struct qnetd_client *client,
  812. const struct msg_decoded *msg)
  813. {
  814. int res;
  815. struct send_buffer_list_entry *send_buffer;
  816. enum tlv_reply_error_code reply_error_code;
  817. enum tlv_vote result_vote;
  818. reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
  819. if ((res = qnetd_client_msg_received_check_tls(instance, client, msg)) != 0) {
  820. return (res == -1 ? -1 : 0);
  821. }
  822. if (!client->init_received) {
  823. log(LOG_ERR, "Received heuristics change message before init message. "
  824. "Sending error reply.");
  825. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  826. TLV_REPLY_ERROR_CODE_INIT_REQUIRED) != 0) {
  827. return (-1);
  828. }
  829. return (0);
  830. }
  831. if (!msg->seq_number_set || msg->heuristics == TLV_HEURISTICS_UNDEFINED) {
  832. log(LOG_ERR, "Received heuristics change message without seq number set or "
  833. "with undefined heuristics. Sending error reply.");
  834. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  835. TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION) != 0) {
  836. return (-1);
  837. }
  838. return (0);
  839. }
  840. qnetd_log_debug_heuristics_change_received(client, msg->seq_number, msg->heuristics);
  841. reply_error_code = qnetd_algorithm_heuristics_change_received(client, msg->seq_number,
  842. msg->heuristics, &result_vote);
  843. if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
  844. log(LOG_ERR, "Algorithm returned error code. "
  845. "Sending error reply.");
  846. if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
  847. reply_error_code) != 0) {
  848. return (-1);
  849. }
  850. return (0);
  851. } else {
  852. log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
  853. }
  854. /*
  855. * Store result vote and heuristics result
  856. */
  857. client->last_sent_vote = result_vote;
  858. if (result_vote == TLV_VOTE_ACK || result_vote == TLV_VOTE_NACK) {
  859. client->last_sent_ack_nack_vote = result_vote;
  860. }
  861. client->last_regular_heuristics = msg->heuristics;
  862. client->last_heuristics = msg->heuristics;
  863. send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
  864. if (send_buffer == NULL) {
  865. log(LOG_ERR, "Can't alloc heuristics change reply msg from list. "
  866. "Disconnecting client connection.");
  867. return (-1);
  868. }
  869. if (msg_create_heuristics_change_reply(&send_buffer->buffer, msg->seq_number,
  870. &client->last_ring_id, msg->heuristics, result_vote) == 0) {
  871. log(LOG_ERR, "Can't alloc heuristics change reply msg. "
  872. "Disconnecting client connection.");
  873. send_buffer_list_discard_new(&client->send_buffer_list, send_buffer);
  874. return (-1);
  875. }
  876. send_buffer_list_put(&client->send_buffer_list, send_buffer);
  877. return (0);
  878. }
  879. static int
  880. qnetd_client_msg_received_heuristics_change_reply(struct qnetd_instance *instance, struct qnetd_client *client,
  881. const struct msg_decoded *msg)
  882. {
  883. return (qnetd_client_msg_received_unexpected_msg(client, msg, "heuristics change reply"));
  884. }
  885. int
  886. qnetd_client_msg_received(struct qnetd_instance *instance, struct qnetd_client *client)
  887. {
  888. struct msg_decoded msg;
  889. int res;
  890. int ret_val;
  891. int msg_processed;
  892. client->dpd_msg_received_since_last_check = 1;
  893. msg_decoded_init(&msg);
  894. res = msg_decode(&client->receive_buffer, &msg);
  895. if (res != 0) {
  896. /*
  897. * Error occurred. Send server error.
  898. */
  899. log_common_msg_decode_error(res);
  900. log(LOG_INFO, "Sending back error message");
  901. if (qnetd_client_send_err(client, msg.seq_number_set, msg.seq_number,
  902. TLV_REPLY_ERROR_CODE_ERROR_DECODING_MSG) != 0) {
  903. return (-1);
  904. }
  905. return (0);
  906. }
  907. ret_val = 0;
  908. msg_processed = 0;
  909. switch (msg.type) {
  910. case MSG_TYPE_PREINIT:
  911. msg_processed = 1;
  912. ret_val = qnetd_client_msg_received_preinit(instance, client, &msg);
  913. break;
  914. case MSG_TYPE_PREINIT_REPLY:
  915. msg_processed = 1;
  916. ret_val = qnetd_client_msg_received_preinit_reply(instance, client, &msg);
  917. break;
  918. case MSG_TYPE_STARTTLS:
  919. msg_processed = 1;
  920. ret_val = qnetd_client_msg_received_starttls(instance, client, &msg);
  921. break;
  922. case MSG_TYPE_INIT:
  923. msg_processed = 1;
  924. ret_val = qnetd_client_msg_received_init(instance, client, &msg);
  925. break;
  926. case MSG_TYPE_INIT_REPLY:
  927. msg_processed = 1;
  928. ret_val = qnetd_client_msg_received_init_reply(instance, client, &msg);
  929. break;
  930. case MSG_TYPE_SERVER_ERROR:
  931. msg_processed = 1;
  932. ret_val = qnetd_client_msg_received_server_error(instance, client, &msg);
  933. break;
  934. case MSG_TYPE_SET_OPTION:
  935. msg_processed = 1;
  936. ret_val = qnetd_client_msg_received_set_option(instance, client, &msg);
  937. break;
  938. case MSG_TYPE_SET_OPTION_REPLY:
  939. msg_processed = 1;
  940. ret_val = qnetd_client_msg_received_set_option_reply(instance, client, &msg);
  941. break;
  942. case MSG_TYPE_ECHO_REQUEST:
  943. msg_processed = 1;
  944. ret_val = qnetd_client_msg_received_echo_request(instance, client, &msg,
  945. &client->receive_buffer);
  946. break;
  947. case MSG_TYPE_ECHO_REPLY:
  948. msg_processed = 1;
  949. ret_val = qnetd_client_msg_received_echo_reply(instance, client, &msg);
  950. break;
  951. case MSG_TYPE_NODE_LIST:
  952. msg_processed = 1;
  953. ret_val = qnetd_client_msg_received_node_list(instance, client, &msg);
  954. break;
  955. case MSG_TYPE_NODE_LIST_REPLY:
  956. msg_processed = 1;
  957. ret_val = qnetd_client_msg_received_node_list_reply(instance, client, &msg);
  958. break;
  959. case MSG_TYPE_ASK_FOR_VOTE:
  960. msg_processed = 1;
  961. ret_val = qnetd_client_msg_received_ask_for_vote(instance, client, &msg);
  962. break;
  963. case MSG_TYPE_ASK_FOR_VOTE_REPLY:
  964. msg_processed = 1;
  965. ret_val = qnetd_client_msg_received_ask_for_vote_reply(instance, client, &msg);
  966. break;
  967. case MSG_TYPE_VOTE_INFO:
  968. msg_processed = 1;
  969. ret_val = qnetd_client_msg_received_vote_info(instance, client, &msg);
  970. break;
  971. case MSG_TYPE_VOTE_INFO_REPLY:
  972. msg_processed = 1;
  973. ret_val = qnetd_client_msg_received_vote_info_reply(instance, client, &msg);
  974. break;
  975. case MSG_TYPE_HEURISTICS_CHANGE:
  976. msg_processed = 1;
  977. ret_val = qnetd_client_msg_received_heuristics_change(instance, client, &msg);
  978. break;
  979. case MSG_TYPE_HEURISTICS_CHANGE_REPLY:
  980. msg_processed = 1;
  981. ret_val = qnetd_client_msg_received_heuristics_change_reply(instance, client,
  982. &msg);
  983. break;
  984. /*
  985. * Default is not defined intentionally. Compiler shows warning when new
  986. * msg type is added.
  987. */
  988. }
  989. if (!msg_processed) {
  990. log(LOG_ERR, "Unsupported message %u received from client. "
  991. "Sending back error message", msg.type);
  992. if (qnetd_client_send_err(client, msg.seq_number_set, msg.seq_number,
  993. TLV_REPLY_ERROR_CODE_UNSUPPORTED_MESSAGE) != 0) {
  994. ret_val = -1;
  995. }
  996. }
  997. msg_decoded_destroy(&msg);
  998. return (ret_val);
  999. }