conflux_cell.c (10582B)
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" 14 #include "core/or/conflux_cell.h" 15 #include "core/or/relay.h" 16 #include "core/or/circuitlist.h" 17 18 #include "lib/crypt_ops/crypto_rand.h" 19 20 #include "trunnel/conflux.h" 21 22 #include "core/or/crypt_path_st.h" 23 #include "core/or/or_circuit_st.h" 24 #include "core/or/origin_circuit_st.h" 25 26 STATIC ssize_t 27 build_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, 67 RELAY_PAYLOAD_SIZE_MAX, cell); 68 69 trn_cell_conflux_link_payload_v1_free(payload); 70 trn_cell_conflux_link_free(cell); 71 return cell_len; 72 } 73 74 static ssize_t 75 build_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 82 static ssize_t 83 build_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, 92 RELAY_PAYLOAD_SIZE_MAX, 93 cell); 94 95 trn_cell_conflux_linked_ack_free(cell); 96 return cell_len; 97 } 98 99 bool 100 conflux_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 133 bool 134 conflux_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 166 bool 167 conflux_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 199 static conflux_cell_link_t * 200 conflux_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 230 conflux_cell_link_t * 231 conflux_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 260 conflux_cell_link_t * 261 conflux_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 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) 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 */ 286 uint32_t 287 conflux_cell_parse_switch(const relay_msg_t *msg) 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. */ 310 bool 311 conflux_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 319 /* This is possible unfortunately because the sequence numbers are 64 bit 320 * while in the SWITCH it is 32 bit. It would require more than 2.2 TB of 321 * data to be transfered on a circuit to reach this. Worth avoiding. */ 322 if (relative_seq >= UINT32_MAX) { 323 /* Avoid spamming logs with this, every hours should be fine. */ 324 static ratelim_t rlimit = RATELIM_INIT(60 * 60); 325 log_fn_ratelim(&rlimit, LOG_WARN, LD_CIRC, 326 "Relative sequence number is too high. Closing circuit."); 327 ret = false; 328 goto end; 329 } 330 331 trn_cell_conflux_switch_set_seqnum(switch_cell, (uint32_t)relative_seq); 332 333 ssize_t len = trn_cell_conflux_switch_encode( 334 payload, RELAY_PAYLOAD_SIZE_MAX, 335 switch_cell); 336 if (len < 0) { 337 log_warn(LD_BUG, "Failed to encode conflux switch cell"); 338 ret = false; 339 goto end; 340 } 341 342 /* Send the switch command to the new hop */ 343 if (CIRCUIT_IS_ORIGIN(send_circ)) { 344 relay_send_command_from_edge(0, send_circ, 345 RELAY_COMMAND_CONFLUX_SWITCH, 346 (const char*)payload, len, 347 TO_ORIGIN_CIRCUIT(send_circ)->cpath->prev); 348 } else { 349 relay_send_command_from_edge(0, send_circ, 350 RELAY_COMMAND_CONFLUX_SWITCH, 351 (const char*)payload, len, 352 NULL); 353 } 354 355 end: 356 trn_cell_conflux_switch_free(switch_cell); 357 return ret; 358 }