Merge remote-tracking branch 'mbeth-private/ticket40821_mr'
[tor.git] / src / trunnel / netinfo.c
blobd7d0cddc8939be0c950b2aee731f7e3b0231f194
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"
8 #include "netinfo.h"
10 #define TRUNNEL_SET_ERROR_CODE(obj) \
11 do { \
12 (obj)->trunnel_error_code_ = 1; \
13 } while (0)
15 #if defined(__COVERITY__) || defined(__clang_analyzer__)
16 /* If we're running a static analysis tool, we don't want it to complain
17 * that some of our remaining-bytes checks are dead-code. */
18 int netinfo_deadcode_dummy__ = 0;
19 #define OR_DEADCODE_DUMMY || netinfo_deadcode_dummy__
20 #else
21 #define OR_DEADCODE_DUMMY
22 #endif
24 #define CHECK_REMAINING(nbytes, label) \
25 do { \
26 if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
27 goto label; \
28 } \
29 } while (0)
31 netinfo_addr_t *
32 netinfo_addr_new(void)
34 netinfo_addr_t *val = trunnel_calloc(1, sizeof(netinfo_addr_t));
35 if (NULL == val)
36 return NULL;
37 return val;
40 /** Release all storage held inside 'obj', but do not free 'obj'.
42 static void
43 netinfo_addr_clear(netinfo_addr_t *obj)
45 (void) obj;
48 void
49 netinfo_addr_free(netinfo_addr_t *obj)
51 if (obj == NULL)
52 return;
53 netinfo_addr_clear(obj);
54 trunnel_memwipe(obj, sizeof(netinfo_addr_t));
55 trunnel_free_(obj);
58 uint8_t
59 netinfo_addr_get_addr_type(const netinfo_addr_t *inp)
61 return inp->addr_type;
63 int
64 netinfo_addr_set_addr_type(netinfo_addr_t *inp, uint8_t val)
66 inp->addr_type = val;
67 return 0;
69 uint8_t
70 netinfo_addr_get_len(const netinfo_addr_t *inp)
72 return inp->len;
74 int
75 netinfo_addr_set_len(netinfo_addr_t *inp, uint8_t val)
77 inp->len = val;
78 return 0;
80 uint32_t
81 netinfo_addr_get_addr_ipv4(const netinfo_addr_t *inp)
83 return inp->addr_ipv4;
85 int
86 netinfo_addr_set_addr_ipv4(netinfo_addr_t *inp, uint32_t val)
88 inp->addr_ipv4 = val;
89 return 0;
91 size_t
92 netinfo_addr_getlen_addr_ipv6(const netinfo_addr_t *inp)
94 (void)inp; return 16;
97 uint8_t
98 netinfo_addr_get_addr_ipv6(netinfo_addr_t *inp, size_t idx)
100 trunnel_assert(idx < 16);
101 return inp->addr_ipv6[idx];
104 uint8_t
105 netinfo_addr_getconst_addr_ipv6(const netinfo_addr_t *inp, size_t idx)
107 return netinfo_addr_get_addr_ipv6((netinfo_addr_t*)inp, idx);
110 netinfo_addr_set_addr_ipv6(netinfo_addr_t *inp, size_t idx, uint8_t elt)
112 trunnel_assert(idx < 16);
113 inp->addr_ipv6[idx] = elt;
114 return 0;
117 uint8_t *
118 netinfo_addr_getarray_addr_ipv6(netinfo_addr_t *inp)
120 return inp->addr_ipv6;
122 const uint8_t *
123 netinfo_addr_getconstarray_addr_ipv6(const netinfo_addr_t *inp)
125 return (const uint8_t *)netinfo_addr_getarray_addr_ipv6((netinfo_addr_t*)inp);
127 const char *
128 netinfo_addr_check(const netinfo_addr_t *obj)
130 if (obj == NULL)
131 return "Object was NULL";
132 if (obj->trunnel_error_code_)
133 return "A set function failed on this object";
134 switch (obj->addr_type) {
136 case NETINFO_ADDR_TYPE_IPV4:
137 break;
139 case NETINFO_ADDR_TYPE_IPV6:
140 break;
142 default:
143 break;
145 return NULL;
148 ssize_t
149 netinfo_addr_encoded_len(const netinfo_addr_t *obj)
151 ssize_t result = 0;
153 if (NULL != netinfo_addr_check(obj))
154 return -1;
157 /* Length of u8 addr_type */
158 result += 1;
160 /* Length of u8 len */
161 result += 1;
162 switch (obj->addr_type) {
164 case NETINFO_ADDR_TYPE_IPV4:
166 /* Length of u32 addr_ipv4 */
167 result += 4;
168 break;
170 case NETINFO_ADDR_TYPE_IPV6:
172 /* Length of u8 addr_ipv6[16] */
173 result += 16;
174 break;
176 default:
177 break;
179 return result;
182 netinfo_addr_clear_errors(netinfo_addr_t *obj)
184 int r = obj->trunnel_error_code_;
185 obj->trunnel_error_code_ = 0;
186 return r;
188 ssize_t
189 netinfo_addr_encode(uint8_t *output, const size_t avail, const netinfo_addr_t *obj)
191 ssize_t result = 0;
192 size_t written = 0;
193 uint8_t *ptr = output;
194 const char *msg;
195 #ifdef TRUNNEL_CHECK_ENCODED_LEN
196 const ssize_t encoded_len = netinfo_addr_encoded_len(obj);
197 #endif
199 uint8_t *backptr_len = NULL;
201 if (NULL != (msg = netinfo_addr_check(obj)))
202 goto check_failed;
204 #ifdef TRUNNEL_CHECK_ENCODED_LEN
205 trunnel_assert(encoded_len >= 0);
206 #endif
208 /* Encode u8 addr_type */
209 trunnel_assert(written <= avail);
210 if (avail - written < 1)
211 goto truncated;
212 trunnel_set_uint8(ptr, (obj->addr_type));
213 written += 1; ptr += 1;
215 /* Encode u8 len */
216 backptr_len = ptr;
217 trunnel_assert(written <= avail);
218 if (avail - written < 1)
219 goto truncated;
220 trunnel_set_uint8(ptr, (obj->len));
221 written += 1; ptr += 1;
223 size_t written_before_union = written;
225 /* Encode union addr[addr_type] */
226 trunnel_assert(written <= avail);
227 switch (obj->addr_type) {
229 case NETINFO_ADDR_TYPE_IPV4:
231 /* Encode u32 addr_ipv4 */
232 trunnel_assert(written <= avail);
233 if (avail - written < 4)
234 goto truncated;
235 trunnel_set_uint32(ptr, trunnel_htonl(obj->addr_ipv4));
236 written += 4; ptr += 4;
237 break;
239 case NETINFO_ADDR_TYPE_IPV6:
241 /* Encode u8 addr_ipv6[16] */
242 trunnel_assert(written <= avail);
243 if (avail - written < 16)
244 goto truncated;
245 memcpy(ptr, obj->addr_ipv6, 16);
246 written += 16; ptr += 16;
247 break;
249 default:
250 break;
252 /* Write the length field back to len */
253 trunnel_assert(written >= written_before_union);
254 #if UINT8_MAX < SIZE_MAX
255 if (written - written_before_union > UINT8_MAX)
256 goto check_failed;
257 #endif
258 trunnel_set_uint8(backptr_len, (written - written_before_union));
262 trunnel_assert(ptr == output + written);
263 #ifdef TRUNNEL_CHECK_ENCODED_LEN
265 trunnel_assert(encoded_len >= 0);
266 trunnel_assert((size_t)encoded_len == written);
269 #endif
271 return written;
273 truncated:
274 result = -2;
275 goto fail;
276 check_failed:
277 (void)msg;
278 result = -1;
279 goto fail;
280 fail:
281 trunnel_assert(result < 0);
282 return result;
285 /** As netinfo_addr_parse(), but do not allocate the output object.
287 static ssize_t
288 netinfo_addr_parse_into(netinfo_addr_t *obj, const uint8_t *input, const size_t len_in)
290 const uint8_t *ptr = input;
291 size_t remaining = len_in;
292 ssize_t result = 0;
293 (void)result;
295 /* Parse u8 addr_type */
296 CHECK_REMAINING(1, truncated);
297 obj->addr_type = (trunnel_get_uint8(ptr));
298 remaining -= 1; ptr += 1;
300 /* Parse u8 len */
301 CHECK_REMAINING(1, truncated);
302 obj->len = (trunnel_get_uint8(ptr));
303 remaining -= 1; ptr += 1;
305 size_t remaining_after;
306 CHECK_REMAINING(obj->len, truncated);
307 remaining_after = remaining - obj->len;
308 remaining = obj->len;
310 /* Parse union addr[addr_type] */
311 switch (obj->addr_type) {
313 case NETINFO_ADDR_TYPE_IPV4:
315 /* Parse u32 addr_ipv4 */
316 CHECK_REMAINING(4, fail);
317 obj->addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
318 remaining -= 4; ptr += 4;
319 break;
321 case NETINFO_ADDR_TYPE_IPV6:
323 /* Parse u8 addr_ipv6[16] */
324 CHECK_REMAINING(16, fail);
325 memcpy(obj->addr_ipv6, ptr, 16);
326 remaining -= 16; ptr += 16;
327 break;
329 default:
330 /* Skip to end of union */
331 ptr += remaining; remaining = 0;
332 break;
334 if (remaining != 0)
335 goto fail;
336 remaining = remaining_after;
338 trunnel_assert(ptr + remaining == input + len_in);
339 return len_in - remaining;
341 truncated:
342 return -2;
343 fail:
344 result = -1;
345 return result;
348 ssize_t
349 netinfo_addr_parse(netinfo_addr_t **output, const uint8_t *input, const size_t len_in)
351 ssize_t result;
352 *output = netinfo_addr_new();
353 if (NULL == *output)
354 return -1;
355 result = netinfo_addr_parse_into(*output, input, len_in);
356 if (result < 0) {
357 netinfo_addr_free(*output);
358 *output = NULL;
360 return result;
362 netinfo_cell_t *
363 netinfo_cell_new(void)
365 netinfo_cell_t *val = trunnel_calloc(1, sizeof(netinfo_cell_t));
366 if (NULL == val)
367 return NULL;
368 return val;
371 /** Release all storage held inside 'obj', but do not free 'obj'.
373 static void
374 netinfo_cell_clear(netinfo_cell_t *obj)
376 (void) obj;
377 netinfo_addr_free(obj->other_addr);
378 obj->other_addr = NULL;
381 unsigned idx;
382 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
383 netinfo_addr_free(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx));
386 TRUNNEL_DYNARRAY_WIPE(&obj->my_addrs);
387 TRUNNEL_DYNARRAY_CLEAR(&obj->my_addrs);
390 void
391 netinfo_cell_free(netinfo_cell_t *obj)
393 if (obj == NULL)
394 return;
395 netinfo_cell_clear(obj);
396 trunnel_memwipe(obj, sizeof(netinfo_cell_t));
397 trunnel_free_(obj);
400 uint32_t
401 netinfo_cell_get_timestamp(const netinfo_cell_t *inp)
403 return inp->timestamp;
406 netinfo_cell_set_timestamp(netinfo_cell_t *inp, uint32_t val)
408 inp->timestamp = val;
409 return 0;
411 struct netinfo_addr_st *
412 netinfo_cell_get_other_addr(netinfo_cell_t *inp)
414 return inp->other_addr;
416 const struct netinfo_addr_st *
417 netinfo_cell_getconst_other_addr(const netinfo_cell_t *inp)
419 return netinfo_cell_get_other_addr((netinfo_cell_t*) inp);
422 netinfo_cell_set_other_addr(netinfo_cell_t *inp, struct netinfo_addr_st *val)
424 if (inp->other_addr && inp->other_addr != val)
425 netinfo_addr_free(inp->other_addr);
426 return netinfo_cell_set0_other_addr(inp, val);
429 netinfo_cell_set0_other_addr(netinfo_cell_t *inp, struct netinfo_addr_st *val)
431 inp->other_addr = val;
432 return 0;
434 uint8_t
435 netinfo_cell_get_n_my_addrs(const netinfo_cell_t *inp)
437 return inp->n_my_addrs;
440 netinfo_cell_set_n_my_addrs(netinfo_cell_t *inp, uint8_t val)
442 inp->n_my_addrs = val;
443 return 0;
445 size_t
446 netinfo_cell_getlen_my_addrs(const netinfo_cell_t *inp)
448 return TRUNNEL_DYNARRAY_LEN(&inp->my_addrs);
451 struct netinfo_addr_st *
452 netinfo_cell_get_my_addrs(netinfo_cell_t *inp, size_t idx)
454 return TRUNNEL_DYNARRAY_GET(&inp->my_addrs, idx);
457 const struct netinfo_addr_st *
458 netinfo_cell_getconst_my_addrs(const netinfo_cell_t *inp, size_t idx)
460 return netinfo_cell_get_my_addrs((netinfo_cell_t*)inp, idx);
463 netinfo_cell_set_my_addrs(netinfo_cell_t *inp, size_t idx, struct netinfo_addr_st * elt)
465 netinfo_addr_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->my_addrs, idx);
466 if (oldval && oldval != elt)
467 netinfo_addr_free(oldval);
468 return netinfo_cell_set0_my_addrs(inp, idx, elt);
471 netinfo_cell_set0_my_addrs(netinfo_cell_t *inp, size_t idx, struct netinfo_addr_st * elt)
473 TRUNNEL_DYNARRAY_SET(&inp->my_addrs, idx, elt);
474 return 0;
477 netinfo_cell_add_my_addrs(netinfo_cell_t *inp, struct netinfo_addr_st * elt)
479 #if SIZE_MAX >= UINT8_MAX
480 if (inp->my_addrs.n_ == UINT8_MAX)
481 goto trunnel_alloc_failed;
482 #endif
483 TRUNNEL_DYNARRAY_ADD(struct netinfo_addr_st *, &inp->my_addrs, elt, {});
484 return 0;
485 trunnel_alloc_failed:
486 TRUNNEL_SET_ERROR_CODE(inp);
487 return -1;
490 struct netinfo_addr_st * *
491 netinfo_cell_getarray_my_addrs(netinfo_cell_t *inp)
493 return inp->my_addrs.elts_;
495 const struct netinfo_addr_st * const *
496 netinfo_cell_getconstarray_my_addrs(const netinfo_cell_t *inp)
498 return (const struct netinfo_addr_st * const *)netinfo_cell_getarray_my_addrs((netinfo_cell_t*)inp);
501 netinfo_cell_setlen_my_addrs(netinfo_cell_t *inp, size_t newlen)
503 struct netinfo_addr_st * *newptr;
504 #if UINT8_MAX < SIZE_MAX
505 if (newlen > UINT8_MAX)
506 goto trunnel_alloc_failed;
507 #endif
508 newptr = trunnel_dynarray_setlen(&inp->my_addrs.allocated_,
509 &inp->my_addrs.n_, inp->my_addrs.elts_, newlen,
510 sizeof(inp->my_addrs.elts_[0]), (trunnel_free_fn_t) netinfo_addr_free,
511 &inp->trunnel_error_code_);
512 if (newlen != 0 && newptr == NULL)
513 goto trunnel_alloc_failed;
514 inp->my_addrs.elts_ = newptr;
515 return 0;
516 trunnel_alloc_failed:
517 TRUNNEL_SET_ERROR_CODE(inp);
518 return -1;
520 const char *
521 netinfo_cell_check(const netinfo_cell_t *obj)
523 if (obj == NULL)
524 return "Object was NULL";
525 if (obj->trunnel_error_code_)
526 return "A set function failed on this object";
528 const char *msg;
529 if (NULL != (msg = netinfo_addr_check(obj->other_addr)))
530 return msg;
533 const char *msg;
535 unsigned idx;
536 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
537 if (NULL != (msg = netinfo_addr_check(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx))))
538 return msg;
541 if (TRUNNEL_DYNARRAY_LEN(&obj->my_addrs) != obj->n_my_addrs)
542 return "Length mismatch for my_addrs";
543 return NULL;
546 ssize_t
547 netinfo_cell_encoded_len(const netinfo_cell_t *obj)
549 ssize_t result = 0;
551 if (NULL != netinfo_cell_check(obj))
552 return -1;
555 /* Length of u32 timestamp */
556 result += 4;
558 /* Length of struct netinfo_addr other_addr */
559 result += netinfo_addr_encoded_len(obj->other_addr);
561 /* Length of u8 n_my_addrs */
562 result += 1;
564 /* Length of struct netinfo_addr my_addrs[n_my_addrs] */
567 unsigned idx;
568 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
569 result += netinfo_addr_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx));
572 return result;
575 netinfo_cell_clear_errors(netinfo_cell_t *obj)
577 int r = obj->trunnel_error_code_;
578 obj->trunnel_error_code_ = 0;
579 return r;
581 ssize_t
582 netinfo_cell_encode(uint8_t *output, const size_t avail, const netinfo_cell_t *obj)
584 ssize_t result = 0;
585 size_t written = 0;
586 uint8_t *ptr = output;
587 const char *msg;
588 #ifdef TRUNNEL_CHECK_ENCODED_LEN
589 const ssize_t encoded_len = netinfo_cell_encoded_len(obj);
590 #endif
592 if (NULL != (msg = netinfo_cell_check(obj)))
593 goto check_failed;
595 #ifdef TRUNNEL_CHECK_ENCODED_LEN
596 trunnel_assert(encoded_len >= 0);
597 #endif
599 /* Encode u32 timestamp */
600 trunnel_assert(written <= avail);
601 if (avail - written < 4)
602 goto truncated;
603 trunnel_set_uint32(ptr, trunnel_htonl(obj->timestamp));
604 written += 4; ptr += 4;
606 /* Encode struct netinfo_addr other_addr */
607 trunnel_assert(written <= avail);
608 result = netinfo_addr_encode(ptr, avail - written, obj->other_addr);
609 if (result < 0)
610 goto fail; /* XXXXXXX !*/
611 written += result; ptr += result;
613 /* Encode u8 n_my_addrs */
614 trunnel_assert(written <= avail);
615 if (avail - written < 1)
616 goto truncated;
617 trunnel_set_uint8(ptr, (obj->n_my_addrs));
618 written += 1; ptr += 1;
620 /* Encode struct netinfo_addr my_addrs[n_my_addrs] */
623 unsigned idx;
624 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
625 trunnel_assert(written <= avail);
626 result = netinfo_addr_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx));
627 if (result < 0)
628 goto fail; /* XXXXXXX !*/
629 written += result; ptr += result;
634 trunnel_assert(ptr == output + written);
635 #ifdef TRUNNEL_CHECK_ENCODED_LEN
637 trunnel_assert(encoded_len >= 0);
638 trunnel_assert((size_t)encoded_len == written);
641 #endif
643 return written;
645 truncated:
646 result = -2;
647 goto fail;
648 check_failed:
649 (void)msg;
650 result = -1;
651 goto fail;
652 fail:
653 trunnel_assert(result < 0);
654 return result;
657 /** As netinfo_cell_parse(), but do not allocate the output object.
659 static ssize_t
660 netinfo_cell_parse_into(netinfo_cell_t *obj, const uint8_t *input, const size_t len_in)
662 const uint8_t *ptr = input;
663 size_t remaining = len_in;
664 ssize_t result = 0;
665 (void)result;
667 /* Parse u32 timestamp */
668 CHECK_REMAINING(4, truncated);
669 obj->timestamp = trunnel_ntohl(trunnel_get_uint32(ptr));
670 remaining -= 4; ptr += 4;
672 /* Parse struct netinfo_addr other_addr */
673 result = netinfo_addr_parse(&obj->other_addr, ptr, remaining);
674 if (result < 0)
675 goto relay_fail;
676 trunnel_assert((size_t)result <= remaining);
677 remaining -= result; ptr += result;
679 /* Parse u8 n_my_addrs */
680 CHECK_REMAINING(1, truncated);
681 obj->n_my_addrs = (trunnel_get_uint8(ptr));
682 remaining -= 1; ptr += 1;
684 /* Parse struct netinfo_addr my_addrs[n_my_addrs] */
685 TRUNNEL_DYNARRAY_EXPAND(netinfo_addr_t *, &obj->my_addrs, obj->n_my_addrs, {});
687 netinfo_addr_t * elt;
688 unsigned idx;
689 for (idx = 0; idx < obj->n_my_addrs; ++idx) {
690 result = netinfo_addr_parse(&elt, ptr, remaining);
691 if (result < 0)
692 goto relay_fail;
693 trunnel_assert((size_t)result <= remaining);
694 remaining -= result; ptr += result;
695 TRUNNEL_DYNARRAY_ADD(netinfo_addr_t *, &obj->my_addrs, elt, {netinfo_addr_free(elt);});
698 trunnel_assert(ptr + remaining == input + len_in);
699 return len_in - remaining;
701 truncated:
702 return -2;
703 relay_fail:
704 trunnel_assert(result < 0);
705 return result;
706 trunnel_alloc_failed:
707 return -1;
710 ssize_t
711 netinfo_cell_parse(netinfo_cell_t **output, const uint8_t *input, const size_t len_in)
713 ssize_t result;
714 *output = netinfo_cell_new();
715 if (NULL == *output)
716 return -1;
717 result = netinfo_cell_parse_into(*output, input, len_in);
718 if (result < 0) {
719 netinfo_cell_free(*output);
720 *output = NULL;
722 return result;