tlv.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165
  1. /*
  2. * Copyright (c) 2015-2020 Red Hat, Inc.
  3. *
  4. * All rights reserved.
  5. *
  6. * Author: Jan Friesse (jfriesse@redhat.com)
  7. *
  8. * This software licensed under BSD license, the text of which follows:
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * - Neither the name of the Red Hat, Inc. nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  32. * THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include <sys/types.h>
  35. #include <arpa/inet.h>
  36. #include <assert.h>
  37. #include <inttypes.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. /*
  41. * 64-bit variant of ntoh is not exactly standard...
  42. */
  43. #if defined(__linux__)
  44. #include <endian.h>
  45. #elif defined(__FreeBSD__) || defined(__NetBSD__)
  46. #include <sys/endian.h>
  47. #elif defined(__OpenBSD__)
  48. #define be64toh(x) betoh64(x)
  49. #endif
  50. #include "tlv.h"
  51. #define TLV_TYPE_LENGTH 2
  52. #define TLV_LENGTH_LENGTH 2
  53. #define TLV_STATIC_SUPPORTED_OPTIONS_SIZE 24
  54. enum tlv_opt_type tlv_static_supported_options[TLV_STATIC_SUPPORTED_OPTIONS_SIZE] = {
  55. TLV_OPT_MSG_SEQ_NUMBER,
  56. TLV_OPT_CLUSTER_NAME,
  57. TLV_OPT_TLS_SUPPORTED,
  58. TLV_OPT_TLS_CLIENT_CERT_REQUIRED,
  59. TLV_OPT_SUPPORTED_MESSAGES,
  60. TLV_OPT_SUPPORTED_OPTIONS,
  61. TLV_OPT_REPLY_ERROR_CODE,
  62. TLV_OPT_SERVER_MAXIMUM_REQUEST_SIZE,
  63. TLV_OPT_SERVER_MAXIMUM_REPLY_SIZE,
  64. TLV_OPT_NODE_ID,
  65. TLV_OPT_SUPPORTED_DECISION_ALGORITHMS,
  66. TLV_OPT_DECISION_ALGORITHM,
  67. TLV_OPT_HEARTBEAT_INTERVAL,
  68. TLV_OPT_RING_ID,
  69. TLV_OPT_CONFIG_VERSION,
  70. TLV_OPT_DATA_CENTER_ID,
  71. TLV_OPT_NODE_STATE,
  72. TLV_OPT_NODE_INFO,
  73. TLV_OPT_NODE_LIST_TYPE,
  74. TLV_OPT_VOTE,
  75. TLV_OPT_QUORATE,
  76. TLV_OPT_TIE_BREAKER,
  77. TLV_OPT_HEURISTICS,
  78. TLV_OPT_KEEP_ACTIVE_PARTITION_TIE_BREAKER,
  79. };
  80. int
  81. tlv_add(struct dynar *msg, enum tlv_opt_type opt_type, uint16_t opt_len, const void *value)
  82. {
  83. uint16_t nlen;
  84. uint16_t nopt_type;
  85. if (dynar_size(msg) + sizeof(nopt_type) + sizeof(nlen) + opt_len > dynar_max_size(msg)) {
  86. return (-1);
  87. }
  88. nopt_type = htons((uint16_t)opt_type);
  89. nlen = htons(opt_len);
  90. dynar_cat(msg, &nopt_type, sizeof(nopt_type));
  91. dynar_cat(msg, &nlen, sizeof(nlen));
  92. dynar_cat(msg, value, opt_len);
  93. return (0);
  94. }
  95. int
  96. tlv_add_u32(struct dynar *msg, enum tlv_opt_type opt_type, uint32_t u32)
  97. {
  98. uint32_t nu32;
  99. nu32 = htonl(u32);
  100. return (tlv_add(msg, opt_type, sizeof(nu32), &nu32));
  101. }
  102. int
  103. tlv_add_u8(struct dynar *msg, enum tlv_opt_type opt_type, uint8_t u8)
  104. {
  105. return (tlv_add(msg, opt_type, sizeof(u8), &u8));
  106. }
  107. int
  108. tlv_add_u16(struct dynar *msg, enum tlv_opt_type opt_type, uint16_t u16)
  109. {
  110. uint16_t nu16;
  111. nu16 = htons(u16);
  112. return (tlv_add(msg, opt_type, sizeof(nu16), &nu16));
  113. }
  114. int
  115. tlv_add_u64(struct dynar *msg, enum tlv_opt_type opt_type, uint64_t u64)
  116. {
  117. uint64_t nu64;
  118. nu64 = htobe64(u64);
  119. return (tlv_add(msg, opt_type, sizeof(nu64), &nu64));
  120. }
  121. int
  122. tlv_add_string(struct dynar *msg, enum tlv_opt_type opt_type, const char *str)
  123. {
  124. return (tlv_add(msg, opt_type, strlen(str), str));
  125. }
  126. int
  127. tlv_add_msg_seq_number(struct dynar *msg, uint32_t msg_seq_number)
  128. {
  129. return (tlv_add_u32(msg, TLV_OPT_MSG_SEQ_NUMBER, msg_seq_number));
  130. }
  131. int
  132. tlv_add_cluster_name(struct dynar *msg, const char *cluster_name)
  133. {
  134. return (tlv_add_string(msg, TLV_OPT_CLUSTER_NAME, cluster_name));
  135. }
  136. int
  137. tlv_add_tls_supported(struct dynar *msg, enum tlv_tls_supported tls_supported)
  138. {
  139. return (tlv_add_u8(msg, TLV_OPT_TLS_SUPPORTED, tls_supported));
  140. }
  141. int
  142. tlv_add_tls_client_cert_required(struct dynar *msg, int tls_client_cert_required)
  143. {
  144. return (tlv_add_u8(msg, TLV_OPT_TLS_CLIENT_CERT_REQUIRED, tls_client_cert_required));
  145. }
  146. int
  147. tlv_add_u16_array(struct dynar *msg, enum tlv_opt_type opt_type, const uint16_t *array,
  148. size_t array_size)
  149. {
  150. size_t i;
  151. uint16_t *nu16a;
  152. uint16_t opt_len;
  153. int res;
  154. nu16a = malloc(sizeof(uint16_t) * array_size);
  155. if (nu16a == NULL) {
  156. return (-1);
  157. }
  158. for (i = 0; i < array_size; i++) {
  159. nu16a[i] = htons(array[i]);
  160. }
  161. opt_len = sizeof(uint16_t) * array_size;
  162. res = tlv_add(msg, opt_type, opt_len, nu16a);
  163. free(nu16a);
  164. return (res);
  165. }
  166. int
  167. tlv_add_supported_options(struct dynar *msg, const enum tlv_opt_type *supported_options,
  168. size_t no_supported_options)
  169. {
  170. uint16_t *u16a;
  171. size_t i;
  172. int res;
  173. u16a = malloc(sizeof(*u16a) * no_supported_options);
  174. if (u16a == NULL) {
  175. return (-1);
  176. }
  177. for (i = 0; i < no_supported_options; i++) {
  178. u16a[i] = (uint16_t)supported_options[i];
  179. }
  180. res = (tlv_add_u16_array(msg, TLV_OPT_SUPPORTED_OPTIONS, u16a, no_supported_options));
  181. free(u16a);
  182. return (res);
  183. }
  184. int
  185. tlv_add_supported_decision_algorithms(struct dynar *msg,
  186. const enum tlv_decision_algorithm_type *supported_algorithms, size_t no_supported_algorithms)
  187. {
  188. uint16_t *u16a;
  189. size_t i;
  190. int res;
  191. u16a = malloc(sizeof(*u16a) * no_supported_algorithms);
  192. if (u16a == NULL) {
  193. return (-1);
  194. }
  195. for (i = 0; i < no_supported_algorithms; i++) {
  196. u16a[i] = (uint16_t)supported_algorithms[i];
  197. }
  198. res = (tlv_add_u16_array(msg, TLV_OPT_SUPPORTED_DECISION_ALGORITHMS, u16a,
  199. no_supported_algorithms));
  200. free(u16a);
  201. return (res);
  202. }
  203. int
  204. tlv_add_reply_error_code(struct dynar *msg, enum tlv_reply_error_code error_code)
  205. {
  206. return (tlv_add_u16(msg, TLV_OPT_REPLY_ERROR_CODE, (uint16_t)error_code));
  207. }
  208. int
  209. tlv_add_server_maximum_request_size(struct dynar *msg, size_t server_maximum_request_size)
  210. {
  211. return (tlv_add_u32(msg, TLV_OPT_SERVER_MAXIMUM_REQUEST_SIZE, server_maximum_request_size));
  212. }
  213. int
  214. tlv_add_server_maximum_reply_size(struct dynar *msg, size_t server_maximum_reply_size)
  215. {
  216. return (tlv_add_u32(msg, TLV_OPT_SERVER_MAXIMUM_REPLY_SIZE, server_maximum_reply_size));
  217. }
  218. int
  219. tlv_add_node_id(struct dynar *msg, uint32_t node_id)
  220. {
  221. return (tlv_add_u32(msg, TLV_OPT_NODE_ID, node_id));
  222. }
  223. int
  224. tlv_add_decision_algorithm(struct dynar *msg, enum tlv_decision_algorithm_type decision_algorithm)
  225. {
  226. return (tlv_add_u16(msg, TLV_OPT_DECISION_ALGORITHM, (uint16_t)decision_algorithm));
  227. }
  228. int
  229. tlv_add_heartbeat_interval(struct dynar *msg, uint32_t heartbeat_interval)
  230. {
  231. return (tlv_add_u32(msg, TLV_OPT_HEARTBEAT_INTERVAL, heartbeat_interval));
  232. }
  233. int
  234. tlv_add_ring_id(struct dynar *msg, const struct tlv_ring_id *ring_id)
  235. {
  236. uint64_t nu64;
  237. uint32_t nu32;
  238. char tmp_buf[12];
  239. nu32 = htonl(ring_id->node_id);
  240. nu64 = htobe64(ring_id->seq);
  241. memcpy(tmp_buf, &nu32, sizeof(nu32));
  242. memcpy(tmp_buf + sizeof(nu32), &nu64, sizeof(nu64));
  243. return (tlv_add(msg, TLV_OPT_RING_ID, sizeof(tmp_buf), tmp_buf));
  244. }
  245. int
  246. tlv_add_tie_breaker(struct dynar *msg, const struct tlv_tie_breaker *tie_breaker)
  247. {
  248. uint32_t nu32;
  249. uint8_t u8;
  250. char tmp_buf[5];
  251. u8 = tie_breaker->mode;
  252. nu32 = (tie_breaker->mode == TLV_TIE_BREAKER_MODE_NODE_ID ?
  253. htonl(tie_breaker->node_id) : 0);
  254. memcpy(tmp_buf, &u8, sizeof(u8));
  255. memcpy(tmp_buf + sizeof(u8), &nu32, sizeof(nu32));
  256. return (tlv_add(msg, TLV_OPT_TIE_BREAKER, sizeof(tmp_buf), tmp_buf));
  257. }
  258. int
  259. tlv_add_config_version(struct dynar *msg, uint64_t config_version)
  260. {
  261. return (tlv_add_u64(msg, TLV_OPT_CONFIG_VERSION, config_version));
  262. }
  263. int
  264. tlv_add_data_center_id(struct dynar *msg, uint32_t data_center_id)
  265. {
  266. return (tlv_add_u32(msg, TLV_OPT_DATA_CENTER_ID, data_center_id));
  267. }
  268. int
  269. tlv_add_node_state(struct dynar *msg, enum tlv_node_state node_state)
  270. {
  271. return (tlv_add_u8(msg, TLV_OPT_NODE_STATE, node_state));
  272. }
  273. int
  274. tlv_add_node_info(struct dynar *msg, const struct tlv_node_info *node_info)
  275. {
  276. struct dynar opt_value;
  277. int res;
  278. res = 0;
  279. /*
  280. * Create sub message,
  281. */
  282. dynar_init(&opt_value, 1024);
  283. if ((res = tlv_add_node_id(&opt_value, node_info->node_id)) != 0) {
  284. goto exit_dynar_destroy;
  285. }
  286. if (node_info->data_center_id != 0) {
  287. if ((res = tlv_add_data_center_id(&opt_value, node_info->data_center_id)) != 0) {
  288. goto exit_dynar_destroy;
  289. }
  290. }
  291. if (node_info->node_state != TLV_NODE_STATE_NOT_SET) {
  292. if ((res = tlv_add_node_state(&opt_value, node_info->node_state)) != 0) {
  293. goto exit_dynar_destroy;
  294. }
  295. }
  296. res = tlv_add(msg, TLV_OPT_NODE_INFO, dynar_size(&opt_value), dynar_data(&opt_value));
  297. if (res != 0) {
  298. goto exit_dynar_destroy;
  299. }
  300. exit_dynar_destroy:
  301. dynar_destroy(&opt_value);
  302. return (res);
  303. }
  304. int
  305. tlv_add_node_list_type(struct dynar *msg, enum tlv_node_list_type node_list_type)
  306. {
  307. return (tlv_add_u8(msg, TLV_OPT_NODE_LIST_TYPE, node_list_type));
  308. }
  309. int
  310. tlv_add_vote(struct dynar *msg, enum tlv_vote vote)
  311. {
  312. return (tlv_add_u8(msg, TLV_OPT_VOTE, vote));
  313. }
  314. int
  315. tlv_add_quorate(struct dynar *msg, enum tlv_quorate quorate)
  316. {
  317. return (tlv_add_u8(msg, TLV_OPT_QUORATE, quorate));
  318. }
  319. int
  320. tlv_add_heuristics(struct dynar *msg, enum tlv_heuristics heuristics)
  321. {
  322. if (heuristics == TLV_HEURISTICS_UNDEFINED) {
  323. return (-1);
  324. }
  325. return (tlv_add_u8(msg, TLV_OPT_HEURISTICS, heuristics));
  326. }
  327. int
  328. tlv_add_keep_active_partition_tie_breaker(struct dynar *msg,
  329. enum tlv_keep_active_partition_tie_breaker enabled)
  330. {
  331. return (tlv_add_u8(msg, TLV_OPT_KEEP_ACTIVE_PARTITION_TIE_BREAKER, enabled));
  332. }
  333. void
  334. tlv_iter_init_str(const char *msg, size_t msg_len, size_t msg_header_len,
  335. struct tlv_iterator *tlv_iter)
  336. {
  337. tlv_iter->msg = msg;
  338. tlv_iter->msg_len = msg_len;
  339. tlv_iter->current_pos = 0;
  340. tlv_iter->msg_header_len = msg_header_len;
  341. tlv_iter->iter_next_called = 0;
  342. }
  343. void
  344. tlv_iter_init(const struct dynar *msg, size_t msg_header_len, struct tlv_iterator *tlv_iter)
  345. {
  346. tlv_iter_init_str(dynar_data(msg), dynar_size(msg), msg_header_len, tlv_iter);
  347. }
  348. enum tlv_opt_type
  349. tlv_iter_get_type(const struct tlv_iterator *tlv_iter)
  350. {
  351. uint16_t ntype;
  352. uint16_t type;
  353. memcpy(&ntype, tlv_iter->msg + tlv_iter->current_pos, sizeof(ntype));
  354. type = ntohs(ntype);
  355. return (type);
  356. }
  357. uint16_t
  358. tlv_iter_get_len(const struct tlv_iterator *tlv_iter)
  359. {
  360. uint16_t nlen;
  361. uint16_t len;
  362. memcpy(&nlen, tlv_iter->msg + tlv_iter->current_pos + TLV_TYPE_LENGTH, sizeof(nlen));
  363. len = ntohs(nlen);
  364. return (len);
  365. }
  366. const char *
  367. tlv_iter_get_data(const struct tlv_iterator *tlv_iter)
  368. {
  369. return (tlv_iter->msg + tlv_iter->current_pos + TLV_TYPE_LENGTH + TLV_LENGTH_LENGTH);
  370. }
  371. int
  372. tlv_iter_next(struct tlv_iterator *tlv_iter)
  373. {
  374. uint16_t len;
  375. if (tlv_iter->iter_next_called == 0) {
  376. tlv_iter->iter_next_called = 1;
  377. tlv_iter->current_pos = tlv_iter->msg_header_len;
  378. goto check_tlv_validity;
  379. }
  380. len = tlv_iter_get_len(tlv_iter);
  381. if (tlv_iter->current_pos + TLV_TYPE_LENGTH + TLV_LENGTH_LENGTH + len >=
  382. tlv_iter->msg_len) {
  383. return (0);
  384. }
  385. tlv_iter->current_pos += TLV_TYPE_LENGTH + TLV_LENGTH_LENGTH + len;
  386. check_tlv_validity:
  387. /*
  388. * Check if tlv is valid = is not larger than whole message
  389. */
  390. len = tlv_iter_get_len(tlv_iter);
  391. if (tlv_iter->current_pos + TLV_TYPE_LENGTH + TLV_LENGTH_LENGTH + len > tlv_iter->msg_len) {
  392. return (-1);
  393. }
  394. return (1);
  395. }
  396. int
  397. tlv_iter_decode_u32(struct tlv_iterator *tlv_iter, uint32_t *res)
  398. {
  399. const char *opt_data;
  400. uint16_t opt_len;
  401. uint32_t nu32;
  402. opt_len = tlv_iter_get_len(tlv_iter);
  403. opt_data = tlv_iter_get_data(tlv_iter);
  404. if (opt_len != sizeof(nu32)) {
  405. return (-1);
  406. }
  407. memcpy(&nu32, opt_data, sizeof(nu32));
  408. *res = ntohl(nu32);
  409. return (0);
  410. }
  411. int
  412. tlv_iter_decode_u8(struct tlv_iterator *tlv_iter, uint8_t *res)
  413. {
  414. const char *opt_data;
  415. uint16_t opt_len;
  416. opt_len = tlv_iter_get_len(tlv_iter);
  417. opt_data = tlv_iter_get_data(tlv_iter);
  418. if (opt_len != sizeof(*res)) {
  419. return (-1);
  420. }
  421. memcpy(res, opt_data, sizeof(*res));
  422. return (0);
  423. }
  424. int
  425. tlv_iter_decode_client_cert_required(struct tlv_iterator *tlv_iter, uint8_t *client_cert_required)
  426. {
  427. return (tlv_iter_decode_u8(tlv_iter, client_cert_required));
  428. }
  429. int
  430. tlv_iter_decode_str(struct tlv_iterator *tlv_iter, char **str, size_t *str_len)
  431. {
  432. const char *opt_data;
  433. uint16_t opt_len;
  434. char *tmp_str;
  435. opt_len = tlv_iter_get_len(tlv_iter);
  436. opt_data = tlv_iter_get_data(tlv_iter);
  437. tmp_str = malloc(opt_len + 1);
  438. if (tmp_str == NULL) {
  439. return (-1);
  440. }
  441. memcpy(tmp_str, opt_data, opt_len);
  442. tmp_str[opt_len] = '\0';
  443. *str = tmp_str;
  444. *str_len = opt_len;
  445. return (0);
  446. }
  447. int
  448. tlv_iter_decode_u16_array(struct tlv_iterator *tlv_iter, uint16_t **u16a, size_t *no_items)
  449. {
  450. uint16_t opt_len;
  451. uint16_t *u16a_res;
  452. size_t i;
  453. opt_len = tlv_iter_get_len(tlv_iter);
  454. if (opt_len % sizeof(uint16_t) != 0) {
  455. return (-1);
  456. }
  457. *no_items = opt_len / sizeof(uint16_t);
  458. u16a_res = malloc(sizeof(uint16_t) * *no_items);
  459. if (u16a_res == NULL) {
  460. return (-2);
  461. }
  462. memcpy(u16a_res, tlv_iter_get_data(tlv_iter), opt_len);
  463. for (i = 0; i < *no_items; i++) {
  464. u16a_res[i] = ntohs(u16a_res[i]);
  465. }
  466. *u16a = u16a_res;
  467. return (0);
  468. }
  469. int
  470. tlv_iter_decode_supported_options(struct tlv_iterator *tlv_iter,
  471. enum tlv_opt_type **supported_options, size_t *no_supported_options)
  472. {
  473. uint16_t *u16a;
  474. enum tlv_opt_type *tlv_opt_array;
  475. size_t i;
  476. int res;
  477. res = tlv_iter_decode_u16_array(tlv_iter, &u16a, no_supported_options);
  478. if (res != 0) {
  479. return (res);
  480. }
  481. tlv_opt_array = malloc(sizeof(enum tlv_opt_type) * *no_supported_options);
  482. if (tlv_opt_array == NULL) {
  483. free(u16a);
  484. return (-2);
  485. }
  486. for (i = 0; i < *no_supported_options; i++) {
  487. tlv_opt_array[i] = (enum tlv_opt_type)u16a[i];
  488. }
  489. free(u16a);
  490. *supported_options = tlv_opt_array;
  491. return (0);
  492. }
  493. int
  494. tlv_iter_decode_supported_decision_algorithms(struct tlv_iterator *tlv_iter,
  495. enum tlv_decision_algorithm_type **supported_decision_algorithms,
  496. size_t *no_supported_decision_algorithms)
  497. {
  498. uint16_t *u16a;
  499. enum tlv_decision_algorithm_type *tlv_decision_algorithm_type_array;
  500. size_t i;
  501. int res;
  502. res = tlv_iter_decode_u16_array(tlv_iter, &u16a, no_supported_decision_algorithms);
  503. if (res != 0) {
  504. return (res);
  505. }
  506. tlv_decision_algorithm_type_array = malloc(
  507. sizeof(enum tlv_decision_algorithm_type) * *no_supported_decision_algorithms);
  508. if (tlv_decision_algorithm_type_array == NULL) {
  509. free(u16a);
  510. return (-2);
  511. }
  512. for (i = 0; i < *no_supported_decision_algorithms; i++) {
  513. tlv_decision_algorithm_type_array[i] = (enum tlv_decision_algorithm_type)u16a[i];
  514. }
  515. free(u16a);
  516. *supported_decision_algorithms = tlv_decision_algorithm_type_array;
  517. return (0);
  518. }
  519. int
  520. tlv_iter_decode_u16(struct tlv_iterator *tlv_iter, uint16_t *u16)
  521. {
  522. const char *opt_data;
  523. uint16_t opt_len;
  524. uint16_t nu16;
  525. opt_len = tlv_iter_get_len(tlv_iter);
  526. opt_data = tlv_iter_get_data(tlv_iter);
  527. if (opt_len != sizeof(nu16)) {
  528. return (-1);
  529. }
  530. memcpy(&nu16, opt_data, sizeof(nu16));
  531. *u16 = ntohs(nu16);
  532. return (0);
  533. }
  534. int
  535. tlv_iter_decode_u64(struct tlv_iterator *tlv_iter, uint64_t *u64)
  536. {
  537. const char *opt_data;
  538. uint64_t opt_len;
  539. uint64_t nu64;
  540. opt_len = tlv_iter_get_len(tlv_iter);
  541. opt_data = tlv_iter_get_data(tlv_iter);
  542. if (opt_len != sizeof(nu64)) {
  543. return (-1);
  544. }
  545. memcpy(&nu64, opt_data, sizeof(nu64));
  546. *u64 = be64toh(nu64);
  547. return (0);
  548. }
  549. int
  550. tlv_iter_decode_reply_error_code(struct tlv_iterator *tlv_iter,
  551. enum tlv_reply_error_code *reply_error_code)
  552. {
  553. return (tlv_iter_decode_u16(tlv_iter, (uint16_t *)reply_error_code));
  554. }
  555. int
  556. tlv_iter_decode_tls_supported(struct tlv_iterator *tlv_iter, enum tlv_tls_supported *tls_supported)
  557. {
  558. uint8_t u8;
  559. enum tlv_tls_supported tmp_tls_supported;
  560. if (tlv_iter_decode_u8(tlv_iter, &u8) != 0) {
  561. return (-1);
  562. }
  563. tmp_tls_supported = u8;
  564. if (tmp_tls_supported != TLV_TLS_UNSUPPORTED &&
  565. tmp_tls_supported != TLV_TLS_SUPPORTED &&
  566. tmp_tls_supported != TLV_TLS_REQUIRED) {
  567. return (-4);
  568. }
  569. *tls_supported = tmp_tls_supported;
  570. return (0);
  571. }
  572. int
  573. tlv_iter_decode_decision_algorithm(struct tlv_iterator *tlv_iter,
  574. enum tlv_decision_algorithm_type *decision_algorithm)
  575. {
  576. uint16_t u16;
  577. if (tlv_iter_decode_u16(tlv_iter, &u16) != 0) {
  578. return (-1);
  579. }
  580. *decision_algorithm = (enum tlv_decision_algorithm_type)u16;
  581. return (0);
  582. }
  583. int
  584. tlv_iter_decode_ring_id(struct tlv_iterator *tlv_iter, struct tlv_ring_id *ring_id)
  585. {
  586. const char *opt_data;
  587. uint16_t opt_len;
  588. uint32_t nu32;
  589. uint64_t nu64;
  590. char tmp_buf[12];
  591. opt_len = tlv_iter_get_len(tlv_iter);
  592. opt_data = tlv_iter_get_data(tlv_iter);
  593. if (opt_len != sizeof(tmp_buf)) {
  594. return (-1);
  595. }
  596. memcpy(&nu32, opt_data, sizeof(nu32));
  597. memcpy(&nu64, opt_data + sizeof(nu32), sizeof(nu64));
  598. ring_id->node_id = ntohl(nu32);
  599. ring_id->seq = be64toh(nu64);
  600. return (0);
  601. }
  602. int
  603. tlv_iter_decode_tie_breaker(struct tlv_iterator *tlv_iter, struct tlv_tie_breaker *tie_breaker)
  604. {
  605. const char *opt_data;
  606. uint16_t opt_len;
  607. uint32_t nu32;
  608. uint8_t u8;
  609. enum tlv_tie_breaker_mode tie_breaker_mode;
  610. char tmp_buf[5];
  611. opt_len = tlv_iter_get_len(tlv_iter);
  612. opt_data = tlv_iter_get_data(tlv_iter);
  613. if (opt_len != sizeof(tmp_buf)) {
  614. return (-1);
  615. }
  616. memcpy(&u8, opt_data, sizeof(u8));
  617. tie_breaker_mode = u8;
  618. if (tie_breaker_mode != TLV_TIE_BREAKER_MODE_LOWEST &&
  619. tie_breaker_mode != TLV_TIE_BREAKER_MODE_HIGHEST &&
  620. tie_breaker_mode != TLV_TIE_BREAKER_MODE_NODE_ID) {
  621. return (-4);
  622. }
  623. memcpy(&nu32, opt_data + sizeof(u8), sizeof(nu32));
  624. tie_breaker->mode = tie_breaker_mode;
  625. tie_breaker->node_id = (tie_breaker->mode == TLV_TIE_BREAKER_MODE_NODE_ID ?
  626. ntohl(nu32) : 0);
  627. return (0);
  628. }
  629. int
  630. tlv_iter_decode_node_state(struct tlv_iterator *tlv_iter, enum tlv_node_state *node_state)
  631. {
  632. uint8_t u8;
  633. enum tlv_node_state tmp_node_state;
  634. if (tlv_iter_decode_u8(tlv_iter, &u8) != 0) {
  635. return (-1);
  636. }
  637. tmp_node_state = u8;
  638. if (tmp_node_state != TLV_NODE_STATE_MEMBER &&
  639. tmp_node_state != TLV_NODE_STATE_DEAD &&
  640. tmp_node_state != TLV_NODE_STATE_LEAVING) {
  641. return (-4);
  642. }
  643. *node_state = tmp_node_state;
  644. return (0);
  645. }
  646. int
  647. tlv_iter_decode_node_info(struct tlv_iterator *tlv_iter, struct tlv_node_info *node_info)
  648. {
  649. struct tlv_iterator data_tlv_iter;
  650. int iter_res;
  651. int res;
  652. enum tlv_opt_type opt_type;
  653. struct tlv_node_info tmp_node_info;
  654. memset(&tmp_node_info, 0, sizeof(tmp_node_info));
  655. tlv_iter_init_str(tlv_iter_get_data(tlv_iter), tlv_iter_get_len(tlv_iter), 0,
  656. &data_tlv_iter);
  657. while ((iter_res = tlv_iter_next(&data_tlv_iter)) > 0) {
  658. opt_type = tlv_iter_get_type(&data_tlv_iter);
  659. switch (opt_type) {
  660. case TLV_OPT_NODE_ID:
  661. if ((res = tlv_iter_decode_u32(&data_tlv_iter,
  662. &tmp_node_info.node_id)) != 0) {
  663. return (res);
  664. }
  665. break;
  666. case TLV_OPT_DATA_CENTER_ID:
  667. if ((res = tlv_iter_decode_u32(&data_tlv_iter,
  668. &tmp_node_info.data_center_id)) != 0) {
  669. return (res);
  670. }
  671. break;
  672. case TLV_OPT_NODE_STATE:
  673. if ((res = tlv_iter_decode_node_state(&data_tlv_iter,
  674. &tmp_node_info.node_state)) != 0) {
  675. return (res);
  676. }
  677. break;
  678. default:
  679. /*
  680. * Other options are not processed
  681. */
  682. break;
  683. }
  684. }
  685. if (iter_res != 0) {
  686. return (-3);
  687. }
  688. if (tmp_node_info.node_id == 0) {
  689. return (-4);
  690. }
  691. memcpy(node_info, &tmp_node_info, sizeof(tmp_node_info));
  692. return (0);
  693. }
  694. int
  695. tlv_iter_decode_node_list_type(struct tlv_iterator *tlv_iter,
  696. enum tlv_node_list_type *node_list_type)
  697. {
  698. uint8_t u8;
  699. enum tlv_node_list_type tmp_node_list_type;
  700. if (tlv_iter_decode_u8(tlv_iter, &u8) != 0) {
  701. return (-1);
  702. }
  703. tmp_node_list_type = u8;
  704. if (tmp_node_list_type != TLV_NODE_LIST_TYPE_INITIAL_CONFIG &&
  705. tmp_node_list_type != TLV_NODE_LIST_TYPE_CHANGED_CONFIG &&
  706. tmp_node_list_type != TLV_NODE_LIST_TYPE_MEMBERSHIP &&
  707. tmp_node_list_type != TLV_NODE_LIST_TYPE_QUORUM) {
  708. return (-4);
  709. }
  710. *node_list_type = tmp_node_list_type;
  711. return (0);
  712. }
  713. int
  714. tlv_iter_decode_vote(struct tlv_iterator *tlv_iter, enum tlv_vote *vote)
  715. {
  716. uint8_t u8;
  717. enum tlv_vote tmp_vote;
  718. if (tlv_iter_decode_u8(tlv_iter, &u8) != 0) {
  719. return (-1);
  720. }
  721. tmp_vote = u8;
  722. if (tmp_vote != TLV_VOTE_ACK &&
  723. tmp_vote != TLV_VOTE_NACK &&
  724. tmp_vote != TLV_VOTE_ASK_LATER &&
  725. tmp_vote != TLV_VOTE_WAIT_FOR_REPLY &&
  726. tmp_vote != TLV_VOTE_NO_CHANGE) {
  727. return (-4);
  728. }
  729. *vote = tmp_vote;
  730. return (0);
  731. }
  732. int
  733. tlv_iter_decode_quorate(struct tlv_iterator *tlv_iter, enum tlv_quorate *quorate)
  734. {
  735. uint8_t u8;
  736. enum tlv_quorate tmp_quorate;
  737. if (tlv_iter_decode_u8(tlv_iter, &u8) != 0) {
  738. return (-1);
  739. }
  740. tmp_quorate = u8;
  741. if (tmp_quorate != TLV_QUORATE_QUORATE &&
  742. tmp_quorate != TLV_QUORATE_INQUORATE) {
  743. return (-4);
  744. }
  745. *quorate = tmp_quorate;
  746. return (0);
  747. }
  748. int
  749. tlv_iter_decode_heuristics(struct tlv_iterator *tlv_iter, enum tlv_heuristics *heuristics)
  750. {
  751. uint8_t u8;
  752. enum tlv_heuristics tmp_heuristics;
  753. if (tlv_iter_decode_u8(tlv_iter, &u8) != 0) {
  754. return (-1);
  755. }
  756. tmp_heuristics = u8;
  757. if (tmp_heuristics != TLV_HEURISTICS_PASS &&
  758. tmp_heuristics != TLV_HEURISTICS_FAIL) {
  759. return (-4);
  760. }
  761. *heuristics = tmp_heuristics;
  762. return (0);
  763. }
  764. int
  765. tlv_iter_decode_keep_active_partition_tie_breaker(struct tlv_iterator *tlv_iter,
  766. enum tlv_keep_active_partition_tie_breaker *keep_active_partition_tie_breaker)
  767. {
  768. uint8_t u8;
  769. enum tlv_keep_active_partition_tie_breaker tmp_keep_active_partition_tb;
  770. if (tlv_iter_decode_u8(tlv_iter, &u8) != 0) {
  771. return (-1);
  772. }
  773. tmp_keep_active_partition_tb = u8;
  774. if (tmp_keep_active_partition_tb != TLV_KEEP_ACTIVE_PARTITION_TIE_BREAKER_DISABLED &&
  775. tmp_keep_active_partition_tb != TLV_KEEP_ACTIVE_PARTITION_TIE_BREAKER_ENABLED) {
  776. return (-4);
  777. }
  778. *keep_active_partition_tie_breaker = tmp_keep_active_partition_tb;
  779. return (0);
  780. }
  781. void
  782. tlv_get_supported_options(enum tlv_opt_type **supported_options, size_t *no_supported_options)
  783. {
  784. *supported_options = tlv_static_supported_options;
  785. *no_supported_options = TLV_STATIC_SUPPORTED_OPTIONS_SIZE;
  786. }
  787. int
  788. tlv_ring_id_eq(const struct tlv_ring_id *rid1, const struct tlv_ring_id *rid2)
  789. {
  790. return (rid1->node_id == rid2->node_id && rid1->seq == rid2->seq);
  791. }
  792. int
  793. tlv_tie_breaker_eq(const struct tlv_tie_breaker *tb1, const struct tlv_tie_breaker *tb2)
  794. {
  795. if (tb1->mode == tb2->mode && tb1->mode == TLV_TIE_BREAKER_MODE_NODE_ID) {
  796. return (tb1->node_id == tb2->node_id);
  797. }
  798. return (tb1->mode == tb2->mode);
  799. }
  800. const char *
  801. tlv_vote_to_str(enum tlv_vote vote)
  802. {
  803. switch (vote) {
  804. case TLV_VOTE_UNDEFINED: break;
  805. case TLV_VOTE_ACK: return ("ACK"); break;
  806. case TLV_VOTE_NACK: return ("NACK"); break;
  807. case TLV_VOTE_ASK_LATER: return ("Ask later"); break;
  808. case TLV_VOTE_WAIT_FOR_REPLY: return ("Wait for reply"); break;
  809. case TLV_VOTE_NO_CHANGE: return ("No change"); break;
  810. }
  811. return ("Unknown vote value");
  812. }
  813. const char *
  814. tlv_node_state_to_str(enum tlv_node_state state)
  815. {
  816. switch (state) {
  817. case TLV_NODE_STATE_NOT_SET: return ("not set"); break;
  818. case TLV_NODE_STATE_MEMBER: return ("member"); break;
  819. case TLV_NODE_STATE_DEAD: return ("dead"); break;
  820. case TLV_NODE_STATE_LEAVING: return ("leaving"); break;
  821. }
  822. return ("Unhandled node state");
  823. }
  824. const char *
  825. tlv_tls_supported_to_str(enum tlv_tls_supported tls_supported)
  826. {
  827. switch (tls_supported) {
  828. case TLV_TLS_UNSUPPORTED: return ("Unsupported"); break;
  829. case TLV_TLS_SUPPORTED: return ("Supported"); break;
  830. case TLV_TLS_REQUIRED: return ("Required"); break;
  831. }
  832. return ("Unhandled tls supported state");
  833. }
  834. const char *
  835. tlv_decision_algorithm_type_to_str(enum tlv_decision_algorithm_type algorithm)
  836. {
  837. switch (algorithm) {
  838. case TLV_DECISION_ALGORITHM_TYPE_TEST: return ("Test"); break;
  839. case TLV_DECISION_ALGORITHM_TYPE_FFSPLIT: return ("Fifty-Fifty split"); break;
  840. case TLV_DECISION_ALGORITHM_TYPE_2NODELMS: return ("2 Node LMS"); break;
  841. case TLV_DECISION_ALGORITHM_TYPE_LMS: return ("LMS"); break;
  842. }
  843. return ("Unknown algorithm");
  844. }
  845. const char *
  846. tlv_heuristics_to_str(enum tlv_heuristics heuristics)
  847. {
  848. switch (heuristics) {
  849. case TLV_HEURISTICS_UNDEFINED: return ("Undefined"); break;
  850. case TLV_HEURISTICS_PASS: return ("Pass"); break;
  851. case TLV_HEURISTICS_FAIL: return ("Fail"); break;
  852. }
  853. return ("Unknown heuristics type");
  854. }
  855. int
  856. tlv_heuristics_cmp(enum tlv_heuristics h1, enum tlv_heuristics h2)
  857. {
  858. int res;
  859. res = -2;
  860. switch (h1) {
  861. case TLV_HEURISTICS_UNDEFINED:
  862. switch (h2) {
  863. case TLV_HEURISTICS_UNDEFINED: res = 0; break;
  864. case TLV_HEURISTICS_PASS: res = -1; break;
  865. case TLV_HEURISTICS_FAIL: res = 1; break;
  866. }
  867. break;
  868. case TLV_HEURISTICS_PASS:
  869. switch (h2) {
  870. case TLV_HEURISTICS_UNDEFINED: res = 1; break;
  871. case TLV_HEURISTICS_PASS: res = 0; break;
  872. case TLV_HEURISTICS_FAIL: res = 1; break;
  873. }
  874. break;
  875. case TLV_HEURISTICS_FAIL:
  876. switch (h2) {
  877. case TLV_HEURISTICS_UNDEFINED: res = -1; break;
  878. case TLV_HEURISTICS_PASS: res = -1; break;
  879. case TLV_HEURISTICS_FAIL: res = 0; break;
  880. }
  881. break;
  882. }
  883. assert(res == -1 || res == 0 || res == 1);
  884. return (res);
  885. }
  886. const char *
  887. tlv_keep_active_partition_tie_breaker_to_str(enum tlv_keep_active_partition_tie_breaker kap_tb)
  888. {
  889. switch (kap_tb) {
  890. case TLV_KEEP_ACTIVE_PARTITION_TIE_BREAKER_DISABLED: return ("Disabled"); break;
  891. case TLV_KEEP_ACTIVE_PARTITION_TIE_BREAKER_ENABLED: return ("Enabled"); break;
  892. }
  893. return ("Unknown keep active partition tie breaker type");
  894. }