diff --git a/include/haproxy/quic_frame-t.h b/include/haproxy/quic_frame-t.h index f5945368a..7770f6187 100644 --- a/include/haproxy/quic_frame-t.h +++ b/include/haproxy/quic_frame-t.h @@ -273,5 +273,33 @@ struct quic_frame { unsigned int flags; }; + +/* QUIC error codes */ +struct quic_err { + uint64_t code; /* error code */ + int app; /* set for Application error code */ +}; + +/* Transport level error codes. */ +#define QC_ERR_NO_ERROR 0x00 +#define QC_ERR_INTERNAL_ERROR 0x01 +#define QC_ERR_CONNECTION_REFUSED 0x02 +#define QC_ERR_FLOW_CONTROL_ERROR 0x03 +#define QC_ERR_STREAM_LIMIT_ERROR 0x04 +#define QC_ERR_STREAM_STATE_ERROR 0x05 +#define QC_ERR_FINAL_SIZE_ERROR 0x06 +#define QC_ERR_FRAME_ENCODING_ERROR 0x07 +#define QC_ERR_TRANSPORT_PARAMETER_ERROR 0x08 +#define QC_ERR_CONNECTION_ID_LIMIT_ERROR 0x09 +#define QC_ERR_PROTOCOL_VIOLATION 0x0a +#define QC_ERR_INVALID_TOKEN 0x0b +#define QC_ERR_APPLICATION_ERROR 0x0c +#define QC_ERR_CRYPTO_BUFFER_EXCEEDED 0x0d +#define QC_ERR_KEY_UPDATE_ERROR 0x0e +#define QC_ERR_AEAD_LIMIT_REACHED 0x0f +#define QC_ERR_NO_VIABLE_PATH 0x10 +/* 256 TLS reserved errors 0x100-0x1ff. */ +#define QC_ERR_CRYPTO_ERROR 0x100 + #endif /* USE_QUIC */ #endif /* _TYPES_QUIC_FRAME_H */ diff --git a/include/haproxy/quic_frame.h b/include/haproxy/quic_frame.h index 4a79e86a0..0926411c6 100644 --- a/include/haproxy/quic_frame.h +++ b/include/haproxy/quic_frame.h @@ -160,5 +160,21 @@ static inline size_t qc_frm_len(struct quic_frame *frm) return len; } +static inline struct quic_err quic_err_transport(uint64_t code) +{ + return (struct quic_err){ .code = code, .app = 0 }; +} + +static inline struct quic_err quic_err_tls(uint64_t tls_alert) +{ + const uint64_t code = QC_ERR_CRYPTO_ERROR|tls_alert; + return (struct quic_err){ .code = code, .app = 0 }; +} + +static inline struct quic_err quic_err_app(uint64_t code) +{ + return (struct quic_err){ .code = code, .app = 1 }; +} + #endif /* USE_QUIC */ #endif /* _HAPROXY_QUIC_FRAME_H */ diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h index c07395f47..7ef6122a6 100644 --- a/include/haproxy/xprt_quic-t.h +++ b/include/haproxy/xprt_quic-t.h @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -164,29 +165,6 @@ enum quic_pkt_type { #define QUIC_PACKET_KEY_PHASE_BIT 0x04 /* (protected) */ -/* - * Transport level error codes. - */ -#define QC_ERR_NO_ERROR 0x00 -#define QC_ERR_INTERNAL_ERROR 0x01 -#define QC_ERR_CONNECTION_REFUSED 0x02 -#define QC_ERR_FLOW_CONTROL_ERROR 0x03 -#define QC_ERR_STREAM_LIMIT_ERROR 0x04 -#define QC_ERR_STREAM_STATE_ERROR 0x05 -#define QC_ERR_FINAL_SIZE_ERROR 0x06 -#define QC_ERR_FRAME_ENCODING_ERROR 0x07 -#define QC_ERR_TRANSPORT_PARAMETER_ERROR 0x08 -#define QC_ERR_CONNECTION_ID_LIMIT_ERROR 0x09 -#define QC_ERR_PROTOCOL_VIOLATION 0x0a -#define QC_ERR_INVALID_TOKEN 0x0b -#define QC_ERR_APPLICATION_ERROR 0x0c -#define QC_ERR_CRYPTO_BUFFER_EXCEEDED 0x0d -#define QC_ERR_KEY_UPDATE_ERROR 0x0e -#define QC_ERR_AEAD_LIMIT_REACHED 0x0f -#define QC_ERR_NO_VIABLE_PATH 0x10 -/* 256 TLS reserved errors 0x100-0x1ff. */ -#define QC_ERR_CRYPTO_ERROR 0x100 - /* The maximum number of QUIC packets stored by the fd I/O handler by QUIC * connection. Must be a power of two. */ @@ -619,7 +597,7 @@ enum qc_mux_state { #define QUIC_FL_CONN_RETRANS_NEEDED (1U << 7) #define QUIC_FL_CONN_RETRANS_OLD_DATA (1U << 8) #define QUIC_FL_CONN_TLS_ALERT (1U << 9) -#define QUIC_FL_CONN_APP_ALERT (1U << 10) /* A connection error of type CONNECTION_CLOSE_APP must be emitted. */ +/* gap here */ #define QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED (1U << 11) /* The half-open connection counter was decremented */ #define QUIC_FL_CONN_NOTIFY_CLOSE (1U << 27) /* MUX notified about quic-conn imminent closure (idle-timeout or CONNECTION_CLOSE emission/reception) */ #define QUIC_FL_CONN_EXP_TIMER (1U << 28) /* timer has expired, quic-conn can be freed */ @@ -637,7 +615,7 @@ struct quic_conn { int tid; int state; enum qc_mux_state mux_state; /* status of the connection/mux layer */ - uint64_t err_code; + struct quic_err err; unsigned char enc_params[QUIC_TP_MAX_ENCLEN]; /* encoded QUIC transport parameters */ size_t enc_params_len; diff --git a/include/haproxy/xprt_quic.h b/include/haproxy/xprt_quic.h index cf9e4ee7a..9f42bd115 100644 --- a/include/haproxy/xprt_quic.h +++ b/include/haproxy/xprt_quic.h @@ -767,7 +767,7 @@ static inline void qc_list_all_rx_pkts(struct quic_conn *qc) void chunk_frm_appendf(struct buffer *buf, const struct quic_frame *frm); -void quic_set_connection_close(struct quic_conn *qc, int err, int app); +void quic_set_connection_close(struct quic_conn *qc, const struct quic_err err); void quic_set_tls_alert(struct quic_conn *qc, int alert); int quic_set_app_ops(struct quic_conn *qc, const unsigned char *alpn, size_t alpn_len); struct task *quic_lstnr_dghdlr(struct task *t, void *ctx, unsigned int state); diff --git a/src/mux_quic.c b/src/mux_quic.c index ba62598ca..065ffa57f 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -107,7 +107,7 @@ INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE); */ static void qcc_emit_cc(struct qcc *qcc, int err) { - quic_set_connection_close(qcc->conn->handle.qc, err, 0); + quic_set_connection_close(qcc->conn->handle.qc, quic_err_transport(err)); qcc->flags |= QC_CF_CC_EMIT; tasklet_wakeup(qcc->wait_event.tasklet); } @@ -671,7 +671,7 @@ static int qcc_decode_qcs(struct qcc *qcc, struct qcs *qcs) */ void qcc_emit_cc_app(struct qcc *qcc, int err) { - quic_set_connection_close(qcc->conn->handle.qc, err, 1); + quic_set_connection_close(qcc->conn->handle.qc, quic_err_app(err)); qcc->flags |= QC_CF_CC_EMIT; tasklet_wakeup(qcc->wait_event.tasklet); } diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 88cf4fded..d736dcbaa 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -438,8 +438,8 @@ static void quic_trace(enum trace_level level, uint64_t mask, const struct trace quic_enc_level_char(ssl_to_quic_enc_level(level))); } - if (qc->err_code) - chunk_appendf(&trace_buf, " err_code=0x%llx", (ull)qc->err_code); + if (qc->err.code) + chunk_appendf(&trace_buf, " err_code=0x%llx", (ull)qc->err.code); } if (mask & (QUIC_EV_CONN_PRSFRM|QUIC_EV_CONN_BFRM)) { @@ -1057,16 +1057,14 @@ static int quic_crypto_data_cpy(struct quic_enc_level *qel, /* Prepare the emission of CONNECTION_CLOSE with error . All send/receive * activity for will be interrupted. */ -void quic_set_connection_close(struct quic_conn *qc, int err, int app) +void quic_set_connection_close(struct quic_conn *qc, const struct quic_err err) { if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE) return; - qc->err_code = err; qc->flags |= QUIC_FL_CONN_IMMEDIATE_CLOSE; - - if (app) - qc->flags |= QUIC_FL_CONN_APP_ALERT; + qc->err.code = err.code; + qc->err.app = err.app; } /* Set TLS alert as QUIC CRYPTO_ERROR error */ @@ -1076,7 +1074,7 @@ void quic_set_tls_alert(struct quic_conn *qc, int alert) qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED; HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn); } - quic_set_connection_close(qc, QC_ERR_CRYPTO_ERROR | alert, 0); + quic_set_connection_close(qc, quic_err_tls(alert)); qc->flags |= QUIC_FL_CONN_TLS_ALERT; TRACE_PROTO("Alert set", QUIC_EV_CONN_SSLDATA, qc); } @@ -4319,6 +4317,7 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4, qc->dcid.len = dcid->len; } qc->mux_state = QC_MUX_NULL; + qc->err = quic_err_transport(QC_ERR_NO_ERROR); icid = new_quic_cid(&qc->cids, qc, 0); if (!icid) { @@ -6141,10 +6140,10 @@ static int qc_do_build_pkt(unsigned char *pos, const unsigned char *end, len += QUIC_TLS_TAG_LEN; /* CONNECTION_CLOSE frame */ if (cc) { - cc_frm.type = qc->flags & QUIC_FL_CONN_APP_ALERT ? + cc_frm.type = qc->err.app ? QUIC_FT_CONNECTION_CLOSE_APP : QUIC_FT_CONNECTION_CLOSE; - cc_frm.connection_close.error_code = qc->err_code; + cc_frm.connection_close.error_code = qc->err.code; len += qc_frm_len(&cc_frm); } add_ping_frm = 0; @@ -6441,8 +6440,7 @@ static int qc_xprt_start(struct connection *conn, void *ctx) if (qcc_install_app_ops(qc->qcc, qc->app_ops)) { TRACE_PROTO("Cannot install app layer", QUIC_EV_CONN_LPKT, qc); /* prepare a CONNECTION_CLOSE frame */ - qc->err_code = QC_ERR_APPLICATION_ERROR; - qc->flags |= QUIC_FL_CONN_IMMEDIATE_CLOSE; + quic_set_connection_close(qc, quic_err_transport(QC_ERR_APPLICATION_ERROR)); return -1; }