mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-01-20 17:41:06 +01:00
At this time haproxy supported only incompatible version negotiation feature which consists in sending a Version Negotiation packet after having received a long packet without compatible value in its version field. This version value is the version use to build the current packet. This patch does not modify this behavior. This patch adds the support for compatible version negotiation feature which allows endpoints to negotiate during the first flight or packets sent by the client the QUIC version to use for the connection (or after the first flight). This is done thanks to "version_information" parameter sent by both endpoints. To be short, the client offers a list of supported versions by preference order. The server (or haproxy listener) chooses the first version it also supported as negotiated version. This implementation has an impact on the tranport parameters handling (in both direcetions). Indeed, the server must sent its version information, but only after received and parsed the client transport parameters). So we cannot encode these parameters at the same time we instantiated a new connection. Add QUIC_TP_DRAFT_VERSION_INFORMATION(0xff73db) new transport parameter. Add tp_version_information new C struct to handle this new parameter. Implement quic_transport_param_enc_version_info() (resp. quic_transport_param_dec_version_info()) to encode (resp. decode) this parameter. Add qc_conn_finalize() which encodes the transport parameters and configure the TLS stack to send them. Add ->negotiated_ictx quic_conn C struct new member to store the Initial QUIC TLS context for the negotiated version. The Initial secrets derivation is version dependent. Rename ->version to ->original_version and add ->negotiated_version to this C struct to reflect the QUIC-VN RFC denomination. Modify most of the QUIC TLS API functions to pass a version as parameter. Export the QUIC version definitions to be reused at least from quic_tp.c (transport parameters. Move the token check after the QUIC connection lookup. As this is the original version which is sent into a Retry packet, and because this original version is stored into the connection, we must check the token after having retreived this connection. Add packet version to traces. See https://datatracker.ietf.org/doc/html/draft-ietf-quic-version-negotiation-08 for more information about this new feature.
77 lines
3.4 KiB
C
77 lines
3.4 KiB
C
#ifndef _HAPROXY_QUIC_TP_H
|
|
#define _HAPROXY_QUIC_TP_H
|
|
#ifdef USE_QUIC
|
|
#ifndef USE_OPENSSL
|
|
#error "Must define USE_OPENSSL"
|
|
#endif
|
|
|
|
#include <haproxy/chunk.h>
|
|
#include <haproxy/quic_tp-t.h>
|
|
#include <haproxy/xprt_quic-t.h>
|
|
|
|
void quic_transport_params_init(struct quic_transport_params *p, int server);
|
|
int quic_transport_params_encode(unsigned char *buf,
|
|
const unsigned char *end,
|
|
struct quic_transport_params *p,
|
|
const struct quic_version *choosen_version,
|
|
int server);
|
|
|
|
int quic_transport_params_store(struct quic_conn *conn, int server,
|
|
const unsigned char *buf,
|
|
const unsigned char *end);
|
|
|
|
int qc_lstnr_params_init(struct quic_conn *qc,
|
|
const struct quic_transport_params *listener_params,
|
|
const unsigned char *stateless_reset_token,
|
|
const unsigned char *dcid, size_t dcidlen,
|
|
const unsigned char *scid, size_t scidlen,
|
|
const unsigned char *odcid, size_t odcidlen, int token);
|
|
|
|
/* Dump <cid> transport parameter connection ID value if present (non null length).
|
|
* Used only for debugging purposes.
|
|
*/
|
|
static inline void quic_tp_cid_dump(struct buffer *buf,
|
|
const struct tp_cid *cid)
|
|
{
|
|
int i;
|
|
|
|
chunk_appendf(buf, "(%d", cid->len);
|
|
if (cid->len)
|
|
chunk_appendf(buf, ",");
|
|
for (i = 0; i < cid->len; i++)
|
|
chunk_appendf(buf, "%02x", cid->data[i]);
|
|
chunk_appendf(buf, ")");
|
|
}
|
|
|
|
static inline void quic_transport_params_dump(struct buffer *b,
|
|
const struct quic_transport_params *p)
|
|
{
|
|
chunk_appendf(b, "\n\toriginal_destination_connection_id:");
|
|
quic_tp_cid_dump(b, &p->original_destination_connection_id);
|
|
chunk_appendf(b, "\n\tinitial_source_connection_id:");
|
|
quic_tp_cid_dump(b, &p->initial_source_connection_id);
|
|
chunk_appendf(b, "\n\tretry_source_connection_id:");
|
|
quic_tp_cid_dump(b, &p->retry_source_connection_id);
|
|
|
|
chunk_appendf(b, "\n\tmax_idle_timeout=%llu", (ull)p->max_idle_timeout);
|
|
chunk_appendf(b, "\n\tmax_udp_payload_size=%llu", (ull)p->max_udp_payload_size);
|
|
chunk_appendf(b, "\n\tinitial_max_data=%llu", (ull)p->initial_max_data);
|
|
chunk_appendf(b, "\n\tinitial_max_stream_data_bidi_local=%llu",
|
|
(ull)p->initial_max_stream_data_bidi_local);
|
|
chunk_appendf(b, "\n\tinitial_max_stream_data_bidi_remote=%llu",
|
|
(ull)p->initial_max_stream_data_bidi_remote);
|
|
chunk_appendf(b, "\n\tinitial_max_stream_data_uni=%llu",
|
|
(ull)p->initial_max_stream_data_uni);
|
|
chunk_appendf(b, "\n\tinitial_max_streams_bidi=%llu", (ull)p->initial_max_streams_bidi);
|
|
chunk_appendf(b, "\n\tinitial_max_streams_uni=%llu", (ull)p->initial_max_streams_uni);
|
|
chunk_appendf(b, "\n\tack_delay_exponent=%llu", (ull)p->ack_delay_exponent);
|
|
chunk_appendf(b, "\n\tmax_ack_delay=%llu", (ull)p->max_ack_delay);
|
|
chunk_appendf(b, "\n\tactive_connection_id_limit=%llu", (ull)p->active_connection_id_limit);
|
|
chunk_appendf(b, "\n\tdisable_active_migration? %s", p->disable_active_migration ? "yes" : "no");
|
|
chunk_appendf(b, "\n\twith_stateless_reset_token? %s", p->with_stateless_reset_token ? "yes" : "no");
|
|
chunk_appendf(b, "\n\twith_preferred_address? %s", p->with_preferred_address ? "yes" : "no");
|
|
}
|
|
|
|
#endif /* USE_QUIC */
|
|
#endif /* _HAPROXY_QUIC_TP_H */
|