corosync-qdevice-net.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. /*
  2. * Copyright (c) 2015 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 <stdio.h>
  35. #include <nss.h>
  36. #include <secerr.h>
  37. #include <sslerr.h>
  38. #include <pk11func.h>
  39. #include <certt.h>
  40. #include <ssl.h>
  41. #include <prio.h>
  42. #include <prnetdb.h>
  43. #include <prerror.h>
  44. #include <prinit.h>
  45. #include <getopt.h>
  46. #include <err.h>
  47. #include <keyhi.h>
  48. #include "dynar.h"
  49. #include "nss-sock.h"
  50. #include "tlv.h"
  51. #include "msg.h"
  52. #include "msgio.h"
  53. #include "qnetd-log.h"
  54. #include "timer-list.h"
  55. #define NSS_DB_DIR "node/nssdb"
  56. #define QNETD_HOST "localhost"
  57. #define QNETD_PORT 4433
  58. #define QNETD_NSS_SERVER_CN "Qnetd Server"
  59. #define QDEVICE_NET_NSS_CLIENT_CERT_NICKNAME "Cluster Cert"
  60. #define QDEVICE_NET_CLUSTER_NAME "Testcluster"
  61. #define QDEVICE_NET_INITIAL_MSG_RECEIVE_SIZE (1 << 15)
  62. #define QDEVICE_NET_INITIAL_MSG_SEND_SIZE (1 << 15)
  63. #define QDEVICE_NET_MIN_MSG_SEND_SIZE QDEVICE_NET_INITIAL_MSG_SEND_SIZE
  64. #define QDEVICE_NET_MAX_MSG_RECEIVE_SIZE (1 << 24)
  65. #define QDEVICE_NET_TLS_SUPPORTED TLV_TLS_SUPPORTED
  66. #define QDEVICE_NET_NODE_ID 42
  67. #define QDEVICE_NET_DECISION_ALGORITHM TLV_DECISION_ALGORITHM_TYPE_TEST
  68. #define QDEVICE_NET_HEARTBEAT_INTERVAL 10000
  69. #define qdevice_net_log qnetd_log
  70. #define qdevice_net_log_nss qnetd_log_nss
  71. #define qdevice_net_log_init qnetd_log_init
  72. #define qdevice_net_log_close qnetd_log_close
  73. #define qdevice_net_log_set_debug qnetd_log_set_debug
  74. #define QDEVICE_NET_LOG_TARGET_STDERR QNETD_LOG_TARGET_STDERR
  75. #define QDEVICE_NET_LOG_TARGET_SYSLOG QNETD_LOG_TARGET_SYSLOG
  76. enum qdevice_net_state {
  77. QDEVICE_NET_STATE_WAITING_PREINIT_REPLY,
  78. QDEVICE_NET_STATE_WAITING_STARTTLS_BEING_SENT,
  79. QDEVICE_NET_STATE_WAITING_INIT_REPLY,
  80. QDEVICE_NET_STATE_WAITING_SET_OPTION_REPLY,
  81. };
  82. struct qdevice_net_instance {
  83. PRFileDesc *socket;
  84. size_t initial_send_size;
  85. size_t initial_receive_size;
  86. size_t max_receive_size;
  87. size_t min_send_size;
  88. struct dynar receive_buffer;
  89. struct dynar send_buffer;
  90. struct dynar echo_request_send_buffer;
  91. int sending_msg;
  92. int skipping_msg;
  93. int sending_echo_request_msg;
  94. size_t msg_already_received_bytes;
  95. size_t msg_already_sent_bytes;
  96. size_t echo_request_msg_already_sent_bytes;
  97. enum qdevice_net_state state;
  98. uint32_t expected_msg_seq_num;
  99. uint32_t echo_request_expected_msg_seq_num;
  100. uint32_t echo_reply_received_msg_seq_num;
  101. enum tlv_tls_supported tls_supported;
  102. int using_tls;
  103. uint32_t node_id;
  104. uint32_t heartbeat_interval;
  105. enum tlv_decision_algorithm_type decision_algorithm;
  106. struct timer_list main_timer_list;
  107. struct timer_list_entry *echo_request_timer;
  108. int schedule_disconnect;
  109. };
  110. static void
  111. err_nss(void) {
  112. errx(1, "nss error %d: %s", PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
  113. }
  114. static SECStatus
  115. qdevice_net_nss_bad_cert_hook(void *arg, PRFileDesc *fd) {
  116. if (PR_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE ||
  117. PR_GetError() == SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE ||
  118. PR_GetError() == SEC_ERROR_CRL_EXPIRED ||
  119. PR_GetError() == SEC_ERROR_KRL_EXPIRED ||
  120. PR_GetError() == SSL_ERROR_EXPIRED_CERT_ALERT) {
  121. qdevice_net_log(LOG_WARNING, "Server certificate is expired.");
  122. return (SECSuccess);
  123. }
  124. qdevice_net_log_nss(LOG_ERR, "Server certificate verification failure.");
  125. return (SECFailure);
  126. }
  127. static SECStatus
  128. qdevice_net_nss_get_client_auth_data(void *arg, PRFileDesc *sock, struct CERTDistNamesStr *caNames,
  129. struct CERTCertificateStr **pRetCert, struct SECKEYPrivateKeyStr **pRetKey)
  130. {
  131. qdevice_net_log(LOG_DEBUG, "Sending client auth data.");
  132. return (NSS_GetClientAuthData(arg, sock, caNames, pRetCert, pRetKey));
  133. }
  134. static int
  135. qdevice_net_schedule_send(struct qdevice_net_instance *instance)
  136. {
  137. if (instance->sending_msg) {
  138. /*
  139. * Msg is already scheduled for send
  140. */
  141. return (-1);
  142. }
  143. instance->msg_already_sent_bytes = 0;
  144. instance->sending_msg = 1;
  145. return (0);
  146. }
  147. static int
  148. qdevice_net_schedule_echo_request_send(struct qdevice_net_instance *instance)
  149. {
  150. if (instance->sending_echo_request_msg) {
  151. qdevice_net_log(LOG_ERR, "Can't schedule send of echo request msg, because "
  152. "previous message wasn't yet sent. Disconnecting from server.");
  153. return (-1);
  154. }
  155. if (instance->echo_reply_received_msg_seq_num != instance->echo_request_expected_msg_seq_num) {
  156. qdevice_net_log(LOG_ERR, "Server didn't send echo reply message on time. "
  157. "Disconnecting from server.");
  158. return (-1);
  159. }
  160. instance->echo_request_expected_msg_seq_num++;
  161. if (msg_create_echo_request(&instance->echo_request_send_buffer, 1, instance->echo_request_expected_msg_seq_num) == -1) {
  162. qdevice_net_log(LOG_ERR, "Can't allocate send buffer for echo request msg");
  163. return (-1);
  164. }
  165. instance->echo_request_msg_already_sent_bytes = 0;
  166. instance->sending_echo_request_msg = 1;
  167. return (0);
  168. }
  169. static void
  170. qdevice_net_log_msg_decode_error(int ret)
  171. {
  172. switch (ret) {
  173. case -1:
  174. qdevice_net_log(LOG_WARNING, "Received message with option with invalid length");
  175. break;
  176. case -2:
  177. qdevice_net_log(LOG_CRIT, "Can't allocate memory");
  178. break;
  179. case -3:
  180. qdevice_net_log(LOG_WARNING, "Received inconsistent msg (tlv len > msg size)");
  181. break;
  182. case -4:
  183. qdevice_net_log(LOG_ERR, "Received message with option with invalid value");
  184. break;
  185. default:
  186. qdevice_net_log(LOG_ERR, "Unknown error occured when decoding message");
  187. break;
  188. }
  189. }
  190. /*
  191. * -1 - Incompatible tls combination
  192. * 0 - Don't use TLS
  193. * 1 - Use TLS
  194. */
  195. static int
  196. qdevice_net_check_tls_compatibility(enum tlv_tls_supported server_tls, enum tlv_tls_supported client_tls)
  197. {
  198. int res;
  199. res = -1;
  200. switch (server_tls) {
  201. case TLV_TLS_UNSUPPORTED:
  202. switch (client_tls) {
  203. case TLV_TLS_UNSUPPORTED: res = 0; break;
  204. case TLV_TLS_SUPPORTED: res = 0; break;
  205. case TLV_TLS_REQUIRED: res = -1; break;
  206. }
  207. break;
  208. case TLV_TLS_SUPPORTED:
  209. switch (client_tls) {
  210. case TLV_TLS_UNSUPPORTED: res = 0; break;
  211. case TLV_TLS_SUPPORTED: res = 1; break;
  212. case TLV_TLS_REQUIRED: res = 1; break;
  213. }
  214. break;
  215. case TLV_TLS_REQUIRED:
  216. switch (client_tls) {
  217. case TLV_TLS_UNSUPPORTED: res = -1; break;
  218. case TLV_TLS_SUPPORTED: res = 1; break;
  219. case TLV_TLS_REQUIRED: res = 1; break;
  220. }
  221. break;
  222. }
  223. return (res);
  224. }
  225. static int
  226. qdevice_net_msg_received_preinit(struct qdevice_net_instance *instance, const struct msg_decoded *msg)
  227. {
  228. qdevice_net_log(LOG_ERR, "Received unexpected preinit message. Disconnecting from server");
  229. return (-1);
  230. }
  231. static int
  232. qdevice_net_msg_check_seq_number(struct qdevice_net_instance *instance, const struct msg_decoded *msg)
  233. {
  234. if (!msg->seq_number_set || msg->seq_number != instance->expected_msg_seq_num) {
  235. qdevice_net_log(LOG_ERR, "Received message doesn't contain seq_number or it's not expected one.");
  236. return (-1);
  237. }
  238. return (0);
  239. }
  240. static int
  241. qdevice_net_msg_check_echo_reply_seq_number(struct qdevice_net_instance *instance, const struct msg_decoded *msg)
  242. {
  243. if (!msg->seq_number_set) {
  244. qdevice_net_log(LOG_ERR, "Received echo reply message doesn't contain seq_number.");
  245. return (-1);
  246. }
  247. if (msg->seq_number != instance->echo_request_expected_msg_seq_num) {
  248. qdevice_net_log(LOG_ERR, "Server doesn't replied in expected time. Closing connection");
  249. return (-1);
  250. }
  251. return (0);
  252. }
  253. static int
  254. qdevice_net_send_init(struct qdevice_net_instance *instance)
  255. {
  256. enum msg_type *supported_msgs;
  257. size_t no_supported_msgs;
  258. enum tlv_opt_type *supported_opts;
  259. size_t no_supported_opts;
  260. tlv_get_supported_options(&supported_opts, &no_supported_opts);
  261. msg_get_supported_messages(&supported_msgs, &no_supported_msgs);
  262. instance->expected_msg_seq_num++;
  263. if (msg_create_init(&instance->send_buffer, 1, instance->expected_msg_seq_num,
  264. supported_msgs, no_supported_msgs, supported_opts, no_supported_opts,
  265. instance->node_id) == 0) {
  266. qdevice_net_log(LOG_ERR, "Can't allocate send buffer for init msg");
  267. return (-1);
  268. }
  269. if (qdevice_net_schedule_send(instance) != 0) {
  270. qdevice_net_log(LOG_ERR, "Can't schedule send of init msg");
  271. return (-1);
  272. }
  273. instance->state = QDEVICE_NET_STATE_WAITING_INIT_REPLY;
  274. return (0);
  275. }
  276. static int
  277. qdevice_net_msg_received_preinit_reply(struct qdevice_net_instance *instance, const struct msg_decoded *msg)
  278. {
  279. int res;
  280. if (instance->state != QDEVICE_NET_STATE_WAITING_PREINIT_REPLY) {
  281. qdevice_net_log(LOG_ERR, "Received unexpected preinit reply message. Disconnecting from server");
  282. return (-1);
  283. }
  284. if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
  285. return (-1);
  286. }
  287. /*
  288. * Check TLS support
  289. */
  290. if (!msg->tls_supported_set || !msg->tls_client_cert_required_set) {
  291. qdevice_net_log(LOG_ERR, "Required tls_supported or tls_client_cert_required option is unset");
  292. return (-1);
  293. }
  294. res = qdevice_net_check_tls_compatibility(msg->tls_supported, instance->tls_supported);
  295. if (res == -1) {
  296. qdevice_net_log(LOG_ERR, "Incompatible tls configuration (server %u client %u)",
  297. msg->tls_supported, instance->tls_supported);
  298. return (-1);
  299. } else if (res == 1) {
  300. /*
  301. * Start TLS
  302. */
  303. instance->expected_msg_seq_num++;
  304. if (msg_create_starttls(&instance->send_buffer, 1, instance->expected_msg_seq_num) == 0) {
  305. qdevice_net_log(LOG_ERR, "Can't allocate send buffer for starttls msg");
  306. return (-1);
  307. }
  308. if (qdevice_net_schedule_send(instance) != 0) {
  309. qdevice_net_log(LOG_ERR, "Can't schedule send of starttls msg");
  310. return (-1);
  311. }
  312. instance->state = QDEVICE_NET_STATE_WAITING_STARTTLS_BEING_SENT;
  313. } else if (res == 0) {
  314. if (qdevice_net_send_init(instance) != 0) {
  315. return (-1);
  316. }
  317. }
  318. return (0);
  319. }
  320. static int
  321. qdevice_net_msg_received_init_reply(struct qdevice_net_instance *instance, const struct msg_decoded *msg)
  322. {
  323. size_t zi;
  324. int res;
  325. if (instance->state != QDEVICE_NET_STATE_WAITING_INIT_REPLY) {
  326. qdevice_net_log(LOG_ERR, "Received unexpected init reply message. Disconnecting from server");
  327. return (-1);
  328. }
  329. if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
  330. return (-1);
  331. }
  332. if (!msg->server_maximum_request_size_set || !msg->server_maximum_reply_size_set) {
  333. qdevice_net_log(LOG_ERR, "Required maximum_request_size or maximum_reply_size option is unset");
  334. return (-1);
  335. }
  336. if (msg->supported_messages == NULL || msg->supported_options == NULL) {
  337. qdevice_net_log(LOG_ERR, "Required supported messages or supported options option is unset");
  338. return (-1);
  339. }
  340. if (msg->supported_decision_algorithms == NULL) {
  341. qdevice_net_log(LOG_ERR, "Required supported decision algorithms option is unset");
  342. return (-1);
  343. }
  344. if (msg->server_maximum_request_size < instance->min_send_size) {
  345. qdevice_net_log(LOG_ERR,
  346. "Server accepts maximum %zu bytes message but this client minimum is %zu bytes.",
  347. msg->server_maximum_request_size, instance->min_send_size);
  348. return (-1);
  349. }
  350. if (msg->server_maximum_reply_size > instance->max_receive_size) {
  351. qdevice_net_log(LOG_ERR,
  352. "Server may send message up to %zu bytes message but this client maximum is %zu bytes.",
  353. msg->server_maximum_reply_size, instance->max_receive_size);
  354. return (-1);
  355. }
  356. /*
  357. * Change buffer sizes
  358. */
  359. dynar_set_max_size(&instance->receive_buffer, msg->server_maximum_reply_size);
  360. dynar_set_max_size(&instance->send_buffer, msg->server_maximum_request_size);
  361. dynar_set_max_size(&instance->echo_request_send_buffer, msg->server_maximum_request_size);
  362. /*
  363. * Check if server supports decision algorithm we need
  364. */
  365. res = 0;
  366. for (zi = 0; zi < msg->no_supported_decision_algorithms && !res; zi++) {
  367. if (msg->supported_decision_algorithms[zi] == instance->decision_algorithm) {
  368. res = 1;
  369. }
  370. }
  371. if (!res) {
  372. qdevice_net_log(LOG_ERR, "Server doesn't support required decision algorithm");
  373. return (-1);
  374. }
  375. /*
  376. * Send set options message
  377. */
  378. instance->expected_msg_seq_num++;
  379. if (msg_create_set_option(&instance->send_buffer, 1, instance->expected_msg_seq_num,
  380. 1, instance->decision_algorithm, 1, instance->heartbeat_interval) == 0) {
  381. qdevice_net_log(LOG_ERR, "Can't allocate send buffer for set option msg");
  382. return (-1);
  383. }
  384. if (qdevice_net_schedule_send(instance) != 0) {
  385. qdevice_net_log(LOG_ERR, "Can't schedule send of set option msg");
  386. return (-1);
  387. }
  388. instance->state = QDEVICE_NET_STATE_WAITING_SET_OPTION_REPLY;
  389. return (0);
  390. }
  391. static int
  392. qdevice_net_msg_received_stattls(struct qdevice_net_instance *instance, const struct msg_decoded *msg)
  393. {
  394. qdevice_net_log(LOG_ERR, "Received unexpected starttls message. Disconnecting from server");
  395. return (-1);
  396. }
  397. static int
  398. qdevice_net_msg_received_server_error(struct qdevice_net_instance *instance, const struct msg_decoded *msg)
  399. {
  400. if (!msg->reply_error_code_set) {
  401. qdevice_net_log(LOG_ERR, "Received server error without error code set. Disconnecting from server");
  402. } else {
  403. qdevice_net_log(LOG_ERR, "Received server error %"PRIu16". Disconnecting from server",
  404. msg->reply_error_code);
  405. }
  406. return (-1);
  407. }
  408. static int
  409. qdevice_net_msg_received_set_option(struct qdevice_net_instance *instance, const struct msg_decoded *msg)
  410. {
  411. qdevice_net_log(LOG_ERR, "Received unexpected set option message. Disconnecting from server");
  412. return (-1);
  413. }
  414. static int
  415. qdevice_net_timer_send_heartbeat(void *data1, void *data2)
  416. {
  417. struct qdevice_net_instance *instance;
  418. instance = (struct qdevice_net_instance *)data1;
  419. if (qdevice_net_schedule_echo_request_send(instance) == -1) {
  420. instance->schedule_disconnect = 1;
  421. return (0);
  422. }
  423. /*
  424. * Schedule this function callback again
  425. */
  426. return (-1);
  427. }
  428. static int
  429. qdevice_net_msg_received_set_option_reply(struct qdevice_net_instance *instance, const struct msg_decoded *msg)
  430. {
  431. if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
  432. return (-1);
  433. }
  434. if (!msg->decision_algorithm_set || !msg->heartbeat_interval_set) {
  435. qdevice_net_log(LOG_ERR, "Received set option reply message without required options. "
  436. "Disconnecting from server");
  437. }
  438. if (msg->decision_algorithm != instance->decision_algorithm ||
  439. msg->heartbeat_interval != instance->heartbeat_interval) {
  440. qdevice_net_log(LOG_ERR, "Server doesn't accept sent decision algorithm or heartbeat interval.");
  441. return (-1);
  442. }
  443. /*
  444. * Server accepted heartbeat interval -> schedule regular sending of echo request
  445. */
  446. if (instance->heartbeat_interval > 0) {
  447. instance->echo_request_timer = timer_list_add(&instance->main_timer_list, instance->heartbeat_interval,
  448. qdevice_net_timer_send_heartbeat, (void *)instance, NULL);
  449. if (instance->echo_request_timer == NULL) {
  450. qdevice_net_log(LOG_ERR, "Can't schedule regular sending of heartbeat.");
  451. return (-1);
  452. }
  453. }
  454. return (0);
  455. }
  456. static int
  457. qdevice_net_msg_received_echo_request(struct qdevice_net_instance *instance, const struct msg_decoded *msg)
  458. {
  459. qdevice_net_log(LOG_ERR, "Received unexpected echo request message. Disconnecting from server");
  460. return (-1);
  461. }
  462. static int
  463. qdevice_net_msg_received_echo_reply(struct qdevice_net_instance *instance, const struct msg_decoded *msg)
  464. {
  465. if (qdevice_net_msg_check_echo_reply_seq_number(instance, msg) != 0) {
  466. return (-1);
  467. }
  468. instance->echo_reply_received_msg_seq_num = msg->seq_number;
  469. return (0);
  470. }
  471. static int
  472. qdevice_net_msg_received(struct qdevice_net_instance *instance)
  473. {
  474. struct msg_decoded msg;
  475. int res;
  476. int ret_val;
  477. msg_decoded_init(&msg);
  478. res = msg_decode(&instance->receive_buffer, &msg);
  479. if (res != 0) {
  480. /*
  481. * Error occurred. Disconnect.
  482. */
  483. qdevice_net_log_msg_decode_error(res);
  484. qdevice_net_log(LOG_ERR, "Disconnecting from server");
  485. return (-1);
  486. }
  487. ret_val = 0;
  488. switch (msg.type) {
  489. case MSG_TYPE_PREINIT:
  490. ret_val = qdevice_net_msg_received_preinit(instance, &msg);
  491. break;
  492. case MSG_TYPE_PREINIT_REPLY:
  493. ret_val = qdevice_net_msg_received_preinit_reply(instance, &msg);
  494. break;
  495. case MSG_TYPE_STARTTLS:
  496. ret_val = qdevice_net_msg_received_stattls(instance, &msg);
  497. break;
  498. case MSG_TYPE_SERVER_ERROR:
  499. ret_val = qdevice_net_msg_received_server_error(instance, &msg);
  500. break;
  501. case MSG_TYPE_INIT_REPLY:
  502. ret_val = qdevice_net_msg_received_init_reply(instance, &msg);
  503. break;
  504. case MSG_TYPE_SET_OPTION:
  505. ret_val = qdevice_net_msg_received_set_option(instance, &msg);
  506. break;
  507. case MSG_TYPE_SET_OPTION_REPLY:
  508. ret_val = qdevice_net_msg_received_set_option_reply(instance, &msg);
  509. break;
  510. case MSG_TYPE_ECHO_REQUEST:
  511. ret_val = qdevice_net_msg_received_echo_request(instance, &msg);
  512. break;
  513. case MSG_TYPE_ECHO_REPLY:
  514. ret_val = qdevice_net_msg_received_echo_reply(instance, &msg);
  515. break;
  516. default:
  517. qdevice_net_log(LOG_ERR, "Received unsupported message %u. Disconnecting from server", msg.type);
  518. ret_val = -1;
  519. break;
  520. }
  521. msg_decoded_destroy(&msg);
  522. return (ret_val);
  523. }
  524. /*
  525. * -1 means end of connection (EOF) or some other unhandled error. 0 = success
  526. */
  527. static int
  528. qdevice_net_socket_read(struct qdevice_net_instance *instance)
  529. {
  530. int res;
  531. int ret_val;
  532. int orig_skipping_msg;
  533. orig_skipping_msg = instance->skipping_msg;
  534. res = msgio_read(instance->socket, &instance->receive_buffer, &instance->msg_already_received_bytes,
  535. &instance->skipping_msg);
  536. if (!orig_skipping_msg && instance->skipping_msg) {
  537. qdevice_net_log(LOG_DEBUG, "msgio_read set skipping_msg");
  538. }
  539. ret_val = 0;
  540. switch (res) {
  541. case 0:
  542. /*
  543. * Partial read
  544. */
  545. break;
  546. case -1:
  547. qdevice_net_log(LOG_DEBUG, "Server closed connection");
  548. ret_val = -1;
  549. break;
  550. case -2:
  551. qdevice_net_log_nss(LOG_ERR, "Unhandled error when reading from server. Disconnecting from server");
  552. ret_val = -1;
  553. break;
  554. case -3:
  555. qdevice_net_log(LOG_ERR, "Can't store message header from server. Disconnecting from server");
  556. ret_val = -1;
  557. break;
  558. case -4:
  559. qdevice_net_log(LOG_ERR, "Can't store message from server. Disconnecting from server");
  560. ret_val = -1;
  561. break;
  562. case -5:
  563. qdevice_net_log(LOG_WARNING, "Server sent unsupported msg type %u. Disconnecting from server",
  564. msg_get_type(&instance->receive_buffer));
  565. ret_val = -1;
  566. break;
  567. case -6:
  568. qdevice_net_log(LOG_WARNING,
  569. "Server wants to send too long message %u bytes. Disconnecting from server",
  570. msg_get_len(&instance->receive_buffer));
  571. ret_val = -1;
  572. break;
  573. case 1:
  574. /*
  575. * Full message received / skipped
  576. */
  577. if (!instance->skipping_msg) {
  578. if (qdevice_net_msg_received(instance) == -1) {
  579. ret_val = -1;
  580. }
  581. } else {
  582. errx(1, "net_socket_read in skipping msg state");
  583. }
  584. instance->skipping_msg = 0;
  585. instance->msg_already_received_bytes = 0;
  586. dynar_clean(&instance->receive_buffer);
  587. break;
  588. default:
  589. errx(1, "qdevice_net_socket_read unhandled error %d", res);
  590. break;
  591. }
  592. return (ret_val);
  593. }
  594. static int
  595. qdevice_net_socket_write_finished(struct qdevice_net_instance *instance)
  596. {
  597. PRFileDesc *new_pr_fd;
  598. if (instance->state == QDEVICE_NET_STATE_WAITING_STARTTLS_BEING_SENT) {
  599. /*
  600. * StartTLS sent to server. Begin with TLS handshake
  601. */
  602. if ((new_pr_fd = nss_sock_start_ssl_as_client(instance->socket, QNETD_NSS_SERVER_CN,
  603. qdevice_net_nss_bad_cert_hook,
  604. qdevice_net_nss_get_client_auth_data, (void *)QDEVICE_NET_NSS_CLIENT_CERT_NICKNAME,
  605. 0, NULL)) == NULL) {
  606. qdevice_net_log_nss(LOG_ERR, "Can't start TLS");
  607. return (-1);
  608. }
  609. /*
  610. * And send init msg
  611. */
  612. if (qdevice_net_send_init(instance) != 0) {
  613. return (-1);
  614. }
  615. instance->socket = new_pr_fd;
  616. }
  617. return (0);
  618. }
  619. static int
  620. qdevice_net_socket_write(struct qdevice_net_instance *instance)
  621. {
  622. int res;
  623. int send_echo_request;
  624. /*
  625. * Echo request has extra buffer and special processing. Messages other then echo request
  626. * has higher priority, but if echo request send was not completed
  627. * it's necesary to complete it.
  628. */
  629. send_echo_request = !(instance->sending_msg && instance->echo_request_msg_already_sent_bytes == 0);
  630. if (!send_echo_request) {
  631. res = msgio_write(instance->socket, &instance->send_buffer, &instance->msg_already_sent_bytes);
  632. } else {
  633. res = msgio_write(instance->socket, &instance->echo_request_send_buffer,
  634. &instance->echo_request_msg_already_sent_bytes);
  635. }
  636. if (res == 1) {
  637. if (!send_echo_request) {
  638. instance->sending_msg = 0;
  639. if (qdevice_net_socket_write_finished(instance) == -1) {
  640. return (-1);
  641. }
  642. } else {
  643. instance->sending_echo_request_msg = 0;
  644. }
  645. }
  646. if (res == -1) {
  647. qdevice_net_log_nss(LOG_CRIT, "PR_Send returned 0");
  648. return (-1);
  649. }
  650. if (res == -2) {
  651. qdevice_net_log_nss(LOG_ERR, "Unhandled error when sending message to server");
  652. return (-1);
  653. }
  654. return (0);
  655. }
  656. #define QDEVICE_NET_POLL_NO_FDS 1
  657. #define QDEVICE_NET_POLL_SOCKET 0
  658. static int
  659. qdevice_net_poll(struct qdevice_net_instance *instance)
  660. {
  661. PRPollDesc pfds[QDEVICE_NET_POLL_NO_FDS];
  662. PRInt32 poll_res;
  663. int i;
  664. pfds[QDEVICE_NET_POLL_SOCKET].fd = instance->socket;
  665. pfds[QDEVICE_NET_POLL_SOCKET].in_flags = PR_POLL_READ;
  666. if (instance->sending_msg || instance->sending_echo_request_msg) {
  667. pfds[QDEVICE_NET_POLL_SOCKET].in_flags |= PR_POLL_WRITE;
  668. }
  669. instance->schedule_disconnect = 0;
  670. if ((poll_res = PR_Poll(pfds, QDEVICE_NET_POLL_NO_FDS,
  671. timer_list_time_to_expire(&instance->main_timer_list))) > 0) {
  672. for (i = 0; i < QDEVICE_NET_POLL_NO_FDS; i++) {
  673. if (pfds[i].out_flags & PR_POLL_READ) {
  674. switch (i) {
  675. case QDEVICE_NET_POLL_SOCKET:
  676. if (qdevice_net_socket_read(instance) == -1) {
  677. instance->schedule_disconnect = 1;
  678. }
  679. break;
  680. default:
  681. errx(1, "Unhandled read poll descriptor %u", i);
  682. break;
  683. }
  684. }
  685. if (!instance->schedule_disconnect && pfds[i].out_flags & PR_POLL_WRITE) {
  686. switch (i) {
  687. case QDEVICE_NET_POLL_SOCKET:
  688. if (qdevice_net_socket_write(instance) == -1) {
  689. instance->schedule_disconnect = 1;
  690. }
  691. break;
  692. default:
  693. errx(1, "Unhandled write poll descriptor %u", i);
  694. break;
  695. }
  696. }
  697. if (!instance->schedule_disconnect &&
  698. pfds[i].out_flags & (PR_POLL_ERR|PR_POLL_NVAL|PR_POLL_HUP|PR_POLL_EXCEPT)) {
  699. switch (i) {
  700. case QDEVICE_NET_POLL_SOCKET:
  701. qdevice_net_log(LOG_CRIT, "POLL_ERR (%u) on main socket", pfds[i].out_flags);
  702. return (-1);
  703. break;
  704. default:
  705. errx(1, "Unhandled poll err on descriptor %u", i);
  706. break;
  707. }
  708. }
  709. }
  710. }
  711. if (!instance->schedule_disconnect) {
  712. timer_list_expire(&instance->main_timer_list);
  713. }
  714. if (instance->schedule_disconnect) {
  715. /*
  716. * Schedule disconnect can be set by this function or by some timer_list callback
  717. */
  718. return (-1);
  719. }
  720. return (0);
  721. }
  722. static int
  723. qdevice_net_instance_init(struct qdevice_net_instance *instance, size_t initial_receive_size,
  724. size_t initial_send_size, size_t min_send_size, size_t max_receive_size, enum tlv_tls_supported tls_supported,
  725. uint32_t node_id, enum tlv_decision_algorithm_type decision_algorithm, uint32_t heartbeat_interval)
  726. {
  727. memset(instance, 0, sizeof(*instance));
  728. instance->initial_receive_size = initial_receive_size;
  729. instance->initial_send_size = initial_send_size;
  730. instance->min_send_size = min_send_size;
  731. instance->max_receive_size = max_receive_size;
  732. instance->node_id = node_id;
  733. instance->decision_algorithm = decision_algorithm;
  734. instance->heartbeat_interval = heartbeat_interval;
  735. dynar_init(&instance->receive_buffer, initial_receive_size);
  736. dynar_init(&instance->send_buffer, initial_send_size);
  737. dynar_init(&instance->echo_request_send_buffer, initial_send_size);
  738. timer_list_init(&instance->main_timer_list);
  739. instance->tls_supported = tls_supported;
  740. return (0);
  741. }
  742. static int
  743. qdevice_net_instance_destroy(struct qdevice_net_instance *instance)
  744. {
  745. timer_list_free(&instance->main_timer_list);
  746. dynar_destroy(&instance->receive_buffer);
  747. dynar_destroy(&instance->send_buffer);
  748. dynar_destroy(&instance->echo_request_send_buffer);
  749. return (0);
  750. }
  751. int
  752. main(void)
  753. {
  754. struct qdevice_net_instance instance;
  755. /*
  756. * Init
  757. */
  758. qdevice_net_log_init(QDEVICE_NET_LOG_TARGET_STDERR);
  759. qdevice_net_log_set_debug(1);
  760. if (nss_sock_init_nss((char *)NSS_DB_DIR) != 0) {
  761. err_nss();
  762. }
  763. if (qdevice_net_instance_init(&instance,
  764. QDEVICE_NET_INITIAL_MSG_RECEIVE_SIZE, QDEVICE_NET_INITIAL_MSG_SEND_SIZE,
  765. QDEVICE_NET_MIN_MSG_SEND_SIZE, QDEVICE_NET_MAX_MSG_RECEIVE_SIZE,
  766. QDEVICE_NET_TLS_SUPPORTED, QDEVICE_NET_NODE_ID, QDEVICE_NET_DECISION_ALGORITHM,
  767. QDEVICE_NET_HEARTBEAT_INTERVAL) == -1) {
  768. errx(1, "Can't initialize qdevice-net");
  769. }
  770. /*
  771. * Try to connect to qnetd host
  772. */
  773. instance.socket = nss_sock_create_client_socket(QNETD_HOST, QNETD_PORT, PR_AF_UNSPEC, 100);
  774. if (instance.socket == NULL) {
  775. err_nss();
  776. }
  777. if (nss_sock_set_nonblocking(instance.socket) != 0) {
  778. err_nss();
  779. }
  780. /*
  781. * Create and schedule send of preinit message to qnetd
  782. */
  783. instance.expected_msg_seq_num = 1;
  784. if (msg_create_preinit(&instance.send_buffer, QDEVICE_NET_CLUSTER_NAME, 1, instance.expected_msg_seq_num) == 0) {
  785. errx(1, "Can't allocate buffer");
  786. }
  787. if (qdevice_net_schedule_send(&instance) != 0) {
  788. errx(1, "Can't schedule send of preinit msg");
  789. }
  790. instance.state = QDEVICE_NET_STATE_WAITING_PREINIT_REPLY;
  791. /*
  792. * Main loop
  793. */
  794. while (qdevice_net_poll(&instance) == 0) {
  795. }
  796. /*
  797. * Cleanup
  798. */
  799. if (PR_Close(instance.socket) != PR_SUCCESS) {
  800. err_nss();
  801. }
  802. qdevice_net_instance_destroy(&instance);
  803. SSL_ClearSessionCache();
  804. if (NSS_Shutdown() != SECSuccess) {
  805. err_nss();
  806. }
  807. PR_Cleanup();
  808. qdevice_net_log_close();
  809. return (0);
  810. }