qdevice-net-msg-received.c 26 KB

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