corosync-qdevice-net.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667
  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 <config.h>
  35. #include <stdio.h>
  36. #include <nss.h>
  37. #include <secerr.h>
  38. #include <sslerr.h>
  39. #include <pk11func.h>
  40. #include <certt.h>
  41. #include <ssl.h>
  42. #include <prio.h>
  43. #include <prnetdb.h>
  44. #include <prerror.h>
  45. #include <prinit.h>
  46. #include <getopt.h>
  47. #include <err.h>
  48. #include <keyhi.h>
  49. #include <poll.h>
  50. /*
  51. * Needed for creating nspr handle from unix fd
  52. */
  53. #include <private/pprio.h>
  54. #include <cmap.h>
  55. #include <votequorum.h>
  56. #include "qnetd-defines.h"
  57. #include "dynar.h"
  58. #include "nss-sock.h"
  59. #include "tlv.h"
  60. #include "msg.h"
  61. #include "msgio.h"
  62. #include "qnetd-log.h"
  63. #include "timer-list.h"
  64. #include "send-buffer-list.h"
  65. #define NSS_DB_DIR COROSYSCONFDIR "/qdevice-net/nssdb"
  66. /*
  67. * It's usually not a good idea to change following defines
  68. */
  69. #define QDEVICE_NET_INITIAL_MSG_RECEIVE_SIZE (1 << 15)
  70. #define QDEVICE_NET_INITIAL_MSG_SEND_SIZE (1 << 15)
  71. #define QDEVICE_NET_MIN_MSG_SEND_SIZE QDEVICE_NET_INITIAL_MSG_SEND_SIZE
  72. #define QDEVICE_NET_MAX_MSG_RECEIVE_SIZE (1 << 24)
  73. #define QNETD_NSS_SERVER_CN "Qnetd Server"
  74. #define QDEVICE_NET_NSS_CLIENT_CERT_NICKNAME "Cluster Cert"
  75. #define QDEVICE_NET_VOTEQUORUM_DEVICE_NAME "QdeviceNet"
  76. #define QDEVICE_NET_MAX_SEND_BUFFERS 10
  77. #define QDEVICE_NET_DEFAULT_ALGORITHM TLV_DECISION_ALGORITHM_TYPE_TEST
  78. #define qdevice_net_log qnetd_log
  79. #define qdevice_net_log_nss qnetd_log_nss
  80. #define qdevice_net_log_init qnetd_log_init
  81. #define qdevice_net_log_close qnetd_log_close
  82. #define qdevice_net_log_set_debug qnetd_log_set_debug
  83. #define QDEVICE_NET_LOG_TARGET_STDERR QNETD_LOG_TARGET_STDERR
  84. #define QDEVICE_NET_LOG_TARGET_SYSLOG QNETD_LOG_TARGET_SYSLOG
  85. #define MAX_CS_TRY_AGAIN 10
  86. enum qdevice_net_state {
  87. QDEVICE_NET_STATE_WAITING_PREINIT_REPLY,
  88. QDEVICE_NET_STATE_WAITING_STARTTLS_BEING_SENT,
  89. QDEVICE_NET_STATE_WAITING_INIT_REPLY,
  90. QDEVICE_NET_STATE_WAITING_SET_OPTION_REPLY,
  91. QDEVICE_NET_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS,
  92. };
  93. struct qdevice_net_instance {
  94. PRFileDesc *socket;
  95. size_t initial_send_size;
  96. size_t initial_receive_size;
  97. size_t max_receive_size;
  98. size_t min_send_size;
  99. struct dynar receive_buffer;
  100. struct send_buffer_list send_buffer_list;
  101. int skipping_msg;
  102. size_t msg_already_received_bytes;
  103. enum qdevice_net_state state;
  104. uint32_t last_msg_seq_num;
  105. uint32_t echo_request_expected_msg_seq_num;
  106. uint32_t echo_reply_received_msg_seq_num;
  107. enum tlv_tls_supported tls_supported;
  108. int using_tls;
  109. uint32_t node_id;
  110. uint32_t heartbeat_interval; /* Heartbeat interval during normal operation */
  111. uint32_t sync_heartbeat_interval; /* Heartbeat interval during corosync sync */
  112. const char *host_addr;
  113. uint16_t host_port;
  114. const char *cluster_name;
  115. enum tlv_decision_algorithm_type decision_algorithm;
  116. struct timer_list main_timer_list;
  117. struct timer_list_entry *echo_request_timer;
  118. int schedule_disconnect;
  119. cmap_handle_t cmap_handle;
  120. votequorum_handle_t votequorum_handle;
  121. PRFileDesc *votequorum_poll_fd;
  122. };
  123. static votequorum_ring_id_t global_last_received_ring_id;
  124. static void
  125. err_nss(void) {
  126. errx(1, "nss error %d: %s", PR_GetError(), PR_ErrorToString(PR_GetError(),
  127. PR_LANGUAGE_I_DEFAULT));
  128. }
  129. static SECStatus
  130. qdevice_net_nss_bad_cert_hook(void *arg, PRFileDesc *fd) {
  131. if (PR_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE ||
  132. PR_GetError() == SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE ||
  133. PR_GetError() == SEC_ERROR_CRL_EXPIRED ||
  134. PR_GetError() == SEC_ERROR_KRL_EXPIRED ||
  135. PR_GetError() == SSL_ERROR_EXPIRED_CERT_ALERT) {
  136. qdevice_net_log(LOG_WARNING, "Server certificate is expired.");
  137. return (SECSuccess);
  138. }
  139. qdevice_net_log_nss(LOG_ERR, "Server certificate verification failure.");
  140. return (SECFailure);
  141. }
  142. static SECStatus
  143. qdevice_net_nss_get_client_auth_data(void *arg, PRFileDesc *sock, struct CERTDistNamesStr *caNames,
  144. struct CERTCertificateStr **pRetCert, struct SECKEYPrivateKeyStr **pRetKey)
  145. {
  146. qdevice_net_log(LOG_DEBUG, "Sending client auth data.");
  147. return (NSS_GetClientAuthData(arg, sock, caNames, pRetCert, pRetKey));
  148. }
  149. static int
  150. qdevice_net_schedule_echo_request_send(struct qdevice_net_instance *instance)
  151. {
  152. struct send_buffer_list_entry *send_buffer;
  153. if (instance->echo_reply_received_msg_seq_num !=
  154. instance->echo_request_expected_msg_seq_num) {
  155. qdevice_net_log(LOG_ERR, "Server didn't send echo reply message on time. "
  156. "Disconnecting from server.");
  157. return (-1);
  158. }
  159. send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
  160. if (send_buffer == NULL) {
  161. qdevice_net_log(LOG_CRIT, "Can't allocate send list buffer for reply msg.");
  162. return (-1);
  163. }
  164. instance->echo_request_expected_msg_seq_num++;
  165. if (msg_create_echo_request(&send_buffer->buffer, 1,
  166. instance->echo_request_expected_msg_seq_num) == -1) {
  167. qdevice_net_log(LOG_ERR, "Can't allocate send buffer for echo request msg");
  168. return (-1);
  169. }
  170. send_buffer_list_put(&instance->send_buffer_list, send_buffer);
  171. return (0);
  172. }
  173. static void
  174. qdevice_net_log_msg_decode_error(int ret)
  175. {
  176. switch (ret) {
  177. case -1:
  178. qdevice_net_log(LOG_WARNING, "Received message with option with invalid length");
  179. break;
  180. case -2:
  181. qdevice_net_log(LOG_CRIT, "Can't allocate memory");
  182. break;
  183. case -3:
  184. qdevice_net_log(LOG_WARNING, "Received inconsistent msg (tlv len > msg size)");
  185. break;
  186. case -4:
  187. qdevice_net_log(LOG_ERR, "Received message with option with invalid value");
  188. break;
  189. default:
  190. qdevice_net_log(LOG_ERR, "Unknown error occured when decoding message");
  191. break;
  192. }
  193. }
  194. /*
  195. * -1 - Incompatible tls combination
  196. * 0 - Don't use TLS
  197. * 1 - Use TLS
  198. */
  199. static int
  200. qdevice_net_check_tls_compatibility(enum tlv_tls_supported server_tls,
  201. enum tlv_tls_supported client_tls)
  202. {
  203. int res;
  204. res = -1;
  205. switch (server_tls) {
  206. case TLV_TLS_UNSUPPORTED:
  207. switch (client_tls) {
  208. case TLV_TLS_UNSUPPORTED: res = 0; break;
  209. case TLV_TLS_SUPPORTED: res = 0; break;
  210. case TLV_TLS_REQUIRED: res = -1; break;
  211. }
  212. break;
  213. case TLV_TLS_SUPPORTED:
  214. switch (client_tls) {
  215. case TLV_TLS_UNSUPPORTED: res = 0; break;
  216. case TLV_TLS_SUPPORTED: res = 1; break;
  217. case TLV_TLS_REQUIRED: res = 1; break;
  218. }
  219. break;
  220. case TLV_TLS_REQUIRED:
  221. switch (client_tls) {
  222. case TLV_TLS_UNSUPPORTED: res = -1; break;
  223. case TLV_TLS_SUPPORTED: res = 1; break;
  224. case TLV_TLS_REQUIRED: res = 1; break;
  225. }
  226. break;
  227. }
  228. return (res);
  229. }
  230. static int
  231. qdevice_net_msg_received_preinit(struct qdevice_net_instance *instance,
  232. const struct msg_decoded *msg)
  233. {
  234. qdevice_net_log(LOG_ERR, "Received unexpected preinit message. Disconnecting from server");
  235. return (-1);
  236. }
  237. static int
  238. qdevice_net_msg_check_seq_number(struct qdevice_net_instance *instance,
  239. const struct msg_decoded *msg)
  240. {
  241. if (!msg->seq_number_set || msg->seq_number != instance->last_msg_seq_num) {
  242. qdevice_net_log(LOG_ERR, "Received message doesn't contain seq_number or "
  243. "it's not expected one.");
  244. return (-1);
  245. }
  246. return (0);
  247. }
  248. static int
  249. qdevice_net_msg_check_echo_reply_seq_number(struct qdevice_net_instance *instance,
  250. const struct msg_decoded *msg)
  251. {
  252. if (!msg->seq_number_set) {
  253. qdevice_net_log(LOG_ERR, "Received echo reply message doesn't contain seq_number.");
  254. return (-1);
  255. }
  256. if (msg->seq_number != instance->echo_request_expected_msg_seq_num) {
  257. qdevice_net_log(LOG_ERR, "Server doesn't replied in expected time. "
  258. "Closing connection");
  259. return (-1);
  260. }
  261. return (0);
  262. }
  263. static int
  264. qdevice_net_send_init(struct qdevice_net_instance *instance)
  265. {
  266. enum msg_type *supported_msgs;
  267. size_t no_supported_msgs;
  268. enum tlv_opt_type *supported_opts;
  269. size_t no_supported_opts;
  270. struct send_buffer_list_entry *send_buffer;
  271. tlv_get_supported_options(&supported_opts, &no_supported_opts);
  272. msg_get_supported_messages(&supported_msgs, &no_supported_msgs);
  273. instance->last_msg_seq_num++;
  274. send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
  275. if (send_buffer == NULL) {
  276. qdevice_net_log(LOG_ERR, "Can't allocate send list buffer for init msg");
  277. return (-1);
  278. }
  279. if (msg_create_init(&send_buffer->buffer, 1, instance->last_msg_seq_num,
  280. instance->decision_algorithm,
  281. supported_msgs, no_supported_msgs, supported_opts, no_supported_opts,
  282. instance->node_id) == 0) {
  283. qdevice_net_log(LOG_ERR, "Can't allocate send buffer for init msg");
  284. return (-1);
  285. }
  286. send_buffer_list_put(&instance->send_buffer_list, send_buffer);
  287. instance->state = QDEVICE_NET_STATE_WAITING_INIT_REPLY;
  288. return (0);
  289. }
  290. static int
  291. qdevice_net_msg_received_preinit_reply(struct qdevice_net_instance *instance,
  292. const struct msg_decoded *msg)
  293. {
  294. int res;
  295. struct send_buffer_list_entry *send_buffer;
  296. if (instance->state != QDEVICE_NET_STATE_WAITING_PREINIT_REPLY) {
  297. qdevice_net_log(LOG_ERR, "Received unexpected preinit reply message. "
  298. "Disconnecting from server");
  299. return (-1);
  300. }
  301. if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
  302. return (-1);
  303. }
  304. /*
  305. * Check TLS support
  306. */
  307. if (!msg->tls_supported_set || !msg->tls_client_cert_required_set) {
  308. qdevice_net_log(LOG_ERR, "Required tls_supported or tls_client_cert_required "
  309. "option is unset");
  310. return (-1);
  311. }
  312. res = qdevice_net_check_tls_compatibility(msg->tls_supported, instance->tls_supported);
  313. if (res == -1) {
  314. qdevice_net_log(LOG_ERR, "Incompatible tls configuration (server %u client %u)",
  315. msg->tls_supported, instance->tls_supported);
  316. return (-1);
  317. } else if (res == 1) {
  318. /*
  319. * Start TLS
  320. */
  321. send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
  322. if (send_buffer == NULL) {
  323. qdevice_net_log(LOG_ERR, "Can't allocate send list buffer for "
  324. "starttls msg");
  325. return (-1);
  326. }
  327. instance->last_msg_seq_num++;
  328. if (msg_create_starttls(&send_buffer->buffer, 1,
  329. instance->last_msg_seq_num) == 0) {
  330. qdevice_net_log(LOG_ERR, "Can't allocate send buffer for starttls msg");
  331. return (-1);
  332. }
  333. send_buffer_list_put(&instance->send_buffer_list, send_buffer);
  334. instance->state = QDEVICE_NET_STATE_WAITING_STARTTLS_BEING_SENT;
  335. } else if (res == 0) {
  336. if (qdevice_net_send_init(instance) != 0) {
  337. return (-1);
  338. }
  339. }
  340. return (0);
  341. }
  342. static int
  343. qdevice_net_msg_received_init_reply(struct qdevice_net_instance *instance,
  344. const struct msg_decoded *msg)
  345. {
  346. size_t zi;
  347. int res;
  348. struct send_buffer_list_entry *send_buffer;
  349. if (instance->state != QDEVICE_NET_STATE_WAITING_INIT_REPLY) {
  350. qdevice_net_log(LOG_ERR, "Received unexpected init reply message. "
  351. "Disconnecting from server");
  352. return (-1);
  353. }
  354. if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
  355. return (-1);
  356. }
  357. if (!msg->reply_error_code_set) {
  358. qdevice_net_log(LOG_ERR, "Received init reply message without error code."
  359. "Disconnecting from server");
  360. return (-1);
  361. }
  362. if (msg->reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
  363. qdevice_net_log(LOG_ERR, "Received init reply message with error code %"PRIu16". "
  364. "Disconnecting from server", msg->reply_error_code);
  365. return (-1);
  366. }
  367. if (!msg->server_maximum_request_size_set || !msg->server_maximum_reply_size_set) {
  368. qdevice_net_log(LOG_ERR, "Required maximum_request_size or maximum_reply_size "
  369. "option is unset");
  370. return (-1);
  371. }
  372. if (msg->supported_messages == NULL || msg->supported_options == NULL) {
  373. qdevice_net_log(LOG_ERR, "Required supported messages or supported options "
  374. "option is unset");
  375. return (-1);
  376. }
  377. if (msg->supported_decision_algorithms == NULL) {
  378. qdevice_net_log(LOG_ERR, "Required supported decision algorithms option is unset");
  379. return (-1);
  380. }
  381. if (msg->server_maximum_request_size < instance->min_send_size) {
  382. qdevice_net_log(LOG_ERR,
  383. "Server accepts maximum %zu bytes message but this client minimum "
  384. "is %zu bytes.", msg->server_maximum_request_size, instance->min_send_size);
  385. return (-1);
  386. }
  387. if (msg->server_maximum_reply_size > instance->max_receive_size) {
  388. qdevice_net_log(LOG_ERR,
  389. "Server may send message up to %zu bytes message but this client maximum "
  390. "is %zu bytes.", msg->server_maximum_reply_size, instance->max_receive_size);
  391. return (-1);
  392. }
  393. /*
  394. * Change buffer sizes
  395. */
  396. dynar_set_max_size(&instance->receive_buffer, msg->server_maximum_reply_size);
  397. send_buffer_list_set_max_buffer_size(&instance->send_buffer_list,
  398. msg->server_maximum_request_size);
  399. /*
  400. * Check if server supports decision algorithm we need
  401. */
  402. res = 0;
  403. for (zi = 0; zi < msg->no_supported_decision_algorithms && !res; zi++) {
  404. if (msg->supported_decision_algorithms[zi] == instance->decision_algorithm) {
  405. res = 1;
  406. }
  407. }
  408. if (!res) {
  409. qdevice_net_log(LOG_ERR, "Server doesn't support required decision algorithm");
  410. return (-1);
  411. }
  412. /*
  413. * Send set options message
  414. */
  415. send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
  416. if (send_buffer == NULL) {
  417. qdevice_net_log(LOG_ERR, "Can't allocate send list buffer for set option msg");
  418. return (-1);
  419. }
  420. instance->last_msg_seq_num++;
  421. if (msg_create_set_option(&send_buffer->buffer, 1, instance->last_msg_seq_num,
  422. 1, instance->heartbeat_interval) == 0) {
  423. qdevice_net_log(LOG_ERR, "Can't allocate send buffer for set option msg");
  424. return (-1);
  425. }
  426. send_buffer_list_put(&instance->send_buffer_list, send_buffer);
  427. instance->state = QDEVICE_NET_STATE_WAITING_SET_OPTION_REPLY;
  428. return (0);
  429. }
  430. static int
  431. qdevice_net_msg_received_starttls(struct qdevice_net_instance *instance,
  432. const struct msg_decoded *msg)
  433. {
  434. qdevice_net_log(LOG_ERR, "Received unexpected starttls message. Disconnecting from server");
  435. return (-1);
  436. }
  437. static int
  438. qdevice_net_msg_received_server_error(struct qdevice_net_instance *instance,
  439. const struct msg_decoded *msg)
  440. {
  441. if (!msg->reply_error_code_set) {
  442. qdevice_net_log(LOG_ERR, "Received server error without error code set. "
  443. "Disconnecting from server");
  444. } else {
  445. qdevice_net_log(LOG_ERR, "Received server error %"PRIu16". "
  446. "Disconnecting from server", msg->reply_error_code);
  447. }
  448. return (-1);
  449. }
  450. static int
  451. qdevice_net_msg_received_set_option(struct qdevice_net_instance *instance,
  452. const struct msg_decoded *msg)
  453. {
  454. qdevice_net_log(LOG_ERR, "Received unexpected set option message. "
  455. "Disconnecting from server");
  456. return (-1);
  457. }
  458. static int
  459. qdevice_net_timer_send_heartbeat(void *data1, void *data2)
  460. {
  461. struct qdevice_net_instance *instance;
  462. instance = (struct qdevice_net_instance *)data1;
  463. if (qdevice_net_schedule_echo_request_send(instance) == -1) {
  464. instance->schedule_disconnect = 1;
  465. return (0);
  466. }
  467. /*
  468. * Schedule this function callback again
  469. */
  470. return (-1);
  471. }
  472. static uint32_t
  473. qdevice_net_autogenerate_node_id(const char *addr, int clear_node_high_byte)
  474. {
  475. struct addrinfo *ainfo;
  476. struct addrinfo ahints;
  477. int ret, i;
  478. memset(&ahints, 0, sizeof(ahints));
  479. ahints.ai_socktype = SOCK_DGRAM;
  480. ahints.ai_protocol = IPPROTO_UDP;
  481. /*
  482. * Hardcoded AF_INET because autogenerated nodeid is valid only for ipv4
  483. */
  484. ahints.ai_family = AF_INET;
  485. ret = getaddrinfo(addr, NULL, &ahints, &ainfo);
  486. if (ret != 0)
  487. return (0);
  488. if (ainfo->ai_family != AF_INET) {
  489. freeaddrinfo(ainfo);
  490. return (0);
  491. }
  492. memcpy(&i, &((struct sockaddr_in *)ainfo->ai_addr)->sin_addr, sizeof(struct in_addr));
  493. freeaddrinfo(ainfo);
  494. ret = htonl(i);
  495. if (clear_node_high_byte) {
  496. ret &= 0x7FFFFFFF;
  497. }
  498. return (ret);
  499. }
  500. static int
  501. qdevice_net_get_nodelist(cmap_handle_t cmap_handle, struct node_list *list)
  502. {
  503. cs_error_t cs_err;
  504. cmap_iter_handle_t iter_handle;
  505. char key_name[CMAP_KEYNAME_MAXLEN + 1];
  506. char tmp_key[CMAP_KEYNAME_MAXLEN + 1];
  507. int res;
  508. int ret_value;
  509. unsigned int node_pos;
  510. uint32_t node_id;
  511. uint32_t data_center_id;
  512. char *tmp_str;
  513. char *addr0_str;
  514. int clear_node_high_byte;
  515. ret_value = 0;
  516. node_list_init(list);
  517. cs_err = cmap_iter_init(cmap_handle, "nodelist.node.", &iter_handle);
  518. if (cs_err != CS_OK) {
  519. return (-1);
  520. }
  521. while ((cs_err = cmap_iter_next(cmap_handle, iter_handle, key_name, NULL, NULL)) == CS_OK) {
  522. res = sscanf(key_name, "nodelist.node.%u.%s", &node_pos, tmp_key);
  523. if (res != 2) {
  524. continue;
  525. }
  526. if (strcmp(tmp_key, "ring0_addr") != 0) {
  527. continue;
  528. }
  529. snprintf(tmp_key, CMAP_KEYNAME_MAXLEN, "nodelist.node.%u.nodeid", node_pos);
  530. cs_err = cmap_get_uint32(cmap_handle, tmp_key, &node_id);
  531. if (cs_err == CS_ERR_NOT_EXIST) {
  532. /*
  533. * Nodeid doesn't exists -> autogenerate node id
  534. */
  535. clear_node_high_byte = 0;
  536. if (cmap_get_string(cmap_handle, "totem.clear_node_high_bit", &tmp_str) == CS_OK) {
  537. if (strcmp (tmp_str, "yes") == 0) {
  538. clear_node_high_byte = 1;
  539. }
  540. free(tmp_str);
  541. }
  542. if (cmap_get_string(cmap_handle, key_name, &addr0_str) != CS_OK) {
  543. return (-1);
  544. }
  545. node_id = qdevice_net_autogenerate_node_id(addr0_str, clear_node_high_byte);
  546. free(addr0_str);
  547. } else if (cs_err != CS_OK) {
  548. ret_value = -1;
  549. goto iter_finalize;
  550. }
  551. snprintf(tmp_key, CMAP_KEYNAME_MAXLEN, "nodelist.node.%u.datacenterid", node_pos);
  552. if (cmap_get_uint32(cmap_handle, tmp_key, &data_center_id) != CS_OK) {
  553. data_center_id = 0;
  554. }
  555. if (node_list_add(list, node_id, data_center_id, TLV_NODE_STATE_NOT_SET) == NULL) {
  556. ret_value = -1;
  557. goto iter_finalize;
  558. }
  559. }
  560. iter_finalize:
  561. cmap_iter_finalize(cmap_handle, iter_handle);
  562. if (ret_value != 0) {
  563. node_list_free(list);
  564. }
  565. return (ret_value);
  566. }
  567. static
  568. int qdevice_net_get_cmap_config_version(cmap_handle_t cmap_handle, uint64_t *config_version)
  569. {
  570. int res;
  571. if (cmap_get_uint64(cmap_handle, "totem.config_version", config_version) == CS_OK) {
  572. res = 1;
  573. } else {
  574. *config_version = 0;
  575. res = 0;
  576. }
  577. return (res);
  578. }
  579. static int
  580. qdevice_net_send_config_node_list(struct qdevice_net_instance *instance, int initial)
  581. {
  582. struct node_list nlist;
  583. struct send_buffer_list_entry *send_buffer;
  584. uint64_t config_version;
  585. int send_config_version;
  586. /*
  587. * Send initial node list
  588. */
  589. if (qdevice_net_get_nodelist(instance->cmap_handle, &nlist) != 0) {
  590. qdevice_net_log(LOG_ERR, "Can't get initial configuration node list.");
  591. return (-1);
  592. }
  593. send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
  594. if (send_buffer == NULL) {
  595. qdevice_net_log(LOG_ERR, "Can't allocate send list buffer for config "
  596. "node list msg");
  597. node_list_free(&nlist);
  598. return (-1);
  599. }
  600. send_config_version = qdevice_net_get_cmap_config_version(instance->cmap_handle,
  601. &config_version);
  602. instance->last_msg_seq_num++;
  603. if (msg_create_node_list(&send_buffer->buffer, instance->last_msg_seq_num,
  604. (initial ? TLV_NODE_LIST_TYPE_INITIAL_CONFIG : TLV_NODE_LIST_TYPE_CHANGED_CONFIG),
  605. 0, NULL, send_config_version, config_version, 0, TLV_QUORATE_INQUORATE, &nlist) == 0) {
  606. qdevice_net_log(LOG_ERR, "Can't allocate send buffer for config list msg");
  607. node_list_free(&nlist);
  608. return (-1);
  609. }
  610. send_buffer_list_put(&instance->send_buffer_list, send_buffer);
  611. return (0);
  612. }
  613. static int
  614. qdevice_net_register_votequorum_callbacks(struct qdevice_net_instance *instance)
  615. {
  616. cs_error_t res;
  617. if ((res = votequorum_trackstart(instance->votequorum_handle, 0, CS_TRACK_CHANGES)) != CS_OK) {
  618. qdevice_net_log(LOG_ERR, "Can't start tracking votequorum changes. Error %s",
  619. cs_strerror(res));
  620. return (-1);
  621. }
  622. return (0);
  623. }
  624. static int
  625. qdevice_net_msg_received_set_option_reply(struct qdevice_net_instance *instance,
  626. const struct msg_decoded *msg)
  627. {
  628. if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
  629. return (-1);
  630. }
  631. if (!msg->decision_algorithm_set || !msg->heartbeat_interval_set) {
  632. qdevice_net_log(LOG_ERR, "Received set option reply message without "
  633. "required options. Disconnecting from server");
  634. }
  635. if (msg->decision_algorithm != instance->decision_algorithm ||
  636. msg->heartbeat_interval != instance->heartbeat_interval) {
  637. qdevice_net_log(LOG_ERR, "Server doesn't accept sent decision algorithm or "
  638. "heartbeat interval.");
  639. return (-1);
  640. }
  641. /*
  642. * Server accepted heartbeat interval -> schedule regular sending of echo request
  643. */
  644. if (instance->heartbeat_interval > 0) {
  645. instance->echo_request_timer = timer_list_add(&instance->main_timer_list,
  646. instance->heartbeat_interval, qdevice_net_timer_send_heartbeat,
  647. (void *)instance, NULL);
  648. if (instance->echo_request_timer == NULL) {
  649. qdevice_net_log(LOG_ERR, "Can't schedule regular sending of heartbeat.");
  650. return (-1);
  651. }
  652. }
  653. /*
  654. * Now we can finally really send node list and initialize qdevice
  655. */
  656. if (qdevice_net_send_config_node_list(instance, 1) != 0) {
  657. return (-1);
  658. }
  659. if (qdevice_net_register_votequorum_callbacks(instance) != 0) {
  660. return (-1);
  661. }
  662. instance->state = QDEVICE_NET_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS;
  663. return (0);
  664. }
  665. static int
  666. qdevice_net_msg_received_echo_request(struct qdevice_net_instance *instance,
  667. const struct msg_decoded *msg)
  668. {
  669. qdevice_net_log(LOG_ERR, "Received unexpected echo request message. "
  670. "Disconnecting from server");
  671. return (-1);
  672. }
  673. static int
  674. qdevice_net_msg_received_echo_reply(struct qdevice_net_instance *instance,
  675. const struct msg_decoded *msg)
  676. {
  677. if (qdevice_net_msg_check_echo_reply_seq_number(instance, msg) != 0) {
  678. return (-1);
  679. }
  680. instance->echo_reply_received_msg_seq_num = msg->seq_number;
  681. return (0);
  682. }
  683. static int
  684. qdevice_net_msg_received_node_list(struct qdevice_net_instance *instance,
  685. const struct msg_decoded *msg)
  686. {
  687. qdevice_net_log(LOG_ERR, "Received unexpected echo request message. "
  688. "Disconnecting from server");
  689. return (-1);
  690. }
  691. static int
  692. qdevice_net_msg_received_node_list_reply(struct qdevice_net_instance *instance,
  693. const struct msg_decoded *msg)
  694. {
  695. qdevice_net_log(LOG_INFO, "Received node list reply %u", msg->vote);
  696. return (0);
  697. }
  698. static int
  699. qdevice_net_msg_received(struct qdevice_net_instance *instance)
  700. {
  701. struct msg_decoded msg;
  702. int res;
  703. int ret_val;
  704. msg_decoded_init(&msg);
  705. res = msg_decode(&instance->receive_buffer, &msg);
  706. if (res != 0) {
  707. /*
  708. * Error occurred. Disconnect.
  709. */
  710. qdevice_net_log_msg_decode_error(res);
  711. qdevice_net_log(LOG_ERR, "Disconnecting from server");
  712. return (-1);
  713. }
  714. ret_val = 0;
  715. switch (msg.type) {
  716. case MSG_TYPE_PREINIT:
  717. ret_val = qdevice_net_msg_received_preinit(instance, &msg);
  718. break;
  719. case MSG_TYPE_PREINIT_REPLY:
  720. ret_val = qdevice_net_msg_received_preinit_reply(instance, &msg);
  721. break;
  722. case MSG_TYPE_STARTTLS:
  723. ret_val = qdevice_net_msg_received_starttls(instance, &msg);
  724. break;
  725. case MSG_TYPE_SERVER_ERROR:
  726. ret_val = qdevice_net_msg_received_server_error(instance, &msg);
  727. break;
  728. case MSG_TYPE_INIT_REPLY:
  729. ret_val = qdevice_net_msg_received_init_reply(instance, &msg);
  730. break;
  731. case MSG_TYPE_SET_OPTION:
  732. ret_val = qdevice_net_msg_received_set_option(instance, &msg);
  733. break;
  734. case MSG_TYPE_SET_OPTION_REPLY:
  735. ret_val = qdevice_net_msg_received_set_option_reply(instance, &msg);
  736. break;
  737. case MSG_TYPE_ECHO_REQUEST:
  738. ret_val = qdevice_net_msg_received_echo_request(instance, &msg);
  739. break;
  740. case MSG_TYPE_ECHO_REPLY:
  741. ret_val = qdevice_net_msg_received_echo_reply(instance, &msg);
  742. break;
  743. case MSG_TYPE_NODE_LIST:
  744. ret_val = qdevice_net_msg_received_node_list(instance, &msg);
  745. break;
  746. case MSG_TYPE_NODE_LIST_REPLY:
  747. ret_val = qdevice_net_msg_received_node_list_reply(instance, &msg);
  748. break;
  749. default:
  750. qdevice_net_log(LOG_ERR, "Received unsupported message %u. "
  751. "Disconnecting from server", msg.type);
  752. ret_val = -1;
  753. break;
  754. }
  755. msg_decoded_destroy(&msg);
  756. return (ret_val);
  757. }
  758. /*
  759. * -1 means end of connection (EOF) or some other unhandled error. 0 = success
  760. */
  761. static int
  762. qdevice_net_socket_read(struct qdevice_net_instance *instance)
  763. {
  764. int res;
  765. int ret_val;
  766. int orig_skipping_msg;
  767. orig_skipping_msg = instance->skipping_msg;
  768. res = msgio_read(instance->socket, &instance->receive_buffer,
  769. &instance->msg_already_received_bytes, &instance->skipping_msg);
  770. if (!orig_skipping_msg && instance->skipping_msg) {
  771. qdevice_net_log(LOG_DEBUG, "msgio_read set skipping_msg");
  772. }
  773. ret_val = 0;
  774. switch (res) {
  775. case 0:
  776. /*
  777. * Partial read
  778. */
  779. break;
  780. case -1:
  781. qdevice_net_log(LOG_DEBUG, "Server closed connection");
  782. ret_val = -1;
  783. break;
  784. case -2:
  785. qdevice_net_log_nss(LOG_ERR, "Unhandled error when reading from server. "
  786. "Disconnecting from server");
  787. ret_val = -1;
  788. break;
  789. case -3:
  790. qdevice_net_log(LOG_ERR, "Can't store message header from server. "
  791. "Disconnecting from server");
  792. ret_val = -1;
  793. break;
  794. case -4:
  795. qdevice_net_log(LOG_ERR, "Can't store message from server. "
  796. "Disconnecting from server");
  797. ret_val = -1;
  798. break;
  799. case -5:
  800. qdevice_net_log(LOG_WARNING, "Server sent unsupported msg type %u. "
  801. "Disconnecting from server", msg_get_type(&instance->receive_buffer));
  802. ret_val = -1;
  803. break;
  804. case -6:
  805. qdevice_net_log(LOG_WARNING,
  806. "Server wants to send too long message %u bytes. Disconnecting from server",
  807. msg_get_len(&instance->receive_buffer));
  808. ret_val = -1;
  809. break;
  810. case 1:
  811. /*
  812. * Full message received / skipped
  813. */
  814. if (!instance->skipping_msg) {
  815. if (qdevice_net_msg_received(instance) == -1) {
  816. ret_val = -1;
  817. }
  818. } else {
  819. errx(1, "net_socket_read in skipping msg state");
  820. }
  821. instance->skipping_msg = 0;
  822. instance->msg_already_received_bytes = 0;
  823. dynar_clean(&instance->receive_buffer);
  824. break;
  825. default:
  826. errx(1, "qdevice_net_socket_read unhandled error %d", res);
  827. break;
  828. }
  829. return (ret_val);
  830. }
  831. static int
  832. qdevice_net_socket_write_finished(struct qdevice_net_instance *instance)
  833. {
  834. PRFileDesc *new_pr_fd;
  835. if (instance->state == QDEVICE_NET_STATE_WAITING_STARTTLS_BEING_SENT) {
  836. /*
  837. * StartTLS sent to server. Begin with TLS handshake
  838. */
  839. if ((new_pr_fd = nss_sock_start_ssl_as_client(instance->socket, QNETD_NSS_SERVER_CN,
  840. qdevice_net_nss_bad_cert_hook,
  841. qdevice_net_nss_get_client_auth_data,
  842. (void *)QDEVICE_NET_NSS_CLIENT_CERT_NICKNAME, 0, NULL)) == NULL) {
  843. qdevice_net_log_nss(LOG_ERR, "Can't start TLS");
  844. return (-1);
  845. }
  846. /*
  847. * And send init msg
  848. */
  849. if (qdevice_net_send_init(instance) != 0) {
  850. return (-1);
  851. }
  852. instance->socket = new_pr_fd;
  853. }
  854. return (0);
  855. }
  856. static int
  857. qdevice_net_socket_write(struct qdevice_net_instance *instance)
  858. {
  859. int res;
  860. struct send_buffer_list_entry *send_buffer;
  861. enum msg_type sent_msg_type;
  862. send_buffer = send_buffer_list_get_active(&instance->send_buffer_list);
  863. if (send_buffer == NULL) {
  864. qdevice_net_log(LOG_CRIT, "send_buffer_list_get_active returned NULL");
  865. return (-1);
  866. }
  867. res = msgio_write(instance->socket, &send_buffer->buffer,
  868. &send_buffer->msg_already_sent_bytes);
  869. if (res == 1) {
  870. sent_msg_type = msg_get_type(&send_buffer->buffer);
  871. send_buffer_list_delete(&instance->send_buffer_list, send_buffer);
  872. if (sent_msg_type != MSG_TYPE_ECHO_REQUEST) {
  873. if (qdevice_net_socket_write_finished(instance) == -1) {
  874. return (-1);
  875. }
  876. }
  877. }
  878. if (res == -1) {
  879. qdevice_net_log_nss(LOG_CRIT, "PR_Send returned 0");
  880. return (-1);
  881. }
  882. if (res == -2) {
  883. qdevice_net_log_nss(LOG_ERR, "Unhandled error when sending message to server");
  884. return (-1);
  885. }
  886. return (0);
  887. }
  888. #define QDEVICE_NET_POLL_NO_FDS 2
  889. #define QDEVICE_NET_POLL_SOCKET 0
  890. #define QDEVICE_NET_POLL_VOTEQUORUM 1
  891. static int
  892. qdevice_net_poll(struct qdevice_net_instance *instance)
  893. {
  894. PRPollDesc pfds[QDEVICE_NET_POLL_NO_FDS];
  895. PRInt32 poll_res;
  896. int i;
  897. pfds[QDEVICE_NET_POLL_SOCKET].fd = instance->socket;
  898. pfds[QDEVICE_NET_POLL_SOCKET].in_flags = PR_POLL_READ;
  899. if (!send_buffer_list_empty(&instance->send_buffer_list)) {
  900. pfds[QDEVICE_NET_POLL_SOCKET].in_flags |= PR_POLL_WRITE;
  901. }
  902. pfds[QDEVICE_NET_POLL_VOTEQUORUM].fd = instance->votequorum_poll_fd;
  903. pfds[QDEVICE_NET_POLL_VOTEQUORUM].in_flags = PR_POLL_READ;
  904. instance->schedule_disconnect = 0;
  905. if ((poll_res = PR_Poll(pfds, QDEVICE_NET_POLL_NO_FDS,
  906. timer_list_time_to_expire(&instance->main_timer_list))) > 0) {
  907. for (i = 0; i < QDEVICE_NET_POLL_NO_FDS; i++) {
  908. if (pfds[i].out_flags & PR_POLL_READ) {
  909. switch (i) {
  910. case QDEVICE_NET_POLL_SOCKET:
  911. if (qdevice_net_socket_read(instance) == -1) {
  912. instance->schedule_disconnect = 1;
  913. }
  914. break;
  915. case QDEVICE_NET_POLL_VOTEQUORUM:
  916. if (votequorum_dispatch(instance->votequorum_handle,
  917. CS_DISPATCH_ALL) != CS_OK) {
  918. errx(1, "Can't dispatch votequorum messages");
  919. }
  920. break;
  921. default:
  922. errx(1, "Unhandled read poll descriptor %u", i);
  923. break;
  924. }
  925. }
  926. if (!instance->schedule_disconnect && pfds[i].out_flags & PR_POLL_WRITE) {
  927. switch (i) {
  928. case QDEVICE_NET_POLL_SOCKET:
  929. if (qdevice_net_socket_write(instance) == -1) {
  930. instance->schedule_disconnect = 1;
  931. }
  932. break;
  933. default:
  934. errx(1, "Unhandled write poll descriptor %u", i);
  935. break;
  936. }
  937. }
  938. if (!instance->schedule_disconnect &&
  939. pfds[i].out_flags &
  940. (PR_POLL_ERR|PR_POLL_NVAL|PR_POLL_HUP|PR_POLL_EXCEPT)) {
  941. switch (i) {
  942. case QDEVICE_NET_POLL_SOCKET:
  943. qdevice_net_log(LOG_CRIT, "POLL_ERR (%u) on main socket",
  944. pfds[i].out_flags);
  945. return (-1);
  946. break;
  947. default:
  948. errx(1, "Unhandled poll err on descriptor %u", i);
  949. break;
  950. }
  951. }
  952. }
  953. }
  954. if (!instance->schedule_disconnect) {
  955. timer_list_expire(&instance->main_timer_list);
  956. }
  957. if (instance->schedule_disconnect) {
  958. /*
  959. * Schedule disconnect can be set by this function, by some timer_list callback
  960. * or cmap/votequorum callbacks
  961. */
  962. return (-1);
  963. }
  964. return (0);
  965. }
  966. static int
  967. qdevice_net_instance_init(struct qdevice_net_instance *instance, size_t initial_receive_size,
  968. size_t initial_send_size, size_t min_send_size, size_t max_receive_size,
  969. enum tlv_tls_supported tls_supported, uint32_t node_id,
  970. enum tlv_decision_algorithm_type decision_algorithm, uint32_t heartbeat_interval,
  971. const char *host_addr, uint16_t host_port, const char *cluster_name)
  972. {
  973. memset(instance, 0, sizeof(*instance));
  974. instance->initial_receive_size = initial_receive_size;
  975. instance->initial_send_size = initial_send_size;
  976. instance->min_send_size = min_send_size;
  977. instance->max_receive_size = max_receive_size;
  978. instance->node_id = node_id;
  979. instance->decision_algorithm = decision_algorithm;
  980. instance->heartbeat_interval = heartbeat_interval;
  981. instance->host_addr = host_addr;
  982. instance->host_port = host_port;
  983. instance->cluster_name = cluster_name;
  984. dynar_init(&instance->receive_buffer, initial_receive_size);
  985. send_buffer_list_init(&instance->send_buffer_list, QDEVICE_NET_MAX_SEND_BUFFERS,
  986. initial_send_size);
  987. timer_list_init(&instance->main_timer_list);
  988. instance->tls_supported = tls_supported;
  989. return (0);
  990. }
  991. static int
  992. qdevice_net_instance_destroy(struct qdevice_net_instance *instance)
  993. {
  994. timer_list_free(&instance->main_timer_list);
  995. dynar_destroy(&instance->receive_buffer);
  996. send_buffer_list_free(&instance->send_buffer_list);
  997. /*
  998. * Close cmap and votequorum connections
  999. */
  1000. if (votequorum_qdevice_unregister(instance->votequorum_handle,
  1001. QDEVICE_NET_VOTEQUORUM_DEVICE_NAME) != CS_OK) {
  1002. qdevice_net_log_nss(LOG_WARNING, "Unable to unregister votequorum device");
  1003. }
  1004. votequorum_finalize(instance->votequorum_handle);
  1005. cmap_finalize(instance->cmap_handle);
  1006. return (0);
  1007. }
  1008. static void
  1009. qdevice_net_init_cmap(cmap_handle_t *handle)
  1010. {
  1011. cs_error_t res;
  1012. int no_retries;
  1013. no_retries = 0;
  1014. while ((res = cmap_initialize(handle)) == CS_ERR_TRY_AGAIN &&
  1015. no_retries++ < MAX_CS_TRY_AGAIN) {
  1016. poll(NULL, 0, 1000);
  1017. }
  1018. if (res != CS_OK) {
  1019. errx(1, "Failed to initialize the cmap API. Error %s", cs_strerror(res));
  1020. }
  1021. }
  1022. /*
  1023. * Check string to value on, off, yes, no, 0, 1. Return 1 if value is on, yes or 1, 0 if
  1024. * value is off, no or 0 and -1 otherwise.
  1025. */
  1026. static int
  1027. qdevice_net_parse_bool_str(const char *str)
  1028. {
  1029. if (strcasecmp(str, "yes") == 0 ||
  1030. strcasecmp(str, "on") == 0 ||
  1031. strcasecmp(str, "1") == 0) {
  1032. return (1);
  1033. } else if (strcasecmp(str, "no") == 0 ||
  1034. strcasecmp(str, "off") == 0 ||
  1035. strcasecmp(str, "0") == 0) {
  1036. return (0);
  1037. }
  1038. return (-1);
  1039. }
  1040. static void
  1041. qdevice_net_instance_init_from_cmap(struct qdevice_net_instance *instance,
  1042. cmap_handle_t cmap_handle)
  1043. {
  1044. uint32_t node_id;
  1045. enum tlv_tls_supported tls_supported;
  1046. int i;
  1047. char *str;
  1048. enum tlv_decision_algorithm_type decision_algorithm;
  1049. uint32_t heartbeat_interval;
  1050. uint32_t sync_heartbeat_interval;
  1051. char *host_addr;
  1052. int host_port;
  1053. char *ep;
  1054. char *cluster_name;
  1055. /*
  1056. * Check if provider is net
  1057. */
  1058. if (cmap_get_string(cmap_handle, "quorum.device.model", &str) != CS_OK) {
  1059. errx(1, "Can't read quorum.device.model cmap key.");
  1060. }
  1061. if (strcmp(str, "net") != 0) {
  1062. free(str);
  1063. errx(1, "Configured device model is not net. "
  1064. "This qdevice provider is only for net.");
  1065. }
  1066. free(str);
  1067. /*
  1068. * Get nodeid
  1069. */
  1070. if (cmap_get_uint32(cmap_handle, "runtime.votequorum.this_node_id", &node_id) != CS_OK) {
  1071. errx(1, "Unable to retrive this node nodeid.");
  1072. }
  1073. /*
  1074. * Check tls
  1075. */
  1076. if (cmap_get_string(cmap_handle, "quorum.device.net.tls", &str) == CS_OK) {
  1077. if ((i = qdevice_net_parse_bool_str(str)) == -1) {
  1078. free(str);
  1079. errx(1, "quorum.device.net.tls value is not valid.");
  1080. }
  1081. if (i == 1) {
  1082. tls_supported = TLV_TLS_SUPPORTED;
  1083. } else {
  1084. tls_supported = TLV_TLS_UNSUPPORTED;
  1085. }
  1086. free(str);
  1087. }
  1088. /*
  1089. * Host
  1090. */
  1091. if (cmap_get_string(cmap_handle, "quorum.device.net.host", &str) != CS_OK) {
  1092. free(str);
  1093. errx(1, "Qdevice net daemon address is not defined (quorum.device.net.host)");
  1094. }
  1095. host_addr = str;
  1096. if (cmap_get_string(cmap_handle, "quorum.device.net.port", &str) == CS_OK) {
  1097. host_port = strtol(str, &ep, 10);
  1098. if (host_port <= 0 || host_port > ((uint16_t)~0) || *ep != '\0') {
  1099. errx(1, "quorum.device.net.port must be in range 0-65535");
  1100. }
  1101. free(str);
  1102. } else {
  1103. host_port = QNETD_DEFAULT_HOST_PORT;
  1104. }
  1105. /*
  1106. * Cluster name
  1107. */
  1108. if (cmap_get_string(cmap_handle, "totem.cluster_name", &str) != CS_OK) {
  1109. errx(1, "Cluster name (totem.cluster_name) has to be defined.");
  1110. }
  1111. cluster_name = str;
  1112. /*
  1113. * Configure timeouts
  1114. */
  1115. if (cmap_get_uint32(cmap_handle, "quorum.device.timeout", &heartbeat_interval) != CS_OK) {
  1116. heartbeat_interval = VOTEQUORUM_QDEVICE_DEFAULT_TIMEOUT;
  1117. }
  1118. heartbeat_interval = heartbeat_interval * 0.8;
  1119. if (cmap_get_uint32(cmap_handle, "quorum.device.sync_timeout",
  1120. &sync_heartbeat_interval) != CS_OK) {
  1121. sync_heartbeat_interval = VOTEQUORUM_QDEVICE_DEFAULT_SYNC_TIMEOUT;
  1122. }
  1123. sync_heartbeat_interval = sync_heartbeat_interval * 0.8;
  1124. /*
  1125. * Choose decision algorithm
  1126. */
  1127. if (cmap_get_string(cmap_handle, "quorum.device.net.algorithm", &str) != CS_OK) {
  1128. decision_algorithm = QDEVICE_NET_DEFAULT_ALGORITHM;
  1129. } else {
  1130. if (strcmp(str, "test") == 0) {
  1131. decision_algorithm = TLV_DECISION_ALGORITHM_TYPE_TEST;
  1132. } else if (strcmp(str, "ffsplit") == 0) {
  1133. decision_algorithm = TLV_DECISION_ALGORITHM_TYPE_FFSPLIT;
  1134. } else {
  1135. errx(1, "Unknown decision algorithm %s", str);
  1136. }
  1137. free(str);
  1138. }
  1139. /*
  1140. * Really initialize instance
  1141. */
  1142. if (qdevice_net_instance_init(instance,
  1143. QDEVICE_NET_INITIAL_MSG_RECEIVE_SIZE, QDEVICE_NET_INITIAL_MSG_SEND_SIZE,
  1144. QDEVICE_NET_MIN_MSG_SEND_SIZE, QDEVICE_NET_MAX_MSG_RECEIVE_SIZE,
  1145. tls_supported, node_id, decision_algorithm,
  1146. heartbeat_interval,
  1147. host_addr, host_port, cluster_name) == -1) {
  1148. errx(1, "Can't initialize qdevice-net");
  1149. }
  1150. instance->cmap_handle = cmap_handle;
  1151. }
  1152. static enum tlv_node_state
  1153. qdevice_net_convert_votequorum_to_tlv_node_state(uint32_t votequorum_node_state)
  1154. {
  1155. enum tlv_node_state res;
  1156. switch (votequorum_node_state) {
  1157. case VOTEQUORUM_NODESTATE_MEMBER: res = TLV_NODE_STATE_MEMBER; break;
  1158. case VOTEQUORUM_NODESTATE_DEAD: res = TLV_NODE_STATE_DEAD; break;
  1159. case VOTEQUORUM_NODESTATE_LEAVING: res = TLV_NODE_STATE_LEAVING; break;
  1160. default:
  1161. errx(1, "qdevice_net_convert_votequorum_to_tlv_node_state: Unhandled votequorum "
  1162. "node state %"PRIu32, votequorum_node_state);
  1163. break;
  1164. }
  1165. return (res);
  1166. }
  1167. static int
  1168. qdevice_net_send_membership_node_list(struct qdevice_net_instance *instance,
  1169. enum tlv_quorate quorate, const struct tlv_ring_id *ring_id,
  1170. uint32_t node_list_entries, votequorum_node_t node_list[])
  1171. {
  1172. struct node_list nlist;
  1173. struct send_buffer_list_entry *send_buffer;
  1174. uint64_t config_version;
  1175. int send_config_version;
  1176. uint32_t i;
  1177. node_list_init(&nlist);
  1178. for (i = 0; i < node_list_entries; i++) {
  1179. if (node_list[i].nodeid == 0) {
  1180. continue;
  1181. }
  1182. if (node_list_add(&nlist, node_list[i].nodeid, 0,
  1183. qdevice_net_convert_votequorum_to_tlv_node_state(node_list[i].state)) == NULL) {
  1184. qdevice_net_log(LOG_ERR, "Can't allocate membership node list.");
  1185. node_list_free(&nlist);
  1186. return (-1);
  1187. }
  1188. }
  1189. send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
  1190. if (send_buffer == NULL) {
  1191. qdevice_net_log(LOG_ERR, "Can't allocate send list buffer for config "
  1192. "node list msg");
  1193. node_list_free(&nlist);
  1194. return (-1);
  1195. }
  1196. instance->last_msg_seq_num++;
  1197. send_config_version = qdevice_net_get_cmap_config_version(instance->cmap_handle,
  1198. &config_version);
  1199. if (msg_create_node_list(&send_buffer->buffer, instance->last_msg_seq_num,
  1200. TLV_NODE_LIST_TYPE_MEMBERSHIP,
  1201. 1, ring_id, send_config_version, config_version, 1, quorate, &nlist) == 0) {
  1202. qdevice_net_log(LOG_ERR, "Can't allocate send buffer for config list msg");
  1203. node_list_free(&nlist);
  1204. return (-1);
  1205. }
  1206. send_buffer_list_put(&instance->send_buffer_list, send_buffer);
  1207. return (0);
  1208. }
  1209. static void
  1210. qdevice_net_convert_votequorum_to_tlv_ring_id(struct tlv_ring_id *tlv_rid,
  1211. const votequorum_ring_id_t *votequorum_rid)
  1212. {
  1213. tlv_rid->node_id = votequorum_rid->nodeid;
  1214. tlv_rid->seq = votequorum_rid->seq;
  1215. }
  1216. static void
  1217. qdevice_net_votequorum_notification(votequorum_handle_t votequorum_handle,
  1218. uint64_t context, uint32_t quorate,
  1219. votequorum_ring_id_t votequorum_ring_id,
  1220. uint32_t node_list_entries, votequorum_node_t node_list[])
  1221. {
  1222. struct qdevice_net_instance *instance;
  1223. struct tlv_ring_id ring_id;
  1224. if (votequorum_context_get(votequorum_handle, (void **)&instance) != CS_OK) {
  1225. errx(1, "Fatal error. Can't get votequorum context");
  1226. }
  1227. qdevice_net_convert_votequorum_to_tlv_ring_id(&ring_id, &votequorum_ring_id);
  1228. if (qdevice_net_send_membership_node_list(instance,
  1229. (quorate ? TLV_QUORATE_QUORATE : TLV_QUORATE_INQUORATE),
  1230. &ring_id, node_list_entries, node_list) != 0) {
  1231. /*
  1232. * Fatal error -> schedule disconnect
  1233. */
  1234. instance->schedule_disconnect = 1;
  1235. }
  1236. memcpy(&global_last_received_ring_id, &ring_id, sizeof(ring_id));
  1237. }
  1238. static void
  1239. qdevice_net_init_votequorum(struct qdevice_net_instance *instance)
  1240. {
  1241. votequorum_callbacks_t votequorum_callbacks;
  1242. votequorum_handle_t votequorum_handle;
  1243. cs_error_t res;
  1244. int no_retries;
  1245. int fd;
  1246. memset(&votequorum_callbacks, 0, sizeof(votequorum_callbacks));
  1247. votequorum_callbacks.votequorum_notify_fn = qdevice_net_votequorum_notification;
  1248. no_retries = 0;
  1249. while ((res = votequorum_initialize(&votequorum_handle,
  1250. &votequorum_callbacks)) == CS_ERR_TRY_AGAIN && no_retries++ < MAX_CS_TRY_AGAIN) {
  1251. poll(NULL, 0, 1000);
  1252. }
  1253. if (res != CS_OK) {
  1254. errx(1, "Failed to initialize the votequorum API. Error %s", cs_strerror(res));
  1255. }
  1256. if ((res = votequorum_qdevice_register(votequorum_handle,
  1257. QDEVICE_NET_VOTEQUORUM_DEVICE_NAME)) != CS_OK) {
  1258. errx(1, "Can't register votequorum device. Error %s", cs_strerror(res));
  1259. }
  1260. if ((res = votequorum_context_set(votequorum_handle, (void *)instance)) != CS_OK) {
  1261. errx(1, "Can't set votequorum context. Error %s", cs_strerror(res));
  1262. }
  1263. instance->votequorum_handle = votequorum_handle;
  1264. votequorum_fd_get(votequorum_handle, &fd);
  1265. if ((instance->votequorum_poll_fd = PR_CreateSocketPollFd(fd)) == NULL) {
  1266. err_nss();
  1267. }
  1268. }
  1269. int
  1270. main(void)
  1271. {
  1272. struct qdevice_net_instance instance;
  1273. cmap_handle_t cmap_handle;
  1274. struct send_buffer_list_entry *send_buffer;
  1275. /*
  1276. * Init
  1277. */
  1278. qdevice_net_init_cmap(&cmap_handle);
  1279. qdevice_net_instance_init_from_cmap(&instance, cmap_handle);
  1280. qdevice_net_log_init(QDEVICE_NET_LOG_TARGET_STDERR);
  1281. qdevice_net_log_set_debug(1);
  1282. if (nss_sock_init_nss((instance.tls_supported != TLV_TLS_UNSUPPORTED ?
  1283. (char *)NSS_DB_DIR : NULL)) != 0) {
  1284. err_nss();
  1285. }
  1286. /*
  1287. * Try to connect to qnetd host
  1288. */
  1289. instance.socket = nss_sock_create_client_socket(instance.host_addr, instance.host_port,
  1290. PR_AF_UNSPEC, 100);
  1291. if (instance.socket == NULL) {
  1292. err_nss();
  1293. }
  1294. if (nss_sock_set_nonblocking(instance.socket) != 0) {
  1295. err_nss();
  1296. }
  1297. qdevice_net_init_votequorum(&instance);
  1298. /*
  1299. * Create and schedule send of preinit message to qnetd
  1300. */
  1301. send_buffer = send_buffer_list_get_new(&instance.send_buffer_list);
  1302. if (send_buffer == NULL) {
  1303. errx(1, "Can't allocate send buffer list");
  1304. }
  1305. instance.last_msg_seq_num = 1;
  1306. if (msg_create_preinit(&send_buffer->buffer, instance.cluster_name, 1,
  1307. instance.last_msg_seq_num) == 0) {
  1308. errx(1, "Can't allocate buffer");
  1309. }
  1310. send_buffer_list_put(&instance.send_buffer_list, send_buffer);
  1311. instance.state = QDEVICE_NET_STATE_WAITING_PREINIT_REPLY;
  1312. /*
  1313. * Main loop
  1314. */
  1315. while (qdevice_net_poll(&instance) == 0) {
  1316. }
  1317. /*
  1318. * Cleanup
  1319. */
  1320. if (PR_Close(instance.socket) != PR_SUCCESS) {
  1321. err_nss();
  1322. }
  1323. qdevice_net_instance_destroy(&instance);
  1324. SSL_ClearSessionCache();
  1325. if (NSS_Shutdown() != SECSuccess) {
  1326. err_nss();
  1327. }
  1328. PR_Cleanup();
  1329. qdevice_net_log_close();
  1330. return (0);
  1331. }