From: David Goulet Date: Mon, 22 Jan 2024 19:35:21 +0000 (-0500) Subject: cc: Consolidate trunnel code with ntorv3 trunnel file X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1d2936b8163e897167b0d0ea54df904d9f3991f4;p=thirdparty%2Ftor.git cc: Consolidate trunnel code with ntorv3 trunnel file Signed-off-by: David Goulet --- diff --git a/src/core/crypto/onion_crypto.c b/src/core/crypto/onion_crypto.c index e892084115..8c785a5c1a 100644 --- a/src/core/crypto/onion_crypto.c +++ b/src/core/crypto/onion_crypto.c @@ -49,7 +49,6 @@ #include "core/or/crypt_path_st.h" #include "core/or/extend_info_st.h" -#include "trunnel/congestion_control.h" #include "trunnel/extension.h" #include "trunnel/ntorv3.h" @@ -138,7 +137,7 @@ parse_ntor3_server_ext(const uint8_t *data, size_t data_len, case TRUNNEL_NTORV3_EXT_TYPE_SUBPROTO_REQ: ret = parse_subproto_extension(field, params_out); break; - case TRUNNEL_EXT_TYPE_CC_FIELD_REQUEST: + case TRUNNEL_NTORV3_EXT_TYPE_CC_REQ: ret = congestion_control_ntor3_parse_ext_request(field, params_out); break; default: diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index 1c3c7f832d..87dd81eae4 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -84,7 +84,6 @@ #include "core/or/origin_circuit_st.h" #include "trunnel/extension.h" -#include "trunnel/congestion_control.h" static int circuit_send_first_onion_skin(origin_circuit_t *circ); static int circuit_build_no_more_hops(origin_circuit_t *circ); diff --git a/src/core/or/congestion_control_common.c b/src/core/or/congestion_control_common.c index 5a0285aaf8..83a0afed30 100644 --- a/src/core/or/congestion_control_common.c +++ b/src/core/or/congestion_control_common.c @@ -30,8 +30,8 @@ #include "feature/nodelist/networkstatus.h" #include "app/config/config.h" -#include "trunnel/congestion_control.h" #include "trunnel/extension.h" +#include "trunnel/ntorv3.h" /* Consensus parameter defaults. * @@ -1006,8 +1006,7 @@ congestion_control_build_ext_request(void) /* Build the extension field that will hold the CC field. */ field = trn_extension_field_new(); - trn_extension_field_set_field_type(field, - TRUNNEL_EXT_TYPE_CC_FIELD_REQUEST); + trn_extension_field_set_field_type(field, TRUNNEL_NTORV3_EXT_TYPE_CC_REQ); /* No payload indicating a request to use congestion control. */ trn_extension_field_set_field_len(field, 0); @@ -1029,7 +1028,7 @@ congestion_control_ntor3_parse_ext_request(const trn_extension_field_t *ext, { tor_assert(ext); tor_assert(trn_extension_field_get_field_type(ext) == - TRUNNEL_EXT_TYPE_CC_FIELD_REQUEST); + TRUNNEL_NTORV3_EXT_TYPE_CC_REQ); /* The presence of the extension is enough to indicate we want it enabled. */ params_out->cc_enabled = true; @@ -1051,21 +1050,21 @@ congestion_control_ntor3_build_ext_response(const circuit_params_t *our_params) { ssize_t ret; trn_extension_field_t *field = NULL; - trn_extension_field_cc_t *cc_field = NULL; + trn_ntorv3_ext_cc_response_t *cc_field = NULL; tor_assert(our_params); /* Build the extension field that will hold the CC field. */ field = trn_extension_field_new(); trn_extension_field_set_field_type(field, - TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE); + TRUNNEL_NTORV3_EXT_TYPE_CC_RESPONSE); /* Build the congestion control field response. */ - cc_field = trn_extension_field_cc_new(); - trn_extension_field_cc_set_sendme_inc(cc_field, - our_params->sendme_inc_cells); + cc_field = trn_ntorv3_ext_cc_response_new(); + trn_ntorv3_ext_cc_response_set_sendme_inc(cc_field, + our_params->sendme_inc_cells); - ret = trn_extension_field_cc_encoded_len(cc_field); + ret = trn_ntorv3_ext_cc_response_encoded_len(cc_field); if (BUG(ret <= 0)) { trn_extension_field_free(field); field = NULL; @@ -1076,7 +1075,7 @@ congestion_control_ntor3_build_ext_response(const circuit_params_t *our_params) trn_extension_field_setlen_field(field, field_len); uint8_t *field_array = trn_extension_field_getarray_field(field); - ret = trn_extension_field_cc_encode(field_array, + ret = trn_ntorv3_ext_cc_response_encode(field_array, trn_extension_field_getlen_field(field), cc_field); if (BUG(ret <= 0)) { trn_extension_field_free(field); @@ -1085,7 +1084,7 @@ congestion_control_ntor3_build_ext_response(const circuit_params_t *our_params) } err: - trn_extension_field_cc_free(cc_field); + trn_ntorv3_ext_cc_response_free(cc_field); return field; } @@ -1110,78 +1109,6 @@ congestion_control_validate_sendme_increment(uint8_t sendme_inc) return true; } -/** Return 1 if CC is enabled which also will set the SENDME increment into our - * params_out. Return 0 if CC is disabled. Else, return -1 on error. */ -int -congestion_control_parse_ext_response(const uint8_t *msg, - const size_t msg_len, - circuit_params_t *params_out) -{ - ssize_t ret = 0; - size_t num_fields = 0; - trn_extension_t *ext = NULL; - trn_extension_field_cc_t *cc_field = NULL; - - /* We will only accept this response (and this circuit) if sendme_inc - * is within a factor of 2 of our consensus value. We should not need - * to change cc_sendme_inc much, and if we do, we can spread out those - * changes over smaller increments once every 4 hours. Exits that - * violate this range should just not be used. */ -#define MAX_SENDME_INC_NEGOTIATE_FACTOR 2 - - /* Parse extension from payload. */ - ret = trn_extension_parse(&ext, msg, msg_len); - if (ret < 0) { - goto end; - } - - if ((num_fields = trn_extension_get_num(ext)) == 0) { - ret = 0; - goto end; - } - - /* Go over all fields. If any field is TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE, - * then congestion control is enabled. Ignore unknown fields. */ - for (size_t f = 0; f < num_fields; f++) { - const trn_extension_field_t *field = trn_extension_get_fields(ext, f); - if (field == NULL) { - ret = -1; - goto end; - } - - /* Only examine TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE; ignore other fields */ - if (trn_extension_field_get_field_type(field) == - TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE) { - - /* Parse the field into the congestion control field. */ - ret = trn_extension_field_cc_parse(&cc_field, - trn_extension_field_getconstarray_field(field), - trn_extension_field_getlen_field(field)); - if (ret < 0) { - goto end; - } - - uint8_t sendme_inc_cells = - trn_extension_field_cc_get_sendme_inc(cc_field); - if (!congestion_control_validate_sendme_increment(sendme_inc_cells)) { - ret = -1; - goto end; - } - - /* All good. Get value and break */ - params_out->sendme_inc_cells = sendme_inc_cells; - ret = 1; - break; - } - } - - end: - trn_extension_free(ext); - trn_extension_field_cc_free(cc_field); - - return (int)ret; -} - /** * Returns a formatted string of fields containing congestion * control information, for the CIRC_BW control port event. diff --git a/src/feature/hs/hs_cell.c b/src/feature/hs/hs_cell.c index 0039825f3c..a0a32d819b 100644 --- a/src/feature/hs/hs_cell.c +++ b/src/feature/hs/hs_cell.c @@ -19,9 +19,9 @@ #include "core/or/origin_circuit_st.h" /* Trunnel. */ -#include "trunnel/congestion_control.h" #include "trunnel/ed25519_cert.h" #include "trunnel/extension.h" +#include "trunnel/ntorv3.h" #include "trunnel/hs/cell_establish_intro.h" #include "trunnel/hs/cell_introduce1.h" #include "trunnel/hs/cell_rendezvous.h" @@ -937,7 +937,6 @@ parse_introduce_cell_extension(const hs_service_t *service, const trn_extension_field_t *field) { int ret = 0; - trn_extension_field_cc_t *cc_field = NULL; tor_assert(data); tor_assert(field); @@ -961,7 +960,6 @@ parse_introduce_cell_extension(const hs_service_t *service, break; } - trn_extension_field_cc_free(cc_field); return ret; } diff --git a/src/trunnel/congestion_control.c b/src/trunnel/congestion_control.c deleted file mode 100644 index 371612bfe0..0000000000 --- a/src/trunnel/congestion_control.c +++ /dev/null @@ -1,183 +0,0 @@ -/* congestion_control.c -- generated by Trunnel v1.5.3. - * https://gitweb.torproject.org/trunnel.git - * You probably shouldn't edit this file. - */ -#include -#include "trunnel-impl.h" - -#include "congestion_control.h" - -#define TRUNNEL_SET_ERROR_CODE(obj) \ - do { \ - (obj)->trunnel_error_code_ = 1; \ - } while (0) - -#if defined(__COVERITY__) || defined(__clang_analyzer__) -/* If we're running a static analysis tool, we don't want it to complain - * that some of our remaining-bytes checks are dead-code. */ -int congestioncontrol_deadcode_dummy__ = 0; -#define OR_DEADCODE_DUMMY || congestioncontrol_deadcode_dummy__ -#else -#define OR_DEADCODE_DUMMY -#endif - -#define CHECK_REMAINING(nbytes, label) \ - do { \ - if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \ - goto label; \ - } \ - } while (0) - -trn_extension_field_cc_t * -trn_extension_field_cc_new(void) -{ - trn_extension_field_cc_t *val = trunnel_calloc(1, sizeof(trn_extension_field_cc_t)); - if (NULL == val) - return NULL; - return val; -} - -/** Release all storage held inside 'obj', but do not free 'obj'. - */ -static void -trn_extension_field_cc_clear(trn_extension_field_cc_t *obj) -{ - (void) obj; -} - -void -trn_extension_field_cc_free(trn_extension_field_cc_t *obj) -{ - if (obj == NULL) - return; - trn_extension_field_cc_clear(obj); - trunnel_memwipe(obj, sizeof(trn_extension_field_cc_t)); - trunnel_free_(obj); -} - -uint8_t -trn_extension_field_cc_get_sendme_inc(const trn_extension_field_cc_t *inp) -{ - return inp->sendme_inc; -} -int -trn_extension_field_cc_set_sendme_inc(trn_extension_field_cc_t *inp, uint8_t val) -{ - inp->sendme_inc = val; - return 0; -} -const char * -trn_extension_field_cc_check(const trn_extension_field_cc_t *obj) -{ - if (obj == NULL) - return "Object was NULL"; - if (obj->trunnel_error_code_) - return "A set function failed on this object"; - return NULL; -} - -ssize_t -trn_extension_field_cc_encoded_len(const trn_extension_field_cc_t *obj) -{ - ssize_t result = 0; - - if (NULL != trn_extension_field_cc_check(obj)) - return -1; - - - /* Length of u8 sendme_inc */ - result += 1; - return result; -} -int -trn_extension_field_cc_clear_errors(trn_extension_field_cc_t *obj) -{ - int r = obj->trunnel_error_code_; - obj->trunnel_error_code_ = 0; - return r; -} -ssize_t -trn_extension_field_cc_encode(uint8_t *output, const size_t avail, const trn_extension_field_cc_t *obj) -{ - ssize_t result = 0; - size_t written = 0; - uint8_t *ptr = output; - const char *msg; -#ifdef TRUNNEL_CHECK_ENCODED_LEN - const ssize_t encoded_len = trn_extension_field_cc_encoded_len(obj); -#endif - - if (NULL != (msg = trn_extension_field_cc_check(obj))) - goto check_failed; - -#ifdef TRUNNEL_CHECK_ENCODED_LEN - trunnel_assert(encoded_len >= 0); -#endif - - /* Encode u8 sendme_inc */ - trunnel_assert(written <= avail); - if (avail - written < 1) - goto truncated; - trunnel_set_uint8(ptr, (obj->sendme_inc)); - written += 1; ptr += 1; - - - trunnel_assert(ptr == output + written); -#ifdef TRUNNEL_CHECK_ENCODED_LEN - { - trunnel_assert(encoded_len >= 0); - trunnel_assert((size_t)encoded_len == written); - } - -#endif - - return written; - - truncated: - result = -2; - goto fail; - check_failed: - (void)msg; - result = -1; - goto fail; - fail: - trunnel_assert(result < 0); - return result; -} - -/** As trn_extension_field_cc_parse(), but do not allocate the output - * object. - */ -static ssize_t -trn_extension_field_cc_parse_into(trn_extension_field_cc_t *obj, const uint8_t *input, const size_t len_in) -{ - const uint8_t *ptr = input; - size_t remaining = len_in; - ssize_t result = 0; - (void)result; - - /* Parse u8 sendme_inc */ - CHECK_REMAINING(1, truncated); - obj->sendme_inc = (trunnel_get_uint8(ptr)); - remaining -= 1; ptr += 1; - trunnel_assert(ptr + remaining == input + len_in); - return len_in - remaining; - - truncated: - return -2; -} - -ssize_t -trn_extension_field_cc_parse(trn_extension_field_cc_t **output, const uint8_t *input, const size_t len_in) -{ - ssize_t result; - *output = trn_extension_field_cc_new(); - if (NULL == *output) - return -1; - result = trn_extension_field_cc_parse_into(*output, input, len_in); - if (result < 0) { - trn_extension_field_cc_free(*output); - *output = NULL; - } - return result; -} diff --git a/src/trunnel/congestion_control.h b/src/trunnel/congestion_control.h deleted file mode 100644 index 0cc21a1db5..0000000000 --- a/src/trunnel/congestion_control.h +++ /dev/null @@ -1,67 +0,0 @@ -/* congestion_control.h -- generated by Trunnel v1.5.3. - * https://gitweb.torproject.org/trunnel.git - * You probably shouldn't edit this file. - */ -#ifndef TRUNNEL_CONGESTION_CONTROL_H -#define TRUNNEL_CONGESTION_CONTROL_H - -#include -#include "trunnel.h" - -#define TRUNNEL_EXT_TYPE_CC_FIELD_REQUEST 1 -#define TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE 2 -#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_TRN_EXTENSION_FIELD_CC) -struct trn_extension_field_cc_st { - uint8_t sendme_inc; - uint8_t trunnel_error_code_; -}; -#endif -typedef struct trn_extension_field_cc_st trn_extension_field_cc_t; -/** Return a newly allocated trn_extension_field_cc with all elements - * set to zero. - */ -trn_extension_field_cc_t *trn_extension_field_cc_new(void); -/** Release all storage held by the trn_extension_field_cc in - * 'victim'. (Do nothing if 'victim' is NULL.) - */ -void trn_extension_field_cc_free(trn_extension_field_cc_t *victim); -/** Try to parse a trn_extension_field_cc from the buffer in 'input', - * using up to 'len_in' bytes from the input buffer. On success, - * return the number of bytes consumed and set *output to the newly - * allocated trn_extension_field_cc_t. On failure, return -2 if the - * input appears truncated, and -1 if the input is otherwise invalid. - */ -ssize_t trn_extension_field_cc_parse(trn_extension_field_cc_t **output, const uint8_t *input, const size_t len_in); -/** Return the number of bytes we expect to need to encode the - * trn_extension_field_cc in 'obj'. On failure, return a negative - * value. Note that this value may be an overestimate, and can even be - * an underestimate for certain unencodeable objects. - */ -ssize_t trn_extension_field_cc_encoded_len(const trn_extension_field_cc_t *obj); -/** Try to encode the trn_extension_field_cc from 'input' into the - * buffer at 'output', using up to 'avail' bytes of the output buffer. - * On success, return the number of bytes used. On failure, return -2 - * if the buffer was not long enough, and -1 if the input was invalid. - */ -ssize_t trn_extension_field_cc_encode(uint8_t *output, size_t avail, const trn_extension_field_cc_t *input); -/** Check whether the internal state of the trn_extension_field_cc in - * 'obj' is consistent. Return NULL if it is, and a short message if - * it is not. - */ -const char *trn_extension_field_cc_check(const trn_extension_field_cc_t *obj); -/** Clear any errors that were set on the object 'obj' by its setter - * functions. Return true iff errors were cleared. - */ -int trn_extension_field_cc_clear_errors(trn_extension_field_cc_t *obj); -/** Return the value of the sendme_inc field of the - * trn_extension_field_cc_t in 'inp' - */ -uint8_t trn_extension_field_cc_get_sendme_inc(const trn_extension_field_cc_t *inp); -/** Set the value of the sendme_inc field of the - * trn_extension_field_cc_t in 'inp' to 'val'. Return 0 on success; - * return -1 and set the error code on 'inp' on failure. - */ -int trn_extension_field_cc_set_sendme_inc(trn_extension_field_cc_t *inp, uint8_t val); - - -#endif diff --git a/src/trunnel/congestion_control.trunnel b/src/trunnel/congestion_control.trunnel deleted file mode 100644 index 50697a0cd2..0000000000 --- a/src/trunnel/congestion_control.trunnel +++ /dev/null @@ -1,22 +0,0 @@ -/* This file contains the definition for the encrypted payload of a circuit - * parameter negotiation request/response portion of the trn_ntorv3 onionskin - * handshake. Currently only supports congestion control params. */ - -/* The following is encoded in the extension format. */ - -/* Field types. */ -const TRUNNEL_EXT_TYPE_CC_FIELD_REQUEST = 0x01; -const TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE = 0x02; - -/* - * "Request" is an empty payload signalling that CC is enabled. - */ - -/* - * "Response" consists of 1 single byte: - * SENDME_INC -- Min: 0, Max: 255 - */ - -struct trn_extension_field_cc { - u8 sendme_inc; -}; diff --git a/src/trunnel/include.am b/src/trunnel/include.am index 3c20acecaa..e4d35038f6 100644 --- a/src/trunnel/include.am +++ b/src/trunnel/include.am @@ -14,7 +14,6 @@ TRUNNELINPUTS = \ src/trunnel/channelpadding_negotiation.trunnel \ src/trunnel/sendme_cell.trunnel \ src/trunnel/flow_control_cells.trunnel \ - src/trunnel/congestion_control.trunnel \ src/trunnel/socks5.trunnel \ src/trunnel/circpad_negotiation.trunnel \ src/trunnel/conflux.trunnel \ @@ -32,7 +31,6 @@ TRUNNELSOURCES = \ src/trunnel/channelpadding_negotiation.c \ src/trunnel/sendme_cell.c \ src/trunnel/flow_control_cells.c \ - src/trunnel/congestion_control.c \ src/trunnel/socks5.c \ src/trunnel/netinfo.c \ src/trunnel/circpad_negotiation.c \ @@ -53,7 +51,6 @@ TRUNNELHEADERS = \ src/trunnel/channelpadding_negotiation.h \ src/trunnel/sendme_cell.h \ src/trunnel/flow_control_cells.h \ - src/trunnel/congestion_control.h \ src/trunnel/socks5.h \ src/trunnel/netinfo.h \ src/trunnel/circpad_negotiation.h \ diff --git a/src/trunnel/ntorv3.c b/src/trunnel/ntorv3.c index ff10fbff29..8f223fb485 100644 --- a/src/trunnel/ntorv3.c +++ b/src/trunnel/ntorv3.c @@ -28,6 +28,159 @@ int ntorv_deadcode_dummy__ = 0; } \ } while (0) +trn_ntorv3_ext_cc_response_t * +trn_ntorv3_ext_cc_response_new(void) +{ + trn_ntorv3_ext_cc_response_t *val = trunnel_calloc(1, sizeof(trn_ntorv3_ext_cc_response_t)); + if (NULL == val) + return NULL; + return val; +} + +/** Release all storage held inside 'obj', but do not free 'obj'. + */ +static void +trn_ntorv3_ext_cc_response_clear(trn_ntorv3_ext_cc_response_t *obj) +{ + (void) obj; +} + +void +trn_ntorv3_ext_cc_response_free(trn_ntorv3_ext_cc_response_t *obj) +{ + if (obj == NULL) + return; + trn_ntorv3_ext_cc_response_clear(obj); + trunnel_memwipe(obj, sizeof(trn_ntorv3_ext_cc_response_t)); + trunnel_free_(obj); +} + +uint8_t +trn_ntorv3_ext_cc_response_get_sendme_inc(const trn_ntorv3_ext_cc_response_t *inp) +{ + return inp->sendme_inc; +} +int +trn_ntorv3_ext_cc_response_set_sendme_inc(trn_ntorv3_ext_cc_response_t *inp, uint8_t val) +{ + inp->sendme_inc = val; + return 0; +} +const char * +trn_ntorv3_ext_cc_response_check(const trn_ntorv3_ext_cc_response_t *obj) +{ + if (obj == NULL) + return "Object was NULL"; + if (obj->trunnel_error_code_) + return "A set function failed on this object"; + return NULL; +} + +ssize_t +trn_ntorv3_ext_cc_response_encoded_len(const trn_ntorv3_ext_cc_response_t *obj) +{ + ssize_t result = 0; + + if (NULL != trn_ntorv3_ext_cc_response_check(obj)) + return -1; + + + /* Length of u8 sendme_inc */ + result += 1; + return result; +} +int +trn_ntorv3_ext_cc_response_clear_errors(trn_ntorv3_ext_cc_response_t *obj) +{ + int r = obj->trunnel_error_code_; + obj->trunnel_error_code_ = 0; + return r; +} +ssize_t +trn_ntorv3_ext_cc_response_encode(uint8_t *output, const size_t avail, const trn_ntorv3_ext_cc_response_t *obj) +{ + ssize_t result = 0; + size_t written = 0; + uint8_t *ptr = output; + const char *msg; +#ifdef TRUNNEL_CHECK_ENCODED_LEN + const ssize_t encoded_len = trn_ntorv3_ext_cc_response_encoded_len(obj); +#endif + + if (NULL != (msg = trn_ntorv3_ext_cc_response_check(obj))) + goto check_failed; + +#ifdef TRUNNEL_CHECK_ENCODED_LEN + trunnel_assert(encoded_len >= 0); +#endif + + /* Encode u8 sendme_inc */ + trunnel_assert(written <= avail); + if (avail - written < 1) + goto truncated; + trunnel_set_uint8(ptr, (obj->sendme_inc)); + written += 1; ptr += 1; + + + trunnel_assert(ptr == output + written); +#ifdef TRUNNEL_CHECK_ENCODED_LEN + { + trunnel_assert(encoded_len >= 0); + trunnel_assert((size_t)encoded_len == written); + } + +#endif + + return written; + + truncated: + result = -2; + goto fail; + check_failed: + (void)msg; + result = -1; + goto fail; + fail: + trunnel_assert(result < 0); + return result; +} + +/** As trn_ntorv3_ext_cc_response_parse(), but do not allocate the + * output object. + */ +static ssize_t +trn_ntorv3_ext_cc_response_parse_into(trn_ntorv3_ext_cc_response_t *obj, const uint8_t *input, const size_t len_in) +{ + const uint8_t *ptr = input; + size_t remaining = len_in; + ssize_t result = 0; + (void)result; + + /* Parse u8 sendme_inc */ + CHECK_REMAINING(1, truncated); + obj->sendme_inc = (trunnel_get_uint8(ptr)); + remaining -= 1; ptr += 1; + trunnel_assert(ptr + remaining == input + len_in); + return len_in - remaining; + + truncated: + return -2; +} + +ssize_t +trn_ntorv3_ext_cc_response_parse(trn_ntorv3_ext_cc_response_t **output, const uint8_t *input, const size_t len_in) +{ + ssize_t result; + *output = trn_ntorv3_ext_cc_response_new(); + if (NULL == *output) + return -1; + result = trn_ntorv3_ext_cc_response_parse_into(*output, input, len_in); + if (result < 0) { + trn_ntorv3_ext_cc_response_free(*output); + *output = NULL; + } + return result; +} trn_ntorv3_ext_subproto_req_t * trn_ntorv3_ext_subproto_req_new(void) { diff --git a/src/trunnel/ntorv3.h b/src/trunnel/ntorv3.h index dfa4bac6dc..9ed5138a1b 100644 --- a/src/trunnel/ntorv3.h +++ b/src/trunnel/ntorv3.h @@ -8,7 +8,16 @@ #include #include "trunnel.h" -#define TRUNNEL_EXT_TYPE_SUBPROTO_REQ 3 +#define TRUNNEL_NTORV3_EXT_TYPE_CC_REQ 1 +#define TRUNNEL_NTORV3_EXT_TYPE_CC_RESPONSE 2 +#define TRUNNEL_NTORV3_EXT_TYPE_SUBPROTO_REQ 3 +#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_TRN_NTORV3_EXT_CC_RESPONSE) +struct trn_ntorv3_ext_cc_response_st { + uint8_t sendme_inc; + uint8_t trunnel_error_code_; +}; +#endif +typedef struct trn_ntorv3_ext_cc_response_st trn_ntorv3_ext_cc_response_t; #if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_TRN_NTORV3_EXT_SUBPROTO_REQ) struct trn_ntorv3_ext_subproto_req_st { uint8_t proto_id; @@ -24,6 +33,52 @@ struct trn_ntorv3_ext_subproto_st { }; #endif typedef struct trn_ntorv3_ext_subproto_st trn_ntorv3_ext_subproto_t; +/** Return a newly allocated trn_ntorv3_ext_cc_response with all + * elements set to zero. + */ +trn_ntorv3_ext_cc_response_t *trn_ntorv3_ext_cc_response_new(void); +/** Release all storage held by the trn_ntorv3_ext_cc_response in + * 'victim'. (Do nothing if 'victim' is NULL.) + */ +void trn_ntorv3_ext_cc_response_free(trn_ntorv3_ext_cc_response_t *victim); +/** Try to parse a trn_ntorv3_ext_cc_response from the buffer in + * 'input', using up to 'len_in' bytes from the input buffer. On + * success, return the number of bytes consumed and set *output to the + * newly allocated trn_ntorv3_ext_cc_response_t. On failure, return -2 + * if the input appears truncated, and -1 if the input is otherwise + * invalid. + */ +ssize_t trn_ntorv3_ext_cc_response_parse(trn_ntorv3_ext_cc_response_t **output, const uint8_t *input, const size_t len_in); +/** Return the number of bytes we expect to need to encode the + * trn_ntorv3_ext_cc_response in 'obj'. On failure, return a negative + * value. Note that this value may be an overestimate, and can even be + * an underestimate for certain unencodeable objects. + */ +ssize_t trn_ntorv3_ext_cc_response_encoded_len(const trn_ntorv3_ext_cc_response_t *obj); +/** Try to encode the trn_ntorv3_ext_cc_response from 'input' into the + * buffer at 'output', using up to 'avail' bytes of the output buffer. + * On success, return the number of bytes used. On failure, return -2 + * if the buffer was not long enough, and -1 if the input was invalid. + */ +ssize_t trn_ntorv3_ext_cc_response_encode(uint8_t *output, size_t avail, const trn_ntorv3_ext_cc_response_t *input); +/** Check whether the internal state of the trn_ntorv3_ext_cc_response + * in 'obj' is consistent. Return NULL if it is, and a short message + * if it is not. + */ +const char *trn_ntorv3_ext_cc_response_check(const trn_ntorv3_ext_cc_response_t *obj); +/** Clear any errors that were set on the object 'obj' by its setter + * functions. Return true iff errors were cleared. + */ +int trn_ntorv3_ext_cc_response_clear_errors(trn_ntorv3_ext_cc_response_t *obj); +/** Return the value of the sendme_inc field of the + * trn_ntorv3_ext_cc_response_t in 'inp' + */ +uint8_t trn_ntorv3_ext_cc_response_get_sendme_inc(const trn_ntorv3_ext_cc_response_t *inp); +/** Set the value of the sendme_inc field of the + * trn_ntorv3_ext_cc_response_t in 'inp' to 'val'. Return 0 on + * success; return -1 and set the error code on 'inp' on failure. + */ +int trn_ntorv3_ext_cc_response_set_sendme_inc(trn_ntorv3_ext_cc_response_t *inp, uint8_t val); /** Return a newly allocated trn_ntorv3_ext_subproto_req with all * elements set to zero. */ diff --git a/src/trunnel/ntorv3.trunnel b/src/trunnel/ntorv3.trunnel index fee756af39..80d25fac59 100644 --- a/src/trunnel/ntorv3.trunnel +++ b/src/trunnel/ntorv3.trunnel @@ -1,8 +1,13 @@ +/* This file contains the definition for the encrypted payload of a circuit + * parameter negotiation request/response portion of the trn_ntorv3 onionskin + * handshake. */ + /* - * The ntorv3 extension type value in order to recognize the subproto - * extension. + * The ntorv3 extension type value. */ -const TRUNNEL_EXT_TYPE_SUBPROTO_REQ = 0x03; +const TRUNNEL_NTORV3_EXT_TYPE_CC_REQ = 0x01; +const TRUNNEL_NTORV3_EXT_TYPE_CC_RESPONSE = 0x02; +const TRUNNEL_NTORV3_EXT_TYPE_SUBPROTO_REQ = 0x03; /* * Extension used to negotiate subprotocol versions detailed in proposal 346. @@ -20,3 +25,17 @@ struct trn_ntorv3_ext_subproto_req { /* Protocol version being requested. */ u8 proto_version; } + +/* + * Congestion Control + */ + +/* "Request" is an empty payload signalling that CC is enabled. */ + +/* + * "Response" consists of 1 single byte: + * SENDME_INC -- Min: 0, Max: 255 + */ +struct trn_ntorv3_ext_cc_response { + u8 sendme_inc; +};