fallbackdir: Update list generated on August 30, 2023
[tor.git] / src / core / or / conflux_cell.c
bloba59fa735f139c0c85ef49ca6dbfbda97e35e625a
1 /* Copyright (c) 2023, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file conflux_cell.c
6 * \brief XXX: Write a brief introduction to this module.
7 **/
9 #define CONFLUX_CELL_PRIVATE
11 #include "app/config/config.h"
13 #include "core/or/conflux.h"
14 #include "core/or/conflux_cell.h"
15 #include "core/or/relay.h"
16 #include "core/or/circuitlist.h"
18 #include "lib/crypt_ops/crypto_rand.h"
20 #include "trunnel/conflux.h"
22 #include "core/or/crypt_path_st.h"
23 #include "core/or/or_circuit_st.h"
24 #include "core/or/origin_circuit_st.h"
26 STATIC ssize_t
27 build_link_cell(const conflux_cell_link_t *link, uint8_t *cell_out)
29 ssize_t cell_len = -1;
30 trn_cell_conflux_link_t *cell = NULL;
31 trn_cell_conflux_link_payload_v1_t *payload = NULL;
33 tor_assert(cell_out);
35 cell = trn_cell_conflux_link_new();
36 trn_cell_conflux_link_set_version(cell, 0x01);
38 payload = trn_cell_conflux_link_payload_v1_new();
40 /* Set the nonce. */
41 size_t nonce_len = trn_cell_conflux_link_payload_v1_getlen_nonce(payload);
42 tor_assert(nonce_len == sizeof(link->nonce));
43 memcpy(trn_cell_conflux_link_payload_v1_getarray_nonce(payload),
44 link->nonce, nonce_len);
46 /* Set the sequence number. */
47 trn_cell_conflux_link_payload_v1_set_last_seqno_recv(payload,
48 link->last_seqno_recv);
49 trn_cell_conflux_link_payload_v1_set_last_seqno_sent(payload,
50 link->last_seqno_sent);
52 /* Set the algorithm */
53 trn_cell_conflux_link_payload_v1_set_desired_ux(payload, link->desired_ux);
55 /* Encode payload. */
56 ssize_t pay_len = trn_cell_conflux_link_payload_v1_encoded_len(payload);
57 tor_assert(pay_len >= 0);
59 trn_cell_conflux_link_setlen_payload(cell, pay_len);
61 trn_cell_conflux_link_payload_v1_encode(
62 trn_cell_conflux_link_getarray_payload(cell),
63 trn_cell_conflux_link_getlen_payload(cell), payload);
65 /* Encode cell. */
66 cell_len = trn_cell_conflux_link_encode(cell_out, RELAY_PAYLOAD_SIZE, cell);
68 trn_cell_conflux_link_payload_v1_free(payload);
69 trn_cell_conflux_link_free(cell);
70 return cell_len;
73 static ssize_t
74 build_linked_cell(const conflux_cell_link_t *link, uint8_t *cell_out)
76 /* Same payload. This might not be true in the future but for now, we don't
77 * need to duplicate the code as it is really the same. */
78 return build_link_cell(link, cell_out);
81 static ssize_t
82 build_linked_ack_cell(uint8_t *cell_out)
84 ssize_t cell_len = -1;
85 trn_cell_conflux_linked_ack_t *cell = NULL;
87 tor_assert(cell_out);
89 cell = trn_cell_conflux_linked_ack_new();
90 cell_len = trn_cell_conflux_linked_ack_encode(cell_out, RELAY_PAYLOAD_SIZE,
91 cell);
93 trn_cell_conflux_linked_ack_free(cell);
94 return cell_len;
97 bool
98 conflux_cell_send_link(const conflux_cell_link_t *link, origin_circuit_t *circ)
100 uint8_t payload[RELAY_PAYLOAD_SIZE] = {0};
101 ssize_t cell_len;
103 tor_assert(link);
104 tor_assert(circ);
106 log_info(LD_CIRC, "Sending CONFLUX_LINK cell onto origin circuit");
108 /* Build the CONFLUX_LINK cell. */
109 cell_len = build_link_cell(link, payload);
110 if (BUG(cell_len < 0)) {
111 log_info(LD_CIRC, "Unable to build CONFLUX_LINK cell.");
112 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
113 goto err;
116 /* Send the cell to the endpoint of the circuit. */
117 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
118 RELAY_COMMAND_CONFLUX_LINK,
119 (char *) payload, cell_len,
120 circ->cpath->prev) < 0) {
121 log_info(LD_CIRC, "Unable to send CONFLUX_LINK cell.");
122 goto err;
125 return true;
127 err:
128 return false;
131 bool
132 conflux_cell_send_linked(const conflux_cell_link_t *link, or_circuit_t *circ)
134 uint8_t payload[RELAY_PAYLOAD_SIZE] = {0};
135 ssize_t cell_len;
137 tor_assert(link);
138 tor_assert(circ);
140 log_info(LD_CIRC, "Sending CONFLUX_LINKED cell onto OR circuit");
142 /* Build the CONFLUX_LINK cell. */
143 cell_len = build_linked_cell(link, payload);
144 if (BUG(cell_len < 0)) {
145 log_info(LD_CIRC, "Unable to build CONFLUX_LINKED cell.");
146 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
147 goto err;
150 /* Send back the LINKED cell. */
151 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
152 RELAY_COMMAND_CONFLUX_LINKED,
153 (char *) payload, cell_len, NULL) < 0) {
154 log_info(LD_CIRC, "Unable to send CONFLUX_LINKED cell.");
155 goto err;
158 return true;
160 err:
161 return false;
164 bool
165 conflux_cell_send_linked_ack(origin_circuit_t *circ)
167 uint8_t payload[RELAY_PAYLOAD_SIZE] = {0};
168 ssize_t cell_len;
170 tor_assert(circ);
172 log_info(LD_CIRC, "Sending CONFLUX_LINKED_ACK cell onto origin circuit");
174 /* Build the CONFLUX_LINKED_ACK cell. */
175 cell_len = build_linked_ack_cell(payload);
176 if (BUG(cell_len < 0)) {
177 log_info(LD_CIRC, "Unable to build CONFLUX_LINKED_ACK cell.");
178 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
179 goto err;
182 /* Send the cell to the endpoint of the circuit. */
183 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
184 RELAY_COMMAND_CONFLUX_LINKED_ACK,
185 (char *) payload, cell_len,
186 circ->cpath->prev) < 0) {
187 log_info(LD_CIRC, "Unable to send CONFLUX_LINKED_ACK cell.");
188 goto err;
191 return true;
193 err:
194 return false;
197 static conflux_cell_link_t *
198 conflux_cell_parse_link_v1(const trn_cell_conflux_link_t *trn_link)
200 conflux_cell_link_t *link = NULL;
201 trn_cell_conflux_link_payload_v1_t *payload = NULL;
203 if (trn_cell_conflux_link_payload_v1_parse(&payload,
204 trn_cell_conflux_link_getconstarray_payload(trn_link),
205 trn_cell_conflux_link_getlen_payload(trn_link)) < 0) {
206 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
207 "Unable to parse CONFLUX_LINK v1 payload.");
208 goto end;
211 link = tor_malloc_zero(sizeof(*link));
212 link->version = trn_cell_conflux_link_get_version(trn_link);
213 link->desired_ux =
214 trn_cell_conflux_link_payload_v1_get_desired_ux(payload);
215 link->last_seqno_recv =
216 trn_cell_conflux_link_payload_v1_get_last_seqno_recv(payload);
217 link->last_seqno_sent =
218 trn_cell_conflux_link_payload_v1_get_last_seqno_sent(payload);
219 memcpy(link->nonce,
220 trn_cell_conflux_link_payload_v1_getconstarray_nonce(payload),
221 trn_cell_conflux_link_payload_v1_getlen_nonce(payload));
223 end:
224 trn_cell_conflux_link_payload_v1_free(payload);
225 return link;
228 conflux_cell_link_t *
229 conflux_cell_parse_link(const cell_t *cell, const uint16_t cell_len)
231 conflux_cell_link_t *link = NULL;
232 trn_cell_conflux_link_t *trn_cell = NULL;
234 tor_assert(cell);
236 if (trn_cell_conflux_link_parse(&trn_cell,
237 cell->payload + RELAY_HEADER_SIZE,
238 cell_len) < 0) {
239 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
240 "Unable to parse CONFLUX_LINK cell.");
241 goto end;
244 uint8_t version = trn_cell_conflux_link_get_version(trn_cell);
245 switch (version) {
246 case 0x01:
247 link = conflux_cell_parse_link_v1(trn_cell);
248 break;
249 default:
250 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
251 "Unsupported version %d in CONFLUX_LINK cell", version);
252 goto end;
255 end:
256 trn_cell_conflux_link_free(trn_cell);
257 return link;
260 conflux_cell_link_t *
261 conflux_cell_parse_linked(const cell_t *cell, const uint16_t cell_len)
263 /* At the moment, same exact payload so avoid code duplication. */
264 return conflux_cell_parse_link(cell, cell_len);
267 conflux_cell_link_t *
268 conflux_cell_new_link(const uint8_t *nonce, uint64_t last_seqno_sent,
269 uint64_t last_seqno_recv, uint8_t ux)
271 conflux_cell_link_t *link = tor_malloc_zero(sizeof(*link));
273 link->version = 0x01;
274 link->desired_ux = ux;
276 link->last_seqno_sent = last_seqno_sent;
277 link->last_seqno_recv = last_seqno_recv;
278 memcpy(link->nonce, nonce, sizeof(link->nonce));
280 return link;
284 * Extracts the sequence number from a switch cell.
286 uint32_t
287 conflux_cell_parse_switch(const cell_t *cell, uint16_t rh_len)
289 uint32_t seq = 0;
290 trn_cell_conflux_switch_t *switch_cell = NULL;
291 tor_assert(cell);
293 if (trn_cell_conflux_switch_parse(&switch_cell,
294 cell->payload + RELAY_HEADER_SIZE,
295 rh_len) < 0) {
296 log_warn(LD_BUG, "Failed to parse switch cell");
297 // Zero counts as a failure to the validation, since legs should
298 // not switch after 0 cells.
299 return 0;
302 seq = trn_cell_conflux_switch_get_seqnum(switch_cell);
304 trn_cell_conflux_switch_free(switch_cell);
306 return seq;
309 /** Send a RELAY_COMMAND_CONFLUX_SWITCH cell on the circuit. */
310 bool
311 conflux_send_switch_command(circuit_t *send_circ, uint64_t relative_seq)
313 trn_cell_conflux_switch_t *switch_cell = trn_cell_conflux_switch_new();
314 cell_t cell;
315 bool ret = true;
317 tor_assert(send_circ);
318 tor_assert(relative_seq < UINT32_MAX);
320 memset(&cell, 0, sizeof(cell));
322 trn_cell_conflux_switch_set_seqnum(switch_cell, (uint32_t)relative_seq);
324 if (trn_cell_conflux_switch_encode(cell.payload, RELAY_PAYLOAD_SIZE,
325 switch_cell) < 0) {
326 log_warn(LD_BUG, "Failed to encode conflux switch cell");
327 ret = false;
328 goto end;
331 /* Send the switch command to the new hop */
332 if (CIRCUIT_IS_ORIGIN(send_circ)) {
333 relay_send_command_from_edge(0, send_circ,
334 RELAY_COMMAND_CONFLUX_SWITCH,
335 (const char*)cell.payload,
336 RELAY_PAYLOAD_SIZE,
337 TO_ORIGIN_CIRCUIT(send_circ)->cpath->prev);
338 } else {
339 relay_send_command_from_edge(0, send_circ,
340 RELAY_COMMAND_CONFLUX_SWITCH,
341 (const char*)cell.payload,
342 RELAY_PAYLOAD_SIZE, NULL);
345 end:
346 trn_cell_conflux_switch_free(switch_cell);
347 return ret;