Tor 0.4.9.2-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
conflux_cell.c
Go to the documentation of this file.
1/* Copyright (c) 2023, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file conflux_cell.c
6 * \brief XXX: Write a brief introduction to this module.
7 **/
8
9#define CONFLUX_CELL_PRIVATE
10
11#include "app/config/config.h"
12
13#include "core/or/conflux.h"
15#include "core/or/relay.h"
16#include "core/or/circuitlist.h"
17
19
20#include "trunnel/conflux.h"
21
23#include "core/or/or_circuit_st.h"
25
26STATIC ssize_t
27build_link_cell(const conflux_cell_link_t *link, uint8_t *cell_out)
28{
29 ssize_t cell_len = -1;
30 trn_cell_conflux_link_t *cell = NULL;
31 trn_cell_conflux_link_payload_v1_t *payload = NULL;
32
33 tor_assert(cell_out);
34
35 cell = trn_cell_conflux_link_new();
36 trn_cell_conflux_link_set_version(cell, 0x01);
37
38 payload = trn_cell_conflux_link_payload_v1_new();
39
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);
45
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);
51
52 /* Set the algorithm */
53 trn_cell_conflux_link_payload_v1_set_desired_ux(payload, link->desired_ux);
54
55 /* Encode payload. */
56 ssize_t pay_len = trn_cell_conflux_link_payload_v1_encoded_len(payload);
57 tor_assert(pay_len >= 0);
58
59 trn_cell_conflux_link_setlen_payload(cell, pay_len);
60
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);
64
65 /* Encode cell. */
66 cell_len = trn_cell_conflux_link_encode(cell_out,
68
69 trn_cell_conflux_link_payload_v1_free(payload);
70 trn_cell_conflux_link_free(cell);
71 return cell_len;
72}
73
74static ssize_t
75build_linked_cell(const conflux_cell_link_t *link, uint8_t *cell_out)
76{
77 /* Same payload. This might not be true in the future but for now, we don't
78 * need to duplicate the code as it is really the same. */
79 return build_link_cell(link, cell_out);
80}
81
82static ssize_t
83build_linked_ack_cell(uint8_t *cell_out)
84{
85 ssize_t cell_len = -1;
86 trn_cell_conflux_linked_ack_t *cell = NULL;
87
88 tor_assert(cell_out);
89
90 cell = trn_cell_conflux_linked_ack_new();
91 cell_len = trn_cell_conflux_linked_ack_encode(cell_out,
93 cell);
94
95 trn_cell_conflux_linked_ack_free(cell);
96 return cell_len;
97}
98
99bool
100conflux_cell_send_link(const conflux_cell_link_t *link, origin_circuit_t *circ)
101{
102 uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
103 ssize_t cell_len;
104
105 tor_assert(link);
106 tor_assert(circ);
107
108 log_info(LD_CIRC, "Sending CONFLUX_LINK cell onto origin circuit");
109
110 /* Build the CONFLUX_LINK cell. */
111 cell_len = build_link_cell(link, payload);
112 if (BUG(cell_len < 0)) {
113 log_info(LD_CIRC, "Unable to build CONFLUX_LINK cell.");
114 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
115 goto err;
116 }
117
118 /* Send the cell to the endpoint of the circuit. */
119 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
120 RELAY_COMMAND_CONFLUX_LINK,
121 (char *) payload, cell_len,
122 circ->cpath->prev) < 0) {
123 log_info(LD_CIRC, "Unable to send CONFLUX_LINK cell.");
124 goto err;
125 }
126
127 return true;
128
129 err:
130 return false;
131}
132
133bool
134conflux_cell_send_linked(const conflux_cell_link_t *link, or_circuit_t *circ)
135{
136 uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
137 ssize_t cell_len;
138
139 tor_assert(link);
140 tor_assert(circ);
141
142 log_info(LD_CIRC, "Sending CONFLUX_LINKED cell onto OR circuit");
143
144 /* Build the CONFLUX_LINK cell. */
145 cell_len = build_linked_cell(link, payload);
146 if (BUG(cell_len < 0)) {
147 log_info(LD_CIRC, "Unable to build CONFLUX_LINKED cell.");
148 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
149 goto err;
150 }
151
152 /* Send back the LINKED cell. */
153 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
154 RELAY_COMMAND_CONFLUX_LINKED,
155 (char *) payload, cell_len, NULL) < 0) {
156 log_info(LD_CIRC, "Unable to send CONFLUX_LINKED cell.");
157 goto err;
158 }
159
160 return true;
161
162 err:
163 return false;
164}
165
166bool
167conflux_cell_send_linked_ack(origin_circuit_t *circ)
168{
169 uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
170 ssize_t cell_len;
171
172 tor_assert(circ);
173
174 log_info(LD_CIRC, "Sending CONFLUX_LINKED_ACK cell onto origin circuit");
175
176 /* Build the CONFLUX_LINKED_ACK cell. */
177 cell_len = build_linked_ack_cell(payload);
178 if (BUG(cell_len < 0)) {
179 log_info(LD_CIRC, "Unable to build CONFLUX_LINKED_ACK cell.");
180 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
181 goto err;
182 }
183
184 /* Send the cell to the endpoint of the circuit. */
185 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
186 RELAY_COMMAND_CONFLUX_LINKED_ACK,
187 (char *) payload, cell_len,
188 circ->cpath->prev) < 0) {
189 log_info(LD_CIRC, "Unable to send CONFLUX_LINKED_ACK cell.");
190 goto err;
191 }
192
193 return true;
194
195 err:
196 return false;
197}
198
199static conflux_cell_link_t *
200conflux_cell_parse_link_v1(const trn_cell_conflux_link_t *trn_link)
201{
202 conflux_cell_link_t *link = NULL;
203 trn_cell_conflux_link_payload_v1_t *payload = NULL;
204
205 if (trn_cell_conflux_link_payload_v1_parse(&payload,
206 trn_cell_conflux_link_getconstarray_payload(trn_link),
207 trn_cell_conflux_link_getlen_payload(trn_link)) < 0) {
208 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
209 "Unable to parse CONFLUX_LINK v1 payload.");
210 goto end;
211 }
212
213 link = tor_malloc_zero(sizeof(*link));
214 link->version = trn_cell_conflux_link_get_version(trn_link);
215 link->desired_ux =
216 trn_cell_conflux_link_payload_v1_get_desired_ux(payload);
217 link->last_seqno_recv =
218 trn_cell_conflux_link_payload_v1_get_last_seqno_recv(payload);
219 link->last_seqno_sent =
220 trn_cell_conflux_link_payload_v1_get_last_seqno_sent(payload);
221 memcpy(link->nonce,
222 trn_cell_conflux_link_payload_v1_getconstarray_nonce(payload),
223 trn_cell_conflux_link_payload_v1_getlen_nonce(payload));
224
225 end:
226 trn_cell_conflux_link_payload_v1_free(payload);
227 return link;
228}
229
231conflux_cell_parse_link(const relay_msg_t *msg)
232{
233 conflux_cell_link_t *link = NULL;
234 trn_cell_conflux_link_t *trn_cell = NULL;
235
236 tor_assert(msg);
237
238 if (trn_cell_conflux_link_parse(&trn_cell, msg->body, msg->length) < 0) {
239 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
240 "Unable to parse CONFLUX_LINK cell.");
241 goto end;
242 }
243
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;
253 }
254
255 end:
256 trn_cell_conflux_link_free(trn_cell);
257 return link;
258}
259
261conflux_cell_parse_linked(const relay_msg_t *msg)
262{
263 /* At the moment, same exact payload so avoid code duplication. */
264 return conflux_cell_parse_link(msg);
265}
266
268conflux_cell_new_link(const uint8_t *nonce, uint64_t last_seqno_sent,
269 uint64_t last_seqno_recv, uint8_t ux)
270{
271 conflux_cell_link_t *link = tor_malloc_zero(sizeof(*link));
272
273 link->version = 0x01;
274 link->desired_ux = ux;
275
276 link->last_seqno_sent = last_seqno_sent;
277 link->last_seqno_recv = last_seqno_recv;
278 memcpy(link->nonce, nonce, sizeof(link->nonce));
279
280 return link;
281}
282
283/**
284 * Extracts the sequence number from a switch cell.
285 */
286uint32_t
288{
289 uint32_t seq = 0;
290 trn_cell_conflux_switch_t *switch_cell = NULL;
291
292 tor_assert(msg);
293
294 if (trn_cell_conflux_switch_parse(&switch_cell,
295 msg->body, msg->length) < 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;
300 }
301
302 seq = trn_cell_conflux_switch_get_seqnum(switch_cell);
303
304 trn_cell_conflux_switch_free(switch_cell);
305
306 return seq;
307}
308
309/** Send a RELAY_COMMAND_CONFLUX_SWITCH cell on the circuit. */
310bool
311conflux_send_switch_command(circuit_t *send_circ, uint64_t relative_seq)
312{
313 trn_cell_conflux_switch_t *switch_cell = trn_cell_conflux_switch_new();
314 uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
315 bool ret = true;
316
317 tor_assert(send_circ);
318 tor_assert(relative_seq < UINT32_MAX);
319
320 trn_cell_conflux_switch_set_seqnum(switch_cell, (uint32_t)relative_seq);
321
322 ssize_t len = trn_cell_conflux_switch_encode(
323 payload, RELAY_PAYLOAD_SIZE_MAX,
324 switch_cell);
325 if (len < 0) {
326 log_warn(LD_BUG, "Failed to encode conflux switch cell");
327 ret = false;
328 goto end;
329 }
330
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*)payload, len,
336 TO_ORIGIN_CIRCUIT(send_circ)->cpath->prev);
337 } else {
338 relay_send_command_from_edge(0, send_circ,
339 RELAY_COMMAND_CONFLUX_SWITCH,
340 (const char*)payload, len,
341 NULL);
342 }
343
344end:
345 trn_cell_conflux_switch_free(switch_cell);
346 return ret;
347}
origin_circuit_t * TO_ORIGIN_CIRCUIT(circuit_t *x)
Definition: circuitlist.c:185
Header file for circuitlist.c.
#define CIRCUIT_IS_ORIGIN(c)
Definition: circuitlist.h:154
Header file for config.c.
Public APIs for conflux multipath support.
uint32_t conflux_cell_parse_switch(const relay_msg_t *msg)
Definition: conflux_cell.c:287
bool conflux_send_switch_command(circuit_t *send_circ, uint64_t relative_seq)
Definition: conflux_cell.c:311
Header file for conflux_cell.c.
Path structures for origin circuits.
Common functions for using (pseudo-)random number generators.
#define log_fn(severity, domain, args,...)
Definition: log.h:283
#define LD_BUG
Definition: log.h:86
#define LD_CIRC
Definition: log.h:82
#define TO_CIRCUIT(x)
Definition: or.h:936
#define RELAY_PAYLOAD_SIZE_MAX
Definition: or.h:567
Origin circuit structure.
Header file for relay.c.
struct crypt_path_t * prev
Definition: crypt_path_st.h:79
crypt_path_t * cpath
#define STATIC
Definition: testsupport.h:32
#define tor_assert(expr)
Definition: util_bug.h:103