qdevice-net-msg-received.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  1. /*
  2. * Copyright (c) 2015-2016 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 "qdevice-log.h"
  35. #include "qdevice-net-algorithm.h"
  36. #include "qdevice-net-cast-vote-timer.h"
  37. #include "qdevice-net-msg-received.h"
  38. #include "qdevice-net-send.h"
  39. #include "qdevice-net-votequorum.h"
  40. #include "qdevice-net-echo-request-timer.h"
  41. #include "msg.h"
  42. #include "utils.h"
  43. /*
  44. * -1 - Incompatible tls combination
  45. * 0 - Don't use TLS
  46. * 1 - Use TLS
  47. */
  48. static int
  49. qdevice_net_msg_received_check_tls_compatibility(enum tlv_tls_supported server_tls,
  50. enum tlv_tls_supported client_tls)
  51. {
  52. int res;
  53. res = -1;
  54. switch (server_tls) {
  55. case TLV_TLS_UNSUPPORTED:
  56. switch (client_tls) {
  57. case TLV_TLS_UNSUPPORTED: res = 0; break;
  58. case TLV_TLS_SUPPORTED: res = 0; break;
  59. case TLV_TLS_REQUIRED: res = -1; break;
  60. }
  61. break;
  62. case TLV_TLS_SUPPORTED:
  63. switch (client_tls) {
  64. case TLV_TLS_UNSUPPORTED: res = 0; break;
  65. case TLV_TLS_SUPPORTED: res = 1; break;
  66. case TLV_TLS_REQUIRED: res = 1; break;
  67. }
  68. break;
  69. case TLV_TLS_REQUIRED:
  70. switch (client_tls) {
  71. case TLV_TLS_UNSUPPORTED: res = -1; break;
  72. case TLV_TLS_SUPPORTED: res = 1; break;
  73. case TLV_TLS_REQUIRED: res = 1; break;
  74. }
  75. break;
  76. }
  77. return (res);
  78. }
  79. static void
  80. qdevice_net_msg_received_log_msg_decode_error(int ret)
  81. {
  82. switch (ret) {
  83. case -1:
  84. qdevice_log(LOG_WARNING, "Received message with option with invalid length");
  85. break;
  86. case -2:
  87. qdevice_log(LOG_CRIT, "Can't allocate memory");
  88. break;
  89. case -3:
  90. qdevice_log(LOG_WARNING, "Received inconsistent msg (tlv len > msg size)");
  91. break;
  92. case -4:
  93. qdevice_log(LOG_ERR, "Received message with option with invalid value");
  94. break;
  95. default:
  96. qdevice_log(LOG_ERR, "Unknown error occured when decoding message");
  97. break;
  98. }
  99. }
  100. static int
  101. qdevice_net_msg_received_unexpected_msg(struct qdevice_net_instance *instance,
  102. const struct msg_decoded *msg, const char *msg_str)
  103. {
  104. qdevice_log(LOG_ERR, "Received unexpected %s message. Disconnecting from server",
  105. msg_str);
  106. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
  107. return (-1);
  108. }
  109. static int
  110. qdevice_net_msg_received_init(struct qdevice_net_instance *instance,
  111. const struct msg_decoded *msg)
  112. {
  113. return (qdevice_net_msg_received_unexpected_msg(instance, msg, "init"));
  114. }
  115. static int
  116. qdevice_net_msg_received_preinit(struct qdevice_net_instance *instance,
  117. const struct msg_decoded *msg)
  118. {
  119. return (qdevice_net_msg_received_unexpected_msg(instance, msg, "preinit"));
  120. }
  121. static int
  122. qdevice_net_msg_check_seq_number(struct qdevice_net_instance *instance,
  123. const struct msg_decoded *msg)
  124. {
  125. if (!msg->seq_number_set || msg->seq_number != instance->last_msg_seq_num) {
  126. qdevice_log(LOG_ERR, "Received message doesn't contain seq_number or "
  127. "it's not expected one.");
  128. return (-1);
  129. }
  130. return (0);
  131. }
  132. static int
  133. qdevice_net_msg_received_preinit_reply(struct qdevice_net_instance *instance,
  134. const struct msg_decoded *msg)
  135. {
  136. int res;
  137. struct send_buffer_list_entry *send_buffer;
  138. qdevice_log(LOG_DEBUG, "Received preinit reply msg");
  139. if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_PREINIT_REPLY) {
  140. qdevice_log(LOG_ERR, "Received unexpected preinit reply message. "
  141. "Disconnecting from server");
  142. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
  143. return (-1);
  144. }
  145. if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
  146. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  147. return (-1);
  148. }
  149. /*
  150. * Check TLS support
  151. */
  152. if (!msg->tls_supported_set || !msg->tls_client_cert_required_set) {
  153. qdevice_log(LOG_ERR, "Required tls_supported or tls_client_cert_required "
  154. "option is unset");
  155. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  156. return (-1);
  157. }
  158. res = qdevice_net_msg_received_check_tls_compatibility(msg->tls_supported, instance->tls_supported);
  159. if (res == -1) {
  160. qdevice_log(LOG_ERR, "Incompatible tls configuration (server %u client %u)",
  161. msg->tls_supported, instance->tls_supported);
  162. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_INCOMPATIBLE_TLS;
  163. return (-1);
  164. } else if (res == 1) {
  165. /*
  166. * Start TLS
  167. */
  168. send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
  169. if (send_buffer == NULL) {
  170. qdevice_log(LOG_ERR, "Can't allocate send list buffer for "
  171. "starttls msg");
  172. instance->disconnect_reason =
  173. QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
  174. return (-1);
  175. }
  176. instance->last_msg_seq_num++;
  177. if (msg_create_starttls(&send_buffer->buffer, 1,
  178. instance->last_msg_seq_num) == 0) {
  179. qdevice_log(LOG_ERR, "Can't allocate send buffer for starttls msg");
  180. instance->disconnect_reason =
  181. QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
  182. send_buffer_list_discard_new(&instance->send_buffer_list, send_buffer);
  183. return (-1);
  184. }
  185. send_buffer_list_put(&instance->send_buffer_list, send_buffer);
  186. instance->state = QDEVICE_NET_INSTANCE_STATE_WAITING_STARTTLS_BEING_SENT;
  187. } else if (res == 0) {
  188. if (qdevice_net_send_init(instance) != 0) {
  189. instance->disconnect_reason =
  190. QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
  191. return (-1);
  192. }
  193. }
  194. return (0);
  195. }
  196. static int
  197. qdevice_net_msg_received_init_reply(struct qdevice_net_instance *instance,
  198. const struct msg_decoded *msg)
  199. {
  200. size_t zi;
  201. int res;
  202. int send_config_node_list;
  203. int send_membership_node_list;
  204. int send_quorum_node_list;
  205. enum tlv_vote vote;
  206. struct tlv_ring_id tlv_rid;
  207. enum tlv_quorate quorate;
  208. qdevice_log(LOG_DEBUG, "Received init reply msg");
  209. if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_INIT_REPLY) {
  210. qdevice_log(LOG_ERR, "Received unexpected init reply message. "
  211. "Disconnecting from server");
  212. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
  213. return (-1);
  214. }
  215. if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
  216. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  217. return (-1);
  218. }
  219. if (!msg->reply_error_code_set) {
  220. qdevice_log(LOG_ERR, "Received init reply message without error code."
  221. "Disconnecting from server");
  222. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  223. return (-1);
  224. }
  225. if (msg->reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
  226. qdevice_log(LOG_ERR, "Received init reply message with error code %"PRIu16". "
  227. "Disconnecting from server", msg->reply_error_code);
  228. if (msg->reply_error_code == TLV_REPLY_ERROR_CODE_DUPLICATE_NODE_ID) {
  229. qdevice_log(LOG_ERR, "Duplicate node id may be result of server not yet "
  230. "accepted this node disconnect. Retry again.");
  231. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_DUPLICATE_NODE_ID_ERROR;
  232. } else if (msg->reply_error_code == TLV_REPLY_ERROR_CODE_TIE_BREAKER_DIFFERS_FROM_OTHER_NODES) {
  233. qdevice_log(LOG_ERR, "Configured tie-breaker differs in cluster. This may be "
  234. "result of server not yet accepted this node disconnect. Retry again.");
  235. instance->disconnect_reason =
  236. QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_TIE_BREAKER_DIFFERS_FROM_OTHER_NODES_ERROR;
  237. } else if (msg->reply_error_code == TLV_REPLY_ERROR_CODE_ALGORITHM_DIFFERS_FROM_OTHER_NODES) {
  238. qdevice_log(LOG_ERR, "Configured algorithm differs in cluster. This may be "
  239. "result of server not yet accepted this node disconnect. Retry again.");
  240. instance->disconnect_reason =
  241. QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_ALGORITHM_DIFFERS_FROM_OTHER_NODES_ERROR;
  242. } else {
  243. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_ERROR;
  244. }
  245. return (-1);
  246. }
  247. if (!msg->server_maximum_request_size_set || !msg->server_maximum_reply_size_set) {
  248. qdevice_log(LOG_ERR, "Required maximum_request_size or maximum_reply_size "
  249. "option is unset");
  250. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  251. return (-1);
  252. }
  253. if (msg->supported_messages == NULL || msg->supported_options == NULL) {
  254. qdevice_log(LOG_ERR, "Required supported messages or supported options "
  255. "option is unset");
  256. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  257. return (-1);
  258. }
  259. if (msg->supported_decision_algorithms == NULL) {
  260. qdevice_log(LOG_ERR, "Required supported decision algorithms option is unset");
  261. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  262. return (-1);
  263. }
  264. if (msg->server_maximum_request_size < instance->advanced_settings->net_min_msg_send_size) {
  265. qdevice_log(LOG_ERR,
  266. "Server accepts maximum %zu bytes message but this client minimum "
  267. "is %zu bytes.", msg->server_maximum_request_size,
  268. instance->advanced_settings->net_min_msg_send_size);
  269. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_INCOMPATIBLE_MSG_SIZE;
  270. return (-1);
  271. }
  272. if (msg->server_maximum_reply_size > instance->advanced_settings->net_max_msg_receive_size) {
  273. qdevice_log(LOG_ERR,
  274. "Server may send message up to %zu bytes message but this client maximum "
  275. "is %zu bytes.", msg->server_maximum_reply_size,
  276. instance->advanced_settings->net_max_msg_receive_size);
  277. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_INCOMPATIBLE_MSG_SIZE;
  278. return (-1);
  279. }
  280. /*
  281. * Change buffer sizes
  282. */
  283. dynar_set_max_size(&instance->receive_buffer, msg->server_maximum_reply_size);
  284. send_buffer_list_set_max_buffer_size(&instance->send_buffer_list,
  285. msg->server_maximum_request_size);
  286. /*
  287. * Check if server supports decision algorithm we need
  288. */
  289. res = 0;
  290. for (zi = 0; zi < msg->no_supported_decision_algorithms && !res; zi++) {
  291. if (msg->supported_decision_algorithms[zi] == instance->decision_algorithm) {
  292. res = 1;
  293. }
  294. }
  295. if (!res) {
  296. qdevice_log(LOG_ERR, "Server doesn't support required decision algorithm");
  297. instance->disconnect_reason =
  298. QDEVICE_NET_DISCONNECT_REASON_SERVER_DOESNT_SUPPORT_REQUIRED_ALGORITHM;
  299. return (-1);
  300. }
  301. /*
  302. * Finally fully connected so it's possible to remove connection timer
  303. */
  304. if (instance->connect_timer != NULL) {
  305. timer_list_delete(&instance->main_timer_list, instance->connect_timer);
  306. instance->connect_timer = NULL;
  307. }
  308. /*
  309. * Server accepted heartbeat interval -> schedule regular sending of echo request
  310. */
  311. qdevice_net_echo_request_timer_schedule(instance);
  312. send_config_node_list = 1;
  313. send_membership_node_list = 1;
  314. send_quorum_node_list = 1;
  315. vote = TLV_VOTE_WAIT_FOR_REPLY;
  316. if (qdevice_net_algorithm_connected(instance, &send_config_node_list, &send_membership_node_list,
  317. &send_quorum_node_list, &vote) != 0) {
  318. qdevice_log(LOG_DEBUG, "Algorithm returned error. Disconnecting.");
  319. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_CONNECTED_ERR;
  320. return (-1);
  321. } else {
  322. qdevice_log(LOG_DEBUG, "Algorithm decided to %s config node list, %s membership "
  323. "node list, %s quorum node list and result vote is %s",
  324. (send_config_node_list ? "send" : "not send"),
  325. (send_membership_node_list ? "send" : "not send"),
  326. (send_quorum_node_list ? "send" : "not send"),
  327. tlv_vote_to_str(vote));
  328. }
  329. /*
  330. * Now we can finally really send node list, votequorum node list and update timer
  331. */
  332. if (send_config_node_list) {
  333. if (qdevice_net_send_config_node_list(instance,
  334. &instance->qdevice_instance_ptr->config_node_list,
  335. instance->qdevice_instance_ptr->config_node_list_version_set,
  336. instance->qdevice_instance_ptr->config_node_list_version, 1) != 0) {
  337. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
  338. return (-1);
  339. }
  340. }
  341. if (send_membership_node_list) {
  342. qdevice_net_votequorum_ring_id_to_tlv(&tlv_rid,
  343. &instance->qdevice_instance_ptr->vq_node_list_ring_id);
  344. if (qdevice_net_send_membership_node_list(instance, &tlv_rid,
  345. instance->qdevice_instance_ptr->vq_node_list_entries,
  346. instance->qdevice_instance_ptr->vq_node_list) != 0) {
  347. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
  348. return (-1);
  349. }
  350. }
  351. if (send_quorum_node_list) {
  352. quorate = (instance->qdevice_instance_ptr->vq_quorum_quorate ?
  353. TLV_QUORATE_QUORATE : TLV_QUORATE_INQUORATE);
  354. if (qdevice_net_send_quorum_node_list(instance,
  355. quorate,
  356. instance->qdevice_instance_ptr->vq_quorum_node_list_entries,
  357. instance->qdevice_instance_ptr->vq_quorum_node_list) != 0) {
  358. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
  359. return (-1);
  360. }
  361. }
  362. if (qdevice_net_cast_vote_timer_update(instance, vote) != 0) {
  363. qdevice_log(LOG_CRIT, "qdevice_net_msg_received_set_option_reply fatal error. "
  364. " Can't update cast vote timer vote");
  365. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER;
  366. }
  367. instance->state = QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS;
  368. instance->connected_since_time = time(NULL);
  369. return (0);
  370. }
  371. static int
  372. qdevice_net_msg_received_starttls(struct qdevice_net_instance *instance,
  373. const struct msg_decoded *msg)
  374. {
  375. return (qdevice_net_msg_received_unexpected_msg(instance, msg, "starttls"));
  376. }
  377. static int
  378. qdevice_net_msg_received_server_error(struct qdevice_net_instance *instance,
  379. const struct msg_decoded *msg)
  380. {
  381. if (!msg->reply_error_code_set) {
  382. qdevice_log(LOG_ERR, "Received server error without error code set. "
  383. "Disconnecting from server");
  384. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  385. } else {
  386. qdevice_log(LOG_ERR, "Received server error %"PRIu16". "
  387. "Disconnecting from server", msg->reply_error_code);
  388. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_ERROR;
  389. }
  390. return (-1);
  391. }
  392. static int
  393. qdevice_net_msg_received_set_option(struct qdevice_net_instance *instance,
  394. const struct msg_decoded *msg)
  395. {
  396. return (qdevice_net_msg_received_unexpected_msg(instance, msg, "set option"));
  397. }
  398. static int
  399. qdevice_net_msg_received_set_option_reply(struct qdevice_net_instance *instance,
  400. const struct msg_decoded *msg)
  401. {
  402. if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) {
  403. qdevice_log(LOG_ERR, "Received unexpected set option reply message. "
  404. "Disconnecting from server");
  405. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
  406. return (-1);
  407. }
  408. if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
  409. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  410. return (-1);
  411. }
  412. qdevice_net_echo_request_timer_schedule(instance);
  413. return (0);
  414. }
  415. static int
  416. qdevice_net_msg_received_echo_request(struct qdevice_net_instance *instance,
  417. const struct msg_decoded *msg)
  418. {
  419. return (qdevice_net_msg_received_unexpected_msg(instance, msg, "echo request"));
  420. }
  421. static int
  422. qdevice_net_msg_received_echo_reply(struct qdevice_net_instance *instance,
  423. const struct msg_decoded *msg)
  424. {
  425. if (!msg->seq_number_set) {
  426. qdevice_log(LOG_ERR, "Received echo reply message doesn't contain seq_number.");
  427. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  428. return (-1);
  429. }
  430. if (msg->seq_number != instance->echo_request_expected_msg_seq_num) {
  431. qdevice_log(LOG_WARNING, "Received echo reply message seq_number is not expected one.");
  432. }
  433. if (qdevice_net_algorithm_echo_reply_received(instance, msg->seq_number,
  434. msg->seq_number == instance->echo_request_expected_msg_seq_num) != 0) {
  435. qdevice_log(LOG_DEBUG, "Algorithm returned error. Disconnecting");
  436. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_ECHO_REPLY_RECEIVED_ERR;
  437. return (-1);
  438. }
  439. instance->echo_reply_received_msg_seq_num = msg->seq_number;
  440. instance->last_echo_reply_received_time = time(NULL);
  441. return (0);
  442. }
  443. static int
  444. qdevice_net_msg_received_node_list(struct qdevice_net_instance *instance,
  445. const struct msg_decoded *msg)
  446. {
  447. return (qdevice_net_msg_received_unexpected_msg(instance, msg, "node list"));
  448. }
  449. static int
  450. qdevice_net_msg_received_node_list_reply(struct qdevice_net_instance *instance,
  451. const struct msg_decoded *msg)
  452. {
  453. const char *str;
  454. enum tlv_vote result_vote;
  455. int res;
  456. int case_processed;
  457. int ring_id_is_valid;
  458. if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) {
  459. qdevice_log(LOG_ERR, "Received unexpected node list reply message. "
  460. "Disconnecting from server");
  461. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
  462. return (-1);
  463. }
  464. if (!msg->vote_set || !msg->seq_number_set || !msg->node_list_type_set) {
  465. qdevice_log(LOG_ERR, "Received node list reply message without "
  466. "required options. Disconnecting from server");
  467. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  468. return (-1);
  469. }
  470. if (!msg->ring_id_set) {
  471. qdevice_log(LOG_ERR, "Received node list reply message "
  472. "without ring id set. Disconnecting from server");
  473. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  474. return (-1);
  475. }
  476. str = NULL;
  477. switch (msg->node_list_type) {
  478. case TLV_NODE_LIST_TYPE_INITIAL_CONFIG: str = "initial config"; break;
  479. case TLV_NODE_LIST_TYPE_CHANGED_CONFIG: str = "changed config"; break;
  480. case TLV_NODE_LIST_TYPE_MEMBERSHIP: str ="membership"; break;
  481. case TLV_NODE_LIST_TYPE_QUORUM: str ="quorum"; break;
  482. /*
  483. * Default is not defined intentionally. Compiler shows warning when new node list type
  484. * is added
  485. */
  486. }
  487. if (str == NULL) {
  488. qdevice_log(LOG_CRIT, "qdevice_net_msg_received_node_list_reply fatal error. "
  489. "Unhandled node_list_type (debug output)");
  490. exit(1);
  491. }
  492. qdevice_log(LOG_DEBUG, "Received %s node list reply", str);
  493. qdevice_log(LOG_DEBUG, " seq = "UTILS_PRI_MSG_SEQ, msg->seq_number);
  494. qdevice_log(LOG_DEBUG, " vote = %s", tlv_vote_to_str(msg->vote));
  495. qdevice_log(LOG_DEBUG, " ring id = ("UTILS_PRI_RING_ID")",
  496. msg->ring_id.node_id, msg->ring_id.seq);
  497. /*
  498. * Call algorithm
  499. */
  500. result_vote = msg->vote;
  501. if (!tlv_ring_id_eq(&msg->ring_id, &instance->last_sent_ring_id)) {
  502. ring_id_is_valid = 0;
  503. qdevice_log(LOG_DEBUG, "Received node list reply with old ring id.");
  504. } else {
  505. ring_id_is_valid = 1;
  506. }
  507. case_processed = 0;
  508. switch (msg->node_list_type) {
  509. case TLV_NODE_LIST_TYPE_INITIAL_CONFIG:
  510. case TLV_NODE_LIST_TYPE_CHANGED_CONFIG:
  511. case_processed = 1;
  512. res = qdevice_net_algorithm_config_node_list_reply_received(instance,
  513. msg->seq_number, (msg->node_list_type == TLV_NODE_LIST_TYPE_INITIAL_CONFIG),
  514. &msg->ring_id, ring_id_is_valid, &result_vote);
  515. break;
  516. case TLV_NODE_LIST_TYPE_MEMBERSHIP:
  517. case_processed = 1;
  518. res = qdevice_net_algorithm_membership_node_list_reply_received(instance,
  519. msg->seq_number, &msg->ring_id, ring_id_is_valid, &result_vote);
  520. break;
  521. case TLV_NODE_LIST_TYPE_QUORUM:
  522. case_processed = 1;
  523. res = qdevice_net_algorithm_quorum_node_list_reply_received(instance,
  524. msg->seq_number, &msg->ring_id, ring_id_is_valid, &result_vote);
  525. break;
  526. /*
  527. * Default is not defined intentionally. Compiler shows warning when new node list type
  528. * is added
  529. */
  530. }
  531. if (!case_processed) {
  532. qdevice_log(LOG_CRIT, "qdevice_net_msg_received_node_list_reply fatal error. "
  533. "Unhandled node_list_type (algorithm call)");
  534. exit(1);
  535. }
  536. if (res != 0) {
  537. qdevice_log(LOG_DEBUG, "Algorithm returned error. Disconnecting.");
  538. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_NODE_LIST_REPLY_ERR;
  539. return (-1);
  540. } else {
  541. qdevice_log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
  542. }
  543. if (qdevice_net_cast_vote_timer_update(instance, result_vote) != 0) {
  544. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER;
  545. return (-1);
  546. }
  547. return (0);
  548. }
  549. static int
  550. qdevice_net_msg_received_ask_for_vote(struct qdevice_net_instance *instance,
  551. const struct msg_decoded *msg)
  552. {
  553. return (qdevice_net_msg_received_unexpected_msg(instance, msg, "ask for vote"));
  554. }
  555. static int
  556. qdevice_net_msg_received_ask_for_vote_reply(struct qdevice_net_instance *instance,
  557. const struct msg_decoded *msg)
  558. {
  559. enum tlv_vote result_vote;
  560. int ring_id_is_valid;
  561. if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) {
  562. qdevice_log(LOG_ERR, "Received unexpected ask for vote reply message. "
  563. "Disconnecting from server");
  564. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
  565. return (-1);
  566. }
  567. if (!msg->vote_set || !msg->seq_number_set || !msg->ring_id_set) {
  568. qdevice_log(LOG_ERR, "Received node list reply message without "
  569. "required options. Disconnecting from server");
  570. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  571. return (-1);
  572. }
  573. qdevice_log(LOG_DEBUG, "Received ask for vote reply");
  574. qdevice_log(LOG_DEBUG, " seq = "UTILS_PRI_MSG_SEQ, msg->seq_number);
  575. qdevice_log(LOG_DEBUG, " vote = %s", tlv_vote_to_str(msg->vote));
  576. qdevice_log(LOG_DEBUG, " ring id = ("UTILS_PRI_RING_ID")",
  577. msg->ring_id.node_id, msg->ring_id.seq);
  578. result_vote = msg->vote;
  579. if (!tlv_ring_id_eq(&msg->ring_id, &instance->last_sent_ring_id)) {
  580. ring_id_is_valid = 0;
  581. qdevice_log(LOG_DEBUG, "Received ask for vote reply with old ring id.");
  582. } else {
  583. ring_id_is_valid = 1;
  584. }
  585. if (qdevice_net_algorithm_ask_for_vote_reply_received(instance, msg->seq_number,
  586. &msg->ring_id, ring_id_is_valid, &result_vote) != 0) {
  587. qdevice_log(LOG_DEBUG, "Algorithm returned error. Disconnecting.");
  588. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_ASK_FOR_VOTE_REPLY_ERR;
  589. return (-1);
  590. } else {
  591. qdevice_log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
  592. }
  593. if (qdevice_net_cast_vote_timer_update(instance, result_vote) != 0) {
  594. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER;
  595. return (-1);
  596. }
  597. return (0);
  598. }
  599. static int
  600. qdevice_net_msg_received_vote_info(struct qdevice_net_instance *instance,
  601. const struct msg_decoded *msg)
  602. {
  603. struct send_buffer_list_entry *send_buffer;
  604. enum tlv_vote result_vote;
  605. int ring_id_is_valid;
  606. if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) {
  607. qdevice_log(LOG_ERR, "Received unexpected vote info message. "
  608. "Disconnecting from server");
  609. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
  610. return (-1);
  611. }
  612. if (!msg->vote_set || !msg->seq_number_set || !msg->ring_id_set) {
  613. qdevice_log(LOG_ERR, "Received node list reply message without "
  614. "required options. Disconnecting from server");
  615. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
  616. return (-1);
  617. }
  618. qdevice_log(LOG_DEBUG, "Received vote info");
  619. qdevice_log(LOG_DEBUG, " seq = "UTILS_PRI_MSG_SEQ, msg->seq_number);
  620. qdevice_log(LOG_DEBUG, " vote = %s", tlv_vote_to_str(msg->vote));
  621. qdevice_log(LOG_DEBUG, " ring id = ("UTILS_PRI_RING_ID")",
  622. msg->ring_id.node_id, msg->ring_id.seq);
  623. result_vote = msg->vote;
  624. if (!tlv_ring_id_eq(&msg->ring_id, &instance->last_sent_ring_id)) {
  625. ring_id_is_valid = 0;
  626. qdevice_log(LOG_DEBUG, "Received vote info with old ring id.");
  627. } else {
  628. ring_id_is_valid = 1;
  629. }
  630. if (qdevice_net_algorithm_vote_info_received(instance, msg->seq_number,
  631. &msg->ring_id, ring_id_is_valid, &result_vote) != 0) {
  632. qdevice_log(LOG_DEBUG, "Algorithm returned error. Disconnecting.");
  633. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_VOTE_INFO_ERR;
  634. return (-1);
  635. } else {
  636. qdevice_log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(result_vote));
  637. }
  638. if (qdevice_net_cast_vote_timer_update(instance, result_vote) != 0) {
  639. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER;
  640. return (-1);
  641. }
  642. /*
  643. * Create reply message
  644. */
  645. send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
  646. if (send_buffer == NULL) {
  647. qdevice_log(LOG_ERR, "Can't allocate send list buffer for "
  648. "vote info reply msg");
  649. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
  650. return (-1);
  651. }
  652. if (msg_create_vote_info_reply(&send_buffer->buffer, msg->seq_number) == 0) {
  653. qdevice_log(LOG_ERR, "Can't allocate send buffer for "
  654. "vote info reply list msg");
  655. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
  656. send_buffer_list_discard_new(&instance->send_buffer_list, send_buffer);
  657. return (-1);
  658. }
  659. send_buffer_list_put(&instance->send_buffer_list, send_buffer);
  660. return (0);
  661. }
  662. static int
  663. qdevice_net_msg_received_vote_info_reply(struct qdevice_net_instance *instance,
  664. const struct msg_decoded *msg)
  665. {
  666. return (qdevice_net_msg_received_unexpected_msg(instance, msg, "vote info reply"));
  667. }
  668. int
  669. qdevice_net_msg_received(struct qdevice_net_instance *instance)
  670. {
  671. struct msg_decoded msg;
  672. int res;
  673. int ret_val;
  674. int msg_processed;
  675. msg_decoded_init(&msg);
  676. res = msg_decode(&instance->receive_buffer, &msg);
  677. if (res != 0) {
  678. /*
  679. * Error occurred. Disconnect.
  680. */
  681. qdevice_net_msg_received_log_msg_decode_error(res);
  682. qdevice_log(LOG_ERR, "Disconnecting from server");
  683. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_MSG_DECODE_ERROR;
  684. return (-1);
  685. }
  686. ret_val = 0;
  687. msg_processed = 0;
  688. switch (msg.type) {
  689. case MSG_TYPE_INIT:
  690. msg_processed = 1;
  691. ret_val = qdevice_net_msg_received_init(instance, &msg);
  692. break;
  693. case MSG_TYPE_PREINIT:
  694. msg_processed = 1;
  695. ret_val = qdevice_net_msg_received_preinit(instance, &msg);
  696. break;
  697. case MSG_TYPE_PREINIT_REPLY:
  698. msg_processed = 1;
  699. ret_val = qdevice_net_msg_received_preinit_reply(instance, &msg);
  700. break;
  701. case MSG_TYPE_STARTTLS:
  702. msg_processed = 1;
  703. ret_val = qdevice_net_msg_received_starttls(instance, &msg);
  704. break;
  705. case MSG_TYPE_SERVER_ERROR:
  706. msg_processed = 1;
  707. ret_val = qdevice_net_msg_received_server_error(instance, &msg);
  708. break;
  709. case MSG_TYPE_INIT_REPLY:
  710. msg_processed = 1;
  711. ret_val = qdevice_net_msg_received_init_reply(instance, &msg);
  712. break;
  713. case MSG_TYPE_SET_OPTION:
  714. msg_processed = 1;
  715. ret_val = qdevice_net_msg_received_set_option(instance, &msg);
  716. break;
  717. case MSG_TYPE_SET_OPTION_REPLY:
  718. msg_processed = 1;
  719. ret_val = qdevice_net_msg_received_set_option_reply(instance, &msg);
  720. break;
  721. case MSG_TYPE_ECHO_REQUEST:
  722. msg_processed = 1;
  723. ret_val = qdevice_net_msg_received_echo_request(instance, &msg);
  724. break;
  725. case MSG_TYPE_ECHO_REPLY:
  726. msg_processed = 1;
  727. ret_val = qdevice_net_msg_received_echo_reply(instance, &msg);
  728. break;
  729. case MSG_TYPE_NODE_LIST:
  730. msg_processed = 1;
  731. ret_val = qdevice_net_msg_received_node_list(instance, &msg);
  732. break;
  733. case MSG_TYPE_NODE_LIST_REPLY:
  734. msg_processed = 1;
  735. ret_val = qdevice_net_msg_received_node_list_reply(instance, &msg);
  736. break;
  737. case MSG_TYPE_ASK_FOR_VOTE:
  738. msg_processed = 1;
  739. ret_val = qdevice_net_msg_received_ask_for_vote(instance, &msg);
  740. break;
  741. case MSG_TYPE_ASK_FOR_VOTE_REPLY:
  742. msg_processed = 1;
  743. ret_val = qdevice_net_msg_received_ask_for_vote_reply(instance, &msg);
  744. break;
  745. case MSG_TYPE_VOTE_INFO:
  746. msg_processed = 1;
  747. ret_val = qdevice_net_msg_received_vote_info(instance, &msg);
  748. break;
  749. case MSG_TYPE_VOTE_INFO_REPLY:
  750. msg_processed = 1;
  751. ret_val = qdevice_net_msg_received_vote_info_reply(instance, &msg);
  752. break;
  753. /*
  754. * Default is not defined intentionally. Compiler shows warning when msg type is added
  755. */
  756. }
  757. if (!msg_processed) {
  758. qdevice_log(LOG_ERR, "Received unsupported message %u. "
  759. "Disconnecting from server", msg.type);
  760. instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
  761. ret_val = -1;
  762. }
  763. msg_decoded_destroy(&msg);
  764. return (ret_val);
  765. }