netinfo.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. /* netinfo.c -- generated by Trunnel v1.5.3.
  2. * https://gitweb.torproject.org/trunnel.git
  3. * You probably shouldn't edit this file.
  4. */
  5. #include <stdlib.h>
  6. #include "trunnel-impl.h"
  7. #include "netinfo.h"
  8. #define TRUNNEL_SET_ERROR_CODE(obj) \
  9. do { \
  10. (obj)->trunnel_error_code_ = 1; \
  11. } while (0)
  12. #if defined(__COVERITY__) || defined(__clang_analyzer__)
  13. /* If we're running a static analysis tool, we don't want it to complain
  14. * that some of our remaining-bytes checks are dead-code. */
  15. int netinfo_deadcode_dummy__ = 0;
  16. #define OR_DEADCODE_DUMMY || netinfo_deadcode_dummy__
  17. #else
  18. #define OR_DEADCODE_DUMMY
  19. #endif
  20. #define CHECK_REMAINING(nbytes, label) \
  21. do { \
  22. if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
  23. goto label; \
  24. } \
  25. } while (0)
  26. netinfo_addr_t *
  27. netinfo_addr_new(void)
  28. {
  29. netinfo_addr_t *val = trunnel_calloc(1, sizeof(netinfo_addr_t));
  30. if (NULL == val)
  31. return NULL;
  32. return val;
  33. }
  34. /** Release all storage held inside 'obj', but do not free 'obj'.
  35. */
  36. static void
  37. netinfo_addr_clear(netinfo_addr_t *obj)
  38. {
  39. (void) obj;
  40. }
  41. void
  42. netinfo_addr_free(netinfo_addr_t *obj)
  43. {
  44. if (obj == NULL)
  45. return;
  46. netinfo_addr_clear(obj);
  47. trunnel_memwipe(obj, sizeof(netinfo_addr_t));
  48. trunnel_free_(obj);
  49. }
  50. uint8_t
  51. netinfo_addr_get_addr_type(const netinfo_addr_t *inp)
  52. {
  53. return inp->addr_type;
  54. }
  55. int
  56. netinfo_addr_set_addr_type(netinfo_addr_t *inp, uint8_t val)
  57. {
  58. inp->addr_type = val;
  59. return 0;
  60. }
  61. uint8_t
  62. netinfo_addr_get_len(const netinfo_addr_t *inp)
  63. {
  64. return inp->len;
  65. }
  66. int
  67. netinfo_addr_set_len(netinfo_addr_t *inp, uint8_t val)
  68. {
  69. inp->len = val;
  70. return 0;
  71. }
  72. uint32_t
  73. netinfo_addr_get_addr_ipv4(const netinfo_addr_t *inp)
  74. {
  75. return inp->addr_ipv4;
  76. }
  77. int
  78. netinfo_addr_set_addr_ipv4(netinfo_addr_t *inp, uint32_t val)
  79. {
  80. inp->addr_ipv4 = val;
  81. return 0;
  82. }
  83. size_t
  84. netinfo_addr_getlen_addr_ipv6(const netinfo_addr_t *inp)
  85. {
  86. (void)inp; return 16;
  87. }
  88. uint8_t
  89. netinfo_addr_get_addr_ipv6(netinfo_addr_t *inp, size_t idx)
  90. {
  91. trunnel_assert(idx < 16);
  92. return inp->addr_ipv6[idx];
  93. }
  94. uint8_t
  95. netinfo_addr_getconst_addr_ipv6(const netinfo_addr_t *inp, size_t idx)
  96. {
  97. return netinfo_addr_get_addr_ipv6((netinfo_addr_t*)inp, idx);
  98. }
  99. int
  100. netinfo_addr_set_addr_ipv6(netinfo_addr_t *inp, size_t idx, uint8_t elt)
  101. {
  102. trunnel_assert(idx < 16);
  103. inp->addr_ipv6[idx] = elt;
  104. return 0;
  105. }
  106. uint8_t *
  107. netinfo_addr_getarray_addr_ipv6(netinfo_addr_t *inp)
  108. {
  109. return inp->addr_ipv6;
  110. }
  111. const uint8_t *
  112. netinfo_addr_getconstarray_addr_ipv6(const netinfo_addr_t *inp)
  113. {
  114. return (const uint8_t *)netinfo_addr_getarray_addr_ipv6((netinfo_addr_t*)inp);
  115. }
  116. const char *
  117. netinfo_addr_check(const netinfo_addr_t *obj)
  118. {
  119. if (obj == NULL)
  120. return "Object was NULL";
  121. if (obj->trunnel_error_code_)
  122. return "A set function failed on this object";
  123. switch (obj->addr_type) {
  124. case NETINFO_ADDR_TYPE_IPV4:
  125. break;
  126. case NETINFO_ADDR_TYPE_IPV6:
  127. break;
  128. default:
  129. break;
  130. }
  131. return NULL;
  132. }
  133. ssize_t
  134. netinfo_addr_encoded_len(const netinfo_addr_t *obj)
  135. {
  136. ssize_t result = 0;
  137. if (NULL != netinfo_addr_check(obj))
  138. return -1;
  139. /* Length of u8 addr_type */
  140. result += 1;
  141. /* Length of u8 len */
  142. result += 1;
  143. switch (obj->addr_type) {
  144. case NETINFO_ADDR_TYPE_IPV4:
  145. /* Length of u32 addr_ipv4 */
  146. result += 4;
  147. break;
  148. case NETINFO_ADDR_TYPE_IPV6:
  149. /* Length of u8 addr_ipv6[16] */
  150. result += 16;
  151. break;
  152. default:
  153. break;
  154. }
  155. return result;
  156. }
  157. int
  158. netinfo_addr_clear_errors(netinfo_addr_t *obj)
  159. {
  160. int r = obj->trunnel_error_code_;
  161. obj->trunnel_error_code_ = 0;
  162. return r;
  163. }
  164. ssize_t
  165. netinfo_addr_encode(uint8_t *output, const size_t avail, const netinfo_addr_t *obj)
  166. {
  167. ssize_t result = 0;
  168. size_t written = 0;
  169. uint8_t *ptr = output;
  170. const char *msg;
  171. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  172. const ssize_t encoded_len = netinfo_addr_encoded_len(obj);
  173. #endif
  174. uint8_t *backptr_len = NULL;
  175. if (NULL != (msg = netinfo_addr_check(obj)))
  176. goto check_failed;
  177. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  178. trunnel_assert(encoded_len >= 0);
  179. #endif
  180. /* Encode u8 addr_type */
  181. trunnel_assert(written <= avail);
  182. if (avail - written < 1)
  183. goto truncated;
  184. trunnel_set_uint8(ptr, (obj->addr_type));
  185. written += 1; ptr += 1;
  186. /* Encode u8 len */
  187. backptr_len = ptr;
  188. trunnel_assert(written <= avail);
  189. if (avail - written < 1)
  190. goto truncated;
  191. trunnel_set_uint8(ptr, (obj->len));
  192. written += 1; ptr += 1;
  193. {
  194. size_t written_before_union = written;
  195. /* Encode union addr[addr_type] */
  196. trunnel_assert(written <= avail);
  197. switch (obj->addr_type) {
  198. case NETINFO_ADDR_TYPE_IPV4:
  199. /* Encode u32 addr_ipv4 */
  200. trunnel_assert(written <= avail);
  201. if (avail - written < 4)
  202. goto truncated;
  203. trunnel_set_uint32(ptr, trunnel_htonl(obj->addr_ipv4));
  204. written += 4; ptr += 4;
  205. break;
  206. case NETINFO_ADDR_TYPE_IPV6:
  207. /* Encode u8 addr_ipv6[16] */
  208. trunnel_assert(written <= avail);
  209. if (avail - written < 16)
  210. goto truncated;
  211. memcpy(ptr, obj->addr_ipv6, 16);
  212. written += 16; ptr += 16;
  213. break;
  214. default:
  215. break;
  216. }
  217. /* Write the length field back to len */
  218. trunnel_assert(written >= written_before_union);
  219. #if UINT8_MAX < SIZE_MAX
  220. if (written - written_before_union > UINT8_MAX)
  221. goto check_failed;
  222. #endif
  223. trunnel_set_uint8(backptr_len, (written - written_before_union));
  224. }
  225. trunnel_assert(ptr == output + written);
  226. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  227. {
  228. trunnel_assert(encoded_len >= 0);
  229. trunnel_assert((size_t)encoded_len == written);
  230. }
  231. #endif
  232. return written;
  233. truncated:
  234. result = -2;
  235. goto fail;
  236. check_failed:
  237. (void)msg;
  238. result = -1;
  239. goto fail;
  240. fail:
  241. trunnel_assert(result < 0);
  242. return result;
  243. }
  244. /** As netinfo_addr_parse(), but do not allocate the output object.
  245. */
  246. static ssize_t
  247. netinfo_addr_parse_into(netinfo_addr_t *obj, const uint8_t *input, const size_t len_in)
  248. {
  249. const uint8_t *ptr = input;
  250. size_t remaining = len_in;
  251. ssize_t result = 0;
  252. (void)result;
  253. /* Parse u8 addr_type */
  254. CHECK_REMAINING(1, truncated);
  255. obj->addr_type = (trunnel_get_uint8(ptr));
  256. remaining -= 1; ptr += 1;
  257. /* Parse u8 len */
  258. CHECK_REMAINING(1, truncated);
  259. obj->len = (trunnel_get_uint8(ptr));
  260. remaining -= 1; ptr += 1;
  261. {
  262. size_t remaining_after;
  263. CHECK_REMAINING(obj->len, truncated);
  264. remaining_after = remaining - obj->len;
  265. remaining = obj->len;
  266. /* Parse union addr[addr_type] */
  267. switch (obj->addr_type) {
  268. case NETINFO_ADDR_TYPE_IPV4:
  269. /* Parse u32 addr_ipv4 */
  270. CHECK_REMAINING(4, fail);
  271. obj->addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
  272. remaining -= 4; ptr += 4;
  273. break;
  274. case NETINFO_ADDR_TYPE_IPV6:
  275. /* Parse u8 addr_ipv6[16] */
  276. CHECK_REMAINING(16, fail);
  277. memcpy(obj->addr_ipv6, ptr, 16);
  278. remaining -= 16; ptr += 16;
  279. break;
  280. default:
  281. /* Skip to end of union */
  282. ptr += remaining; remaining = 0;
  283. break;
  284. }
  285. if (remaining != 0)
  286. goto fail;
  287. remaining = remaining_after;
  288. }
  289. trunnel_assert(ptr + remaining == input + len_in);
  290. return len_in - remaining;
  291. truncated:
  292. return -2;
  293. fail:
  294. result = -1;
  295. return result;
  296. }
  297. ssize_t
  298. netinfo_addr_parse(netinfo_addr_t **output, const uint8_t *input, const size_t len_in)
  299. {
  300. ssize_t result;
  301. *output = netinfo_addr_new();
  302. if (NULL == *output)
  303. return -1;
  304. result = netinfo_addr_parse_into(*output, input, len_in);
  305. if (result < 0) {
  306. netinfo_addr_free(*output);
  307. *output = NULL;
  308. }
  309. return result;
  310. }
  311. netinfo_cell_t *
  312. netinfo_cell_new(void)
  313. {
  314. netinfo_cell_t *val = trunnel_calloc(1, sizeof(netinfo_cell_t));
  315. if (NULL == val)
  316. return NULL;
  317. return val;
  318. }
  319. /** Release all storage held inside 'obj', but do not free 'obj'.
  320. */
  321. static void
  322. netinfo_cell_clear(netinfo_cell_t *obj)
  323. {
  324. (void) obj;
  325. netinfo_addr_free(obj->other_addr);
  326. obj->other_addr = NULL;
  327. {
  328. unsigned idx;
  329. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
  330. netinfo_addr_free(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx));
  331. }
  332. }
  333. TRUNNEL_DYNARRAY_WIPE(&obj->my_addrs);
  334. TRUNNEL_DYNARRAY_CLEAR(&obj->my_addrs);
  335. }
  336. void
  337. netinfo_cell_free(netinfo_cell_t *obj)
  338. {
  339. if (obj == NULL)
  340. return;
  341. netinfo_cell_clear(obj);
  342. trunnel_memwipe(obj, sizeof(netinfo_cell_t));
  343. trunnel_free_(obj);
  344. }
  345. uint32_t
  346. netinfo_cell_get_timestamp(const netinfo_cell_t *inp)
  347. {
  348. return inp->timestamp;
  349. }
  350. int
  351. netinfo_cell_set_timestamp(netinfo_cell_t *inp, uint32_t val)
  352. {
  353. inp->timestamp = val;
  354. return 0;
  355. }
  356. struct netinfo_addr_st *
  357. netinfo_cell_get_other_addr(netinfo_cell_t *inp)
  358. {
  359. return inp->other_addr;
  360. }
  361. const struct netinfo_addr_st *
  362. netinfo_cell_getconst_other_addr(const netinfo_cell_t *inp)
  363. {
  364. return netinfo_cell_get_other_addr((netinfo_cell_t*) inp);
  365. }
  366. int
  367. netinfo_cell_set_other_addr(netinfo_cell_t *inp, struct netinfo_addr_st *val)
  368. {
  369. if (inp->other_addr && inp->other_addr != val)
  370. netinfo_addr_free(inp->other_addr);
  371. return netinfo_cell_set0_other_addr(inp, val);
  372. }
  373. int
  374. netinfo_cell_set0_other_addr(netinfo_cell_t *inp, struct netinfo_addr_st *val)
  375. {
  376. inp->other_addr = val;
  377. return 0;
  378. }
  379. uint8_t
  380. netinfo_cell_get_n_my_addrs(const netinfo_cell_t *inp)
  381. {
  382. return inp->n_my_addrs;
  383. }
  384. int
  385. netinfo_cell_set_n_my_addrs(netinfo_cell_t *inp, uint8_t val)
  386. {
  387. inp->n_my_addrs = val;
  388. return 0;
  389. }
  390. size_t
  391. netinfo_cell_getlen_my_addrs(const netinfo_cell_t *inp)
  392. {
  393. return TRUNNEL_DYNARRAY_LEN(&inp->my_addrs);
  394. }
  395. struct netinfo_addr_st *
  396. netinfo_cell_get_my_addrs(netinfo_cell_t *inp, size_t idx)
  397. {
  398. return TRUNNEL_DYNARRAY_GET(&inp->my_addrs, idx);
  399. }
  400. const struct netinfo_addr_st *
  401. netinfo_cell_getconst_my_addrs(const netinfo_cell_t *inp, size_t idx)
  402. {
  403. return netinfo_cell_get_my_addrs((netinfo_cell_t*)inp, idx);
  404. }
  405. int
  406. netinfo_cell_set_my_addrs(netinfo_cell_t *inp, size_t idx, struct netinfo_addr_st * elt)
  407. {
  408. netinfo_addr_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->my_addrs, idx);
  409. if (oldval && oldval != elt)
  410. netinfo_addr_free(oldval);
  411. return netinfo_cell_set0_my_addrs(inp, idx, elt);
  412. }
  413. int
  414. netinfo_cell_set0_my_addrs(netinfo_cell_t *inp, size_t idx, struct netinfo_addr_st * elt)
  415. {
  416. TRUNNEL_DYNARRAY_SET(&inp->my_addrs, idx, elt);
  417. return 0;
  418. }
  419. int
  420. netinfo_cell_add_my_addrs(netinfo_cell_t *inp, struct netinfo_addr_st * elt)
  421. {
  422. #if SIZE_MAX >= UINT8_MAX
  423. if (inp->my_addrs.n_ == UINT8_MAX)
  424. goto trunnel_alloc_failed;
  425. #endif
  426. TRUNNEL_DYNARRAY_ADD(struct netinfo_addr_st *, &inp->my_addrs, elt, {});
  427. return 0;
  428. trunnel_alloc_failed:
  429. TRUNNEL_SET_ERROR_CODE(inp);
  430. return -1;
  431. }
  432. struct netinfo_addr_st * *
  433. netinfo_cell_getarray_my_addrs(netinfo_cell_t *inp)
  434. {
  435. return inp->my_addrs.elts_;
  436. }
  437. const struct netinfo_addr_st * const *
  438. netinfo_cell_getconstarray_my_addrs(const netinfo_cell_t *inp)
  439. {
  440. return (const struct netinfo_addr_st * const *)netinfo_cell_getarray_my_addrs((netinfo_cell_t*)inp);
  441. }
  442. int
  443. netinfo_cell_setlen_my_addrs(netinfo_cell_t *inp, size_t newlen)
  444. {
  445. struct netinfo_addr_st * *newptr;
  446. #if UINT8_MAX < SIZE_MAX
  447. if (newlen > UINT8_MAX)
  448. goto trunnel_alloc_failed;
  449. #endif
  450. newptr = trunnel_dynarray_setlen(&inp->my_addrs.allocated_,
  451. &inp->my_addrs.n_, inp->my_addrs.elts_, newlen,
  452. sizeof(inp->my_addrs.elts_[0]), (trunnel_free_fn_t) netinfo_addr_free,
  453. &inp->trunnel_error_code_);
  454. if (newlen != 0 && newptr == NULL)
  455. goto trunnel_alloc_failed;
  456. inp->my_addrs.elts_ = newptr;
  457. return 0;
  458. trunnel_alloc_failed:
  459. TRUNNEL_SET_ERROR_CODE(inp);
  460. return -1;
  461. }
  462. const char *
  463. netinfo_cell_check(const netinfo_cell_t *obj)
  464. {
  465. if (obj == NULL)
  466. return "Object was NULL";
  467. if (obj->trunnel_error_code_)
  468. return "A set function failed on this object";
  469. {
  470. const char *msg;
  471. if (NULL != (msg = netinfo_addr_check(obj->other_addr)))
  472. return msg;
  473. }
  474. {
  475. const char *msg;
  476. unsigned idx;
  477. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
  478. if (NULL != (msg = netinfo_addr_check(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx))))
  479. return msg;
  480. }
  481. }
  482. if (TRUNNEL_DYNARRAY_LEN(&obj->my_addrs) != obj->n_my_addrs)
  483. return "Length mismatch for my_addrs";
  484. return NULL;
  485. }
  486. ssize_t
  487. netinfo_cell_encoded_len(const netinfo_cell_t *obj)
  488. {
  489. ssize_t result = 0;
  490. if (NULL != netinfo_cell_check(obj))
  491. return -1;
  492. /* Length of u32 timestamp */
  493. result += 4;
  494. /* Length of struct netinfo_addr other_addr */
  495. result += netinfo_addr_encoded_len(obj->other_addr);
  496. /* Length of u8 n_my_addrs */
  497. result += 1;
  498. /* Length of struct netinfo_addr my_addrs[n_my_addrs] */
  499. {
  500. unsigned idx;
  501. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
  502. result += netinfo_addr_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx));
  503. }
  504. }
  505. return result;
  506. }
  507. int
  508. netinfo_cell_clear_errors(netinfo_cell_t *obj)
  509. {
  510. int r = obj->trunnel_error_code_;
  511. obj->trunnel_error_code_ = 0;
  512. return r;
  513. }
  514. ssize_t
  515. netinfo_cell_encode(uint8_t *output, const size_t avail, const netinfo_cell_t *obj)
  516. {
  517. ssize_t result = 0;
  518. size_t written = 0;
  519. uint8_t *ptr = output;
  520. const char *msg;
  521. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  522. const ssize_t encoded_len = netinfo_cell_encoded_len(obj);
  523. #endif
  524. if (NULL != (msg = netinfo_cell_check(obj)))
  525. goto check_failed;
  526. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  527. trunnel_assert(encoded_len >= 0);
  528. #endif
  529. /* Encode u32 timestamp */
  530. trunnel_assert(written <= avail);
  531. if (avail - written < 4)
  532. goto truncated;
  533. trunnel_set_uint32(ptr, trunnel_htonl(obj->timestamp));
  534. written += 4; ptr += 4;
  535. /* Encode struct netinfo_addr other_addr */
  536. trunnel_assert(written <= avail);
  537. result = netinfo_addr_encode(ptr, avail - written, obj->other_addr);
  538. if (result < 0)
  539. goto fail; /* XXXXXXX !*/
  540. written += result; ptr += result;
  541. /* Encode u8 n_my_addrs */
  542. trunnel_assert(written <= avail);
  543. if (avail - written < 1)
  544. goto truncated;
  545. trunnel_set_uint8(ptr, (obj->n_my_addrs));
  546. written += 1; ptr += 1;
  547. /* Encode struct netinfo_addr my_addrs[n_my_addrs] */
  548. {
  549. unsigned idx;
  550. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
  551. trunnel_assert(written <= avail);
  552. result = netinfo_addr_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx));
  553. if (result < 0)
  554. goto fail; /* XXXXXXX !*/
  555. written += result; ptr += result;
  556. }
  557. }
  558. trunnel_assert(ptr == output + written);
  559. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  560. {
  561. trunnel_assert(encoded_len >= 0);
  562. trunnel_assert((size_t)encoded_len == written);
  563. }
  564. #endif
  565. return written;
  566. truncated:
  567. result = -2;
  568. goto fail;
  569. check_failed:
  570. (void)msg;
  571. result = -1;
  572. goto fail;
  573. fail:
  574. trunnel_assert(result < 0);
  575. return result;
  576. }
  577. /** As netinfo_cell_parse(), but do not allocate the output object.
  578. */
  579. static ssize_t
  580. netinfo_cell_parse_into(netinfo_cell_t *obj, const uint8_t *input, const size_t len_in)
  581. {
  582. const uint8_t *ptr = input;
  583. size_t remaining = len_in;
  584. ssize_t result = 0;
  585. (void)result;
  586. /* Parse u32 timestamp */
  587. CHECK_REMAINING(4, truncated);
  588. obj->timestamp = trunnel_ntohl(trunnel_get_uint32(ptr));
  589. remaining -= 4; ptr += 4;
  590. /* Parse struct netinfo_addr other_addr */
  591. result = netinfo_addr_parse(&obj->other_addr, ptr, remaining);
  592. if (result < 0)
  593. goto relay_fail;
  594. trunnel_assert((size_t)result <= remaining);
  595. remaining -= result; ptr += result;
  596. /* Parse u8 n_my_addrs */
  597. CHECK_REMAINING(1, truncated);
  598. obj->n_my_addrs = (trunnel_get_uint8(ptr));
  599. remaining -= 1; ptr += 1;
  600. /* Parse struct netinfo_addr my_addrs[n_my_addrs] */
  601. TRUNNEL_DYNARRAY_EXPAND(netinfo_addr_t *, &obj->my_addrs, obj->n_my_addrs, {});
  602. {
  603. netinfo_addr_t * elt;
  604. unsigned idx;
  605. for (idx = 0; idx < obj->n_my_addrs; ++idx) {
  606. result = netinfo_addr_parse(&elt, ptr, remaining);
  607. if (result < 0)
  608. goto relay_fail;
  609. trunnel_assert((size_t)result <= remaining);
  610. remaining -= result; ptr += result;
  611. TRUNNEL_DYNARRAY_ADD(netinfo_addr_t *, &obj->my_addrs, elt, {netinfo_addr_free(elt);});
  612. }
  613. }
  614. trunnel_assert(ptr + remaining == input + len_in);
  615. return len_in - remaining;
  616. truncated:
  617. return -2;
  618. relay_fail:
  619. trunnel_assert(result < 0);
  620. return result;
  621. trunnel_alloc_failed:
  622. return -1;
  623. }
  624. ssize_t
  625. netinfo_cell_parse(netinfo_cell_t **output, const uint8_t *input, const size_t len_in)
  626. {
  627. ssize_t result;
  628. *output = netinfo_cell_new();
  629. if (NULL == *output)
  630. return -1;
  631. result = netinfo_cell_parse_into(*output, input, len_in);
  632. if (result < 0) {
  633. netinfo_cell_free(*output);
  634. *output = NULL;
  635. }
  636. return result;
  637. }