1 /* Copyright (c) 2023, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 * \brief XXX: Write a brief introduction to this module.
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"
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
;
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();
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
);
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
);
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
);
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
);
82 build_linked_ack_cell(uint8_t *cell_out
)
84 ssize_t cell_len
= -1;
85 trn_cell_conflux_linked_ack_t
*cell
= NULL
;
89 cell
= trn_cell_conflux_linked_ack_new();
90 cell_len
= trn_cell_conflux_linked_ack_encode(cell_out
, RELAY_PAYLOAD_SIZE
,
93 trn_cell_conflux_linked_ack_free(cell
);
98 conflux_cell_send_link(const conflux_cell_link_t
*link
, origin_circuit_t
*circ
)
100 uint8_t payload
[RELAY_PAYLOAD_SIZE
] = {0};
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
);
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.");
132 conflux_cell_send_linked(const conflux_cell_link_t
*link
, or_circuit_t
*circ
)
134 uint8_t payload
[RELAY_PAYLOAD_SIZE
] = {0};
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
);
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.");
165 conflux_cell_send_linked_ack(origin_circuit_t
*circ
)
167 uint8_t payload
[RELAY_PAYLOAD_SIZE
] = {0};
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
);
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.");
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.");
211 link
= tor_malloc_zero(sizeof(*link
));
212 link
->version
= trn_cell_conflux_link_get_version(trn_link
);
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
);
220 trn_cell_conflux_link_payload_v1_getconstarray_nonce(payload
),
221 trn_cell_conflux_link_payload_v1_getlen_nonce(payload
));
224 trn_cell_conflux_link_payload_v1_free(payload
);
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
;
236 if (trn_cell_conflux_link_parse(&trn_cell
,
237 cell
->payload
+ RELAY_HEADER_SIZE
,
239 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
240 "Unable to parse CONFLUX_LINK cell.");
244 uint8_t version
= trn_cell_conflux_link_get_version(trn_cell
);
247 link
= conflux_cell_parse_link_v1(trn_cell
);
250 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
251 "Unsupported version %d in CONFLUX_LINK cell", version
);
256 trn_cell_conflux_link_free(trn_cell
);
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
));
284 * Extracts the sequence number from a switch cell.
287 conflux_cell_parse_switch(const cell_t
*cell
, uint16_t rh_len
)
290 trn_cell_conflux_switch_t
*switch_cell
= NULL
;
293 if (trn_cell_conflux_switch_parse(&switch_cell
,
294 cell
->payload
+ RELAY_HEADER_SIZE
,
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.
302 seq
= trn_cell_conflux_switch_get_seqnum(switch_cell
);
304 trn_cell_conflux_switch_free(switch_cell
);
309 /** Send a RELAY_COMMAND_CONFLUX_SWITCH cell on the circuit. */
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();
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
,
326 log_warn(LD_BUG
, "Failed to encode conflux switch cell");
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
,
337 TO_ORIGIN_CIRCUIT(send_circ
)->cpath
->prev
);
339 relay_send_command_from_edge(0, send_circ
,
340 RELAY_COMMAND_CONFLUX_SWITCH
,
341 (const char*)cell
.payload
,
342 RELAY_PAYLOAD_SIZE
, NULL
);
346 trn_cell_conflux_switch_free(switch_cell
);