1 /* netinfo.c -- generated by Trunnel v1.5.3.
2 * https://gitweb.torproject.org/trunnel.git
3 * You probably shouldn't edit this file.
6 #include "trunnel-impl.h"
10 #define TRUNNEL_SET_ERROR_CODE(obj) \
12 (obj)->trunnel_error_code_ = 1; \
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__
21 #define OR_DEADCODE_DUMMY
24 #define CHECK_REMAINING(nbytes, label) \
26 if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
32 netinfo_addr_new(void)
34 netinfo_addr_t
*val
= trunnel_calloc(1, sizeof(netinfo_addr_t
));
40 /** Release all storage held inside 'obj', but do not free 'obj'.
43 netinfo_addr_clear(netinfo_addr_t
*obj
)
49 netinfo_addr_free(netinfo_addr_t
*obj
)
53 netinfo_addr_clear(obj
);
54 trunnel_memwipe(obj
, sizeof(netinfo_addr_t
));
59 netinfo_addr_get_addr_type(const netinfo_addr_t
*inp
)
61 return inp
->addr_type
;
64 netinfo_addr_set_addr_type(netinfo_addr_t
*inp
, uint8_t val
)
70 netinfo_addr_get_len(const netinfo_addr_t
*inp
)
75 netinfo_addr_set_len(netinfo_addr_t
*inp
, uint8_t val
)
81 netinfo_addr_get_addr_ipv4(const netinfo_addr_t
*inp
)
83 return inp
->addr_ipv4
;
86 netinfo_addr_set_addr_ipv4(netinfo_addr_t
*inp
, uint32_t val
)
92 netinfo_addr_getlen_addr_ipv6(const netinfo_addr_t
*inp
)
98 netinfo_addr_get_addr_ipv6(netinfo_addr_t
*inp
, size_t idx
)
100 trunnel_assert(idx
< 16);
101 return inp
->addr_ipv6
[idx
];
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
;
118 netinfo_addr_getarray_addr_ipv6(netinfo_addr_t
*inp
)
120 return inp
->addr_ipv6
;
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
);
128 netinfo_addr_check(const netinfo_addr_t
*obj
)
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
:
139 case NETINFO_ADDR_TYPE_IPV6
:
149 netinfo_addr_encoded_len(const netinfo_addr_t
*obj
)
153 if (NULL
!= netinfo_addr_check(obj
))
157 /* Length of u8 addr_type */
160 /* Length of u8 len */
162 switch (obj
->addr_type
) {
164 case NETINFO_ADDR_TYPE_IPV4
:
166 /* Length of u32 addr_ipv4 */
170 case NETINFO_ADDR_TYPE_IPV6
:
172 /* Length of u8 addr_ipv6[16] */
182 netinfo_addr_clear_errors(netinfo_addr_t
*obj
)
184 int r
= obj
->trunnel_error_code_
;
185 obj
->trunnel_error_code_
= 0;
189 netinfo_addr_encode(uint8_t *output
, const size_t avail
, const netinfo_addr_t
*obj
)
193 uint8_t *ptr
= output
;
195 #ifdef TRUNNEL_CHECK_ENCODED_LEN
196 const ssize_t encoded_len
= netinfo_addr_encoded_len(obj
);
199 uint8_t *backptr_len
= NULL
;
201 if (NULL
!= (msg
= netinfo_addr_check(obj
)))
204 #ifdef TRUNNEL_CHECK_ENCODED_LEN
205 trunnel_assert(encoded_len
>= 0);
208 /* Encode u8 addr_type */
209 trunnel_assert(written
<= avail
);
210 if (avail
- written
< 1)
212 trunnel_set_uint8(ptr
, (obj
->addr_type
));
213 written
+= 1; ptr
+= 1;
217 trunnel_assert(written
<= avail
);
218 if (avail
- written
< 1)
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)
235 trunnel_set_uint32(ptr
, trunnel_htonl(obj
->addr_ipv4
));
236 written
+= 4; ptr
+= 4;
239 case NETINFO_ADDR_TYPE_IPV6
:
241 /* Encode u8 addr_ipv6[16] */
242 trunnel_assert(written
<= avail
);
243 if (avail
- written
< 16)
245 memcpy(ptr
, obj
->addr_ipv6
, 16);
246 written
+= 16; ptr
+= 16;
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
)
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
);
281 trunnel_assert(result
< 0);
285 /** As netinfo_addr_parse(), but do not allocate the output object.
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
;
295 /* Parse u8 addr_type */
296 CHECK_REMAINING(1, truncated
);
297 obj
->addr_type
= (trunnel_get_uint8(ptr
));
298 remaining
-= 1; ptr
+= 1;
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;
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;
330 /* Skip to end of union */
331 ptr
+= remaining
; remaining
= 0;
336 remaining
= remaining_after
;
338 trunnel_assert(ptr
+ remaining
== input
+ len_in
);
339 return len_in
- remaining
;
349 netinfo_addr_parse(netinfo_addr_t
**output
, const uint8_t *input
, const size_t len_in
)
352 *output
= netinfo_addr_new();
355 result
= netinfo_addr_parse_into(*output
, input
, len_in
);
357 netinfo_addr_free(*output
);
363 netinfo_cell_new(void)
365 netinfo_cell_t
*val
= trunnel_calloc(1, sizeof(netinfo_cell_t
));
371 /** Release all storage held inside 'obj', but do not free 'obj'.
374 netinfo_cell_clear(netinfo_cell_t
*obj
)
377 netinfo_addr_free(obj
->other_addr
);
378 obj
->other_addr
= NULL
;
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
);
391 netinfo_cell_free(netinfo_cell_t
*obj
)
395 netinfo_cell_clear(obj
);
396 trunnel_memwipe(obj
, sizeof(netinfo_cell_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
;
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
;
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
;
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
);
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
;
483 TRUNNEL_DYNARRAY_ADD(struct netinfo_addr_st
*, &inp
->my_addrs
, elt
, {});
485 trunnel_alloc_failed
:
486 TRUNNEL_SET_ERROR_CODE(inp
);
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
;
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
;
516 trunnel_alloc_failed
:
517 TRUNNEL_SET_ERROR_CODE(inp
);
521 netinfo_cell_check(const netinfo_cell_t
*obj
)
524 return "Object was NULL";
525 if (obj
->trunnel_error_code_
)
526 return "A set function failed on this object";
529 if (NULL
!= (msg
= netinfo_addr_check(obj
->other_addr
)))
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
))))
541 if (TRUNNEL_DYNARRAY_LEN(&obj
->my_addrs
) != obj
->n_my_addrs
)
542 return "Length mismatch for my_addrs";
547 netinfo_cell_encoded_len(const netinfo_cell_t
*obj
)
551 if (NULL
!= netinfo_cell_check(obj
))
555 /* Length of u32 timestamp */
558 /* Length of struct netinfo_addr other_addr */
559 result
+= netinfo_addr_encoded_len(obj
->other_addr
);
561 /* Length of u8 n_my_addrs */
564 /* Length of struct netinfo_addr my_addrs[n_my_addrs] */
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
));
575 netinfo_cell_clear_errors(netinfo_cell_t
*obj
)
577 int r
= obj
->trunnel_error_code_
;
578 obj
->trunnel_error_code_
= 0;
582 netinfo_cell_encode(uint8_t *output
, const size_t avail
, const netinfo_cell_t
*obj
)
586 uint8_t *ptr
= output
;
588 #ifdef TRUNNEL_CHECK_ENCODED_LEN
589 const ssize_t encoded_len
= netinfo_cell_encoded_len(obj
);
592 if (NULL
!= (msg
= netinfo_cell_check(obj
)))
595 #ifdef TRUNNEL_CHECK_ENCODED_LEN
596 trunnel_assert(encoded_len
>= 0);
599 /* Encode u32 timestamp */
600 trunnel_assert(written
<= avail
);
601 if (avail
- written
< 4)
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
);
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)
617 trunnel_set_uint8(ptr
, (obj
->n_my_addrs
));
618 written
+= 1; ptr
+= 1;
620 /* Encode struct netinfo_addr my_addrs[n_my_addrs] */
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
));
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
);
653 trunnel_assert(result
< 0);
657 /** As netinfo_cell_parse(), but do not allocate the output object.
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
;
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
);
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
;
689 for (idx
= 0; idx
< obj
->n_my_addrs
; ++idx
) {
690 result
= netinfo_addr_parse(&elt
, ptr
, remaining
);
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
;
704 trunnel_assert(result
< 0);
706 trunnel_alloc_failed
:
711 netinfo_cell_parse(netinfo_cell_t
**output
, const uint8_t *input
, const size_t len_in
)
714 *output
= netinfo_cell_new();
717 result
= netinfo_cell_parse_into(*output
, input
, len_in
);
719 netinfo_cell_free(*output
);