]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic-be: Store asap the DCID
authorFrederic Lecaille <flecaille@haproxy.com>
Fri, 12 Jan 2024 13:39:08 +0000 (14:39 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 11 Jun 2025 16:37:34 +0000 (18:37 +0200)
Store the peer connection ID (SCID) as the connection DCID as soon as an Initial
packet is received.
Stop comparing the packet to QUIC_PACKET_TYPE_0RTT is already match as
QUIC_PACKET_TYPE_INITIAL.
A QUIC server must not send too short datagram with ack-eliciting packets inside.
This cannot be done from quic_rx_pkt_parse() because one does not know if
there is ack-eliciting frame into the Initial packets. If the packet must be
dropped, this is after having parsed it!

include/haproxy/quic_conn-t.h
src/quic_rx.c

index cec1203aea1632fa9300be64777187b388576b03..a8ffd9e7a5e24f1e28c988800c0973b98342243a 100644 (file)
@@ -460,6 +460,7 @@ struct quic_conn_closed {
 #define QUIC_FL_CONN_HPKTNS_DCD                  (1U << 16) /* Handshake packet number space discarded  */
 #define QUIC_FL_CONN_PEER_VALIDATED_ADDR         (1U << 17) /* Peer address is considered as validated for this connection. */
 #define QUIC_FL_CONN_NO_TOKEN_RCVD               (1U << 18) /* Client dit not send any token */
+#define QUIC_FL_CONN_SCID_RECEIVED               (1U << 19) /* (client only: first Initial received. */
 /* gap here */
 #define QUIC_FL_CONN_TO_KILL                     (1U << 24) /* Unusable connection, to be killed */
 #define QUIC_FL_CONN_TX_TP_RECEIVED              (1U << 25) /* Peer transport parameters have been received (used for the transmitting part) */
index b1b0a39abc141ebfde1f505cf81e5a12d7289029..3b6a678d66c17094750995d51dfa48dae8ca4683 100644 (file)
@@ -1878,13 +1878,14 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
  * if the packet is incomplete. This function will populate fields of <pkt>
  * instance, most notably its length. <dgram> is the UDP datagram which
  * contains the parsed packet. <o> is the address object type address of the
- * object which receives this received packet.
+ * object which receives this received packet. <qc> is the QUIC connection,
+ * only valid for QUIC clients.
  *
  * Returns 0 on success else non-zero. Packet length is guaranteed to be set to
  * the real packet value or to cover all data between <pos> and <end> : this is
  * useful to reject a whole datagram.
  */
-static int quic_rx_pkt_parse(struct quic_rx_packet *pkt,
+static int quic_rx_pkt_parse(struct quic_conn *qc, struct quic_rx_packet *pkt,
                              unsigned char *pos, const unsigned char *end,
                              struct quic_dgram *dgram, enum obj_type *o)
 {
@@ -2014,23 +2015,44 @@ static int quic_rx_pkt_parse(struct quic_rx_packet *pkt,
                 * datagram.
                 */
 
-               /* RFC 9000. Initial Datagram Size
-                *
-                * A server MUST discard an Initial packet that is carried in a UDP datagram
-                * with a payload that is smaller than the smallest allowed maximum datagram
-                * size of 1200 bytes.
-                */
-               if (pkt->type == QUIC_PACKET_TYPE_INITIAL &&
-                   dgram->len < QUIC_INITIAL_PACKET_MINLEN) {
-                       TRACE_PROTO("RX too short datagram with an Initial packet", QUIC_EV_CONN_LPKT);
-                       HA_ATOMIC_INC(&prx_counters->too_short_initial_dgram);
-                       goto drop;
+               if (pkt->type == QUIC_PACKET_TYPE_INITIAL) {
+                       if (l) {
+                               /* RFC 9000. Initial Datagram Size
+                                *
+                                * A server MUST discard an Initial packet that is carried in a UDP datagram
+                                * with a payload that is smaller than the smallest allowed maximum datagram
+                                * size of 1200 bytes.
+                                */
+                               if (dgram->len < QUIC_INITIAL_PACKET_MINLEN) {
+                                       TRACE_PROTO("RX too short datagram with an Initial packet", QUIC_EV_CONN_LPKT);
+                                       HA_ATOMIC_INC(&prx_counters->too_short_initial_dgram);
+                                       goto drop;
+                               }
+                       }
+                       else {
+                               /* TODO: This is not clear if a too short RX datagram which carries ack-eliciting
+                                * packets must be dropped by a client. If this is the case, this is not from
+                                * here, but after having parsed the datagram frames.
+                                *
+                                * RFC 9000. Initial Datagram Size
+                                *
+                                * Similarly, a server MUST expand the payload of all UDP datagrams carrying
+                                * ack-eliciting Initial packets to at least the smallest allowed maximum
+                                * datagram size of 1200 bytes.
+                                */
+                               if (!(qc->flags & QUIC_FL_CONN_SCID_RECEIVED)) {
+                                       qc->flags |= QUIC_FL_CONN_SCID_RECEIVED;
+                                       memcpy(qc->dcid.data, pkt->scid.data, pkt->scid.len);
+                                       qc->dcid.len = pkt->scid.len;
+                               }
+                       }
                }
-
-               /* O-RTT packet are not sent by servers. */
-               if (pkt->type == QUIC_PACKET_TYPE_0RTT && (!l || !l->bind_conf->ssl_conf.early_data)) {
-                       TRACE_PROTO("RX 0-RTT packet not supported", QUIC_EV_CONN_LPKT);
-                       goto drop;
+               else if (pkt->type == QUIC_PACKET_TYPE_0RTT) {
+                       /* O-RTT packet are not sent by servers. */
+                       if (!l || !l->bind_conf->ssl_conf.early_data) {
+                               TRACE_PROTO("RX 0-RTT packet not supported", QUIC_EV_CONN_LPKT);
+                               goto drop;
+                       }
                }
        }
        else {
@@ -2303,7 +2325,7 @@ int quic_dgram_parse(struct quic_dgram *dgram, struct quic_conn *from_qc,
                        pkt->flags |= QUIC_FL_RX_PACKET_DGRAM_FIRST;
 
                quic_rx_packet_refinc(pkt);
-               if (quic_rx_pkt_parse(pkt, pos, end, dgram, o))
+               if (quic_rx_pkt_parse(from_qc, pkt, pos, end, dgram, o))
                        goto next;
 
                /* Search quic-conn instance for first packet of the datagram.