]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: define a generic QUIC error type
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 13 Jul 2022 13:07:56 +0000 (15:07 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 15 Jul 2022 12:57:49 +0000 (14:57 +0200)
Define a new structure quic_err to abstract a QUIC error type. This
allows to easily differentiate a transport and an application error
code. This simplifies error transmission from QUIC MUX and H3 layers.

This new type is defined in quic_frame module. It is used to replace
<err_code> field in <quic_conn>. QUIC_FL_CONN_APP_ALERT flag is removed
as it is now useless.

Utility functions are defined to be able to quickly instantiate
transport, tls and application errors.

include/haproxy/quic_frame-t.h
include/haproxy/quic_frame.h
include/haproxy/xprt_quic-t.h
include/haproxy/xprt_quic.h
src/mux_quic.c
src/xprt_quic.c

index f5945368ad5fc676aa5e5cf12e9dbb1dfb623653..7770f61878608959b12dbb4f306bbbeb0b550113 100644 (file)
@@ -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 */
index 4a79e86a0527e30d10503644c83881027077d491..0926411c608044d5e444203d43920aefb847eab3 100644 (file)
@@ -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 */
index c07395f473747eb0b7ef3a55f0866e72a7d832d0..7ef6122a6deb200cc5a407b68bfdeadbdd61b15f 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <haproxy/mux_quic-t.h>
 #include <haproxy/quic_cc-t.h>
+#include <haproxy/quic_frame-t.h>
 #include <haproxy/quic_loss-t.h>
 #include <haproxy/quic_stats-t.h>
 #include <haproxy/quic_tls-t.h>
@@ -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;
 
index cf9e4ee7ad14a9edbbd05254410836abc709bfc4..9f42bd1153cb2c3ccbca4268db85ea561cb22092 100644 (file)
@@ -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);
index ba62598cad7b9182c73493ba5672f9bf0cbc51b2..065ffa57fe3d2199b5e6ce57cc8467113e585c46 100644 (file)
@@ -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);
 }
index 88cf4fded664c103dcb53493715760a60f3835e8..d736dcbaa1c23a92ed09988ea9586f7a9085dead 100644 (file)
@@ -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 <err>. All send/receive
  * activity for <qc> 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 <alert> 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;
        }