1 /* sendme_cell.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"
8 #include "sendme_cell.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 sendmecell_deadcode_dummy__
= 0;
19 #define OR_DEADCODE_DUMMY || sendmecell_deadcode_dummy__
21 #define OR_DEADCODE_DUMMY
24 #define CHECK_REMAINING(nbytes, label) \
26 if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
34 sendme_cell_t
*val
= trunnel_calloc(1, sizeof(sendme_cell_t
));
40 /** Release all storage held inside 'obj', but do not free 'obj'.
43 sendme_cell_clear(sendme_cell_t
*obj
)
49 sendme_cell_free(sendme_cell_t
*obj
)
53 sendme_cell_clear(obj
);
54 trunnel_memwipe(obj
, sizeof(sendme_cell_t
));
59 sendme_cell_get_version(const sendme_cell_t
*inp
)
64 sendme_cell_set_version(sendme_cell_t
*inp
, uint8_t val
)
66 if (! ((val
== 0 || val
== 1))) {
67 TRUNNEL_SET_ERROR_CODE(inp
);
74 sendme_cell_get_data_len(const sendme_cell_t
*inp
)
79 sendme_cell_set_data_len(sendme_cell_t
*inp
, uint16_t val
)
85 sendme_cell_getlen_data_v1_digest(const sendme_cell_t
*inp
)
87 (void)inp
; return TRUNNEL_SENDME_V1_DIGEST_LEN
;
91 sendme_cell_get_data_v1_digest(sendme_cell_t
*inp
, size_t idx
)
93 trunnel_assert(idx
< TRUNNEL_SENDME_V1_DIGEST_LEN
);
94 return inp
->data_v1_digest
[idx
];
98 sendme_cell_getconst_data_v1_digest(const sendme_cell_t
*inp
, size_t idx
)
100 return sendme_cell_get_data_v1_digest((sendme_cell_t
*)inp
, idx
);
103 sendme_cell_set_data_v1_digest(sendme_cell_t
*inp
, size_t idx
, uint8_t elt
)
105 trunnel_assert(idx
< TRUNNEL_SENDME_V1_DIGEST_LEN
);
106 inp
->data_v1_digest
[idx
] = elt
;
111 sendme_cell_getarray_data_v1_digest(sendme_cell_t
*inp
)
113 return inp
->data_v1_digest
;
116 sendme_cell_getconstarray_data_v1_digest(const sendme_cell_t
*inp
)
118 return (const uint8_t *)sendme_cell_getarray_data_v1_digest((sendme_cell_t
*)inp
);
121 sendme_cell_check(const sendme_cell_t
*obj
)
124 return "Object was NULL";
125 if (obj
->trunnel_error_code_
)
126 return "A set function failed on this object";
127 if (! (obj
->version
== 0 || obj
->version
== 1))
128 return "Integer out of bounds";
129 switch (obj
->version
) {
138 return "Bad tag for union";
145 sendme_cell_encoded_len(const sendme_cell_t
*obj
)
149 if (NULL
!= sendme_cell_check(obj
))
153 /* Length of u8 version IN [0, 1] */
156 /* Length of u16 data_len */
158 switch (obj
->version
) {
165 /* Length of u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */
166 result
+= TRUNNEL_SENDME_V1_DIGEST_LEN
;
176 sendme_cell_clear_errors(sendme_cell_t
*obj
)
178 int r
= obj
->trunnel_error_code_
;
179 obj
->trunnel_error_code_
= 0;
183 sendme_cell_encode(uint8_t *output
, const size_t avail
, const sendme_cell_t
*obj
)
187 uint8_t *ptr
= output
;
189 #ifdef TRUNNEL_CHECK_ENCODED_LEN
190 const ssize_t encoded_len
= sendme_cell_encoded_len(obj
);
193 uint8_t *backptr_data_len
= NULL
;
195 if (NULL
!= (msg
= sendme_cell_check(obj
)))
198 #ifdef TRUNNEL_CHECK_ENCODED_LEN
199 trunnel_assert(encoded_len
>= 0);
202 /* Encode u8 version IN [0, 1] */
203 trunnel_assert(written
<= avail
);
204 if (avail
- written
< 1)
206 trunnel_set_uint8(ptr
, (obj
->version
));
207 written
+= 1; ptr
+= 1;
209 /* Encode u16 data_len */
210 backptr_data_len
= ptr
;
211 trunnel_assert(written
<= avail
);
212 if (avail
- written
< 2)
214 trunnel_set_uint16(ptr
, trunnel_htons(obj
->data_len
));
215 written
+= 2; ptr
+= 2;
217 size_t written_before_union
= written
;
219 /* Encode union data[version] */
220 trunnel_assert(written
<= avail
);
221 switch (obj
->version
) {
228 /* Encode u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */
229 trunnel_assert(written
<= avail
);
230 if (avail
- written
< TRUNNEL_SENDME_V1_DIGEST_LEN
)
232 memcpy(ptr
, obj
->data_v1_digest
, TRUNNEL_SENDME_V1_DIGEST_LEN
);
233 written
+= TRUNNEL_SENDME_V1_DIGEST_LEN
; ptr
+= TRUNNEL_SENDME_V1_DIGEST_LEN
;
240 /* Write the length field back to data_len */
241 trunnel_assert(written
>= written_before_union
);
242 #if UINT16_MAX < SIZE_MAX
243 if (written
- written_before_union
> UINT16_MAX
)
246 trunnel_set_uint16(backptr_data_len
, trunnel_htons(written
- written_before_union
));
250 trunnel_assert(ptr
== output
+ written
);
251 #ifdef TRUNNEL_CHECK_ENCODED_LEN
253 trunnel_assert(encoded_len
>= 0);
254 trunnel_assert((size_t)encoded_len
== written
);
269 trunnel_assert(result
< 0);
273 /** As sendme_cell_parse(), but do not allocate the output object.
276 sendme_cell_parse_into(sendme_cell_t
*obj
, const uint8_t *input
, const size_t len_in
)
278 const uint8_t *ptr
= input
;
279 size_t remaining
= len_in
;
283 /* Parse u8 version IN [0, 1] */
284 CHECK_REMAINING(1, truncated
);
285 obj
->version
= (trunnel_get_uint8(ptr
));
286 remaining
-= 1; ptr
+= 1;
287 if (! (obj
->version
== 0 || obj
->version
== 1))
290 /* Parse u16 data_len */
291 CHECK_REMAINING(2, truncated
);
292 obj
->data_len
= trunnel_ntohs(trunnel_get_uint16(ptr
));
293 remaining
-= 2; ptr
+= 2;
295 size_t remaining_after
;
296 CHECK_REMAINING(obj
->data_len
, truncated
);
297 remaining_after
= remaining
- obj
->data_len
;
298 remaining
= obj
->data_len
;
300 /* Parse union data[version] */
301 switch (obj
->version
) {
304 /* Skip to end of union */
305 ptr
+= remaining
; remaining
= 0;
310 /* Parse u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */
311 CHECK_REMAINING(TRUNNEL_SENDME_V1_DIGEST_LEN
, fail
);
312 memcpy(obj
->data_v1_digest
, ptr
, TRUNNEL_SENDME_V1_DIGEST_LEN
);
313 remaining
-= TRUNNEL_SENDME_V1_DIGEST_LEN
; ptr
+= TRUNNEL_SENDME_V1_DIGEST_LEN
;
322 remaining
= remaining_after
;
324 trunnel_assert(ptr
+ remaining
== input
+ len_in
);
325 return len_in
- remaining
;
335 sendme_cell_parse(sendme_cell_t
**output
, const uint8_t *input
, const size_t len_in
)
338 *output
= sendme_cell_new();
341 result
= sendme_cell_parse_into(*output
, input
, len_in
);
343 sendme_cell_free(*output
);