diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h index 6e22fe1b3..5cfd3daa3 100644 --- a/include/haproxy/xprt_quic-t.h +++ b/include/haproxy/xprt_quic-t.h @@ -420,6 +420,14 @@ struct quic_pktns { unsigned int flags; }; +/* QUIC datagram */ +struct quic_dgram { + unsigned char *buf; + size_t len; + struct sockaddr_storage saddr; + struct list list; +}; + /* The QUIC packet numbers are 62-bits integers */ #define QUIC_MAX_PACKET_NUM ((1ULL << 62) - 1) diff --git a/include/haproxy/xprt_quic.h b/include/haproxy/xprt_quic.h index a24df7480..4bda6a74d 100644 --- a/include/haproxy/xprt_quic.h +++ b/include/haproxy/xprt_quic.h @@ -1184,8 +1184,8 @@ void chunk_frm_appendf(struct buffer *buf, const struct quic_frame *frm); 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); -ssize_t quic_lstnr_dgram_read(unsigned char *buf, size_t len, void *owner, - struct sockaddr_storage *saddr); +int quic_lstnr_dgram_read(unsigned char *buf, size_t len, void *owner, + struct sockaddr_storage *saddr, struct list *dgrams); #endif /* USE_QUIC */ #endif /* _HAPROXY_XPRT_QUIC_H */ diff --git a/src/quic_sock.c b/src/quic_sock.c index ef94acb15..ef03908c6 100644 --- a/src/quic_sock.c +++ b/src/quic_sock.c @@ -212,7 +212,8 @@ void quic_sock_fd_iocb(int fd) } while (0); b_add(buf, ret); - quic_lstnr_dgram_read((unsigned char *)b_head(buf), ret, l, &saddr); + quic_lstnr_dgram_read((unsigned char *)b_head(buf), ret, + l, &saddr, &rxbuf->dgrams); b_del(buf, ret); out: MT_LIST_APPEND(&l->rx.rxbuf_list, &rxbuf->mt_list); diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 0a0e6f333..cc3985e91 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -160,6 +160,7 @@ DECLARE_STATIC_POOL(pool_head_quic_conn_ctx, DECLARE_STATIC_POOL(pool_head_quic_conn, "quic_conn", sizeof(struct quic_conn)); DECLARE_POOL(pool_head_quic_connection_id, "quic_connnection_id_pool", sizeof(struct quic_connection_id)); +DECLARE_POOL(pool_head_quic_dgram, "quic_dgram", sizeof(struct quic_dgram)); DECLARE_POOL(pool_head_quic_rx_packet, "quic_rx_packet_pool", sizeof(struct quic_rx_packet)); DECLARE_POOL(pool_head_quic_tx_packet, "quic_tx_packet_pool", sizeof(struct quic_tx_packet)); DECLARE_STATIC_POOL(pool_head_quic_rx_crypto_frm, "quic_rx_crypto_frm_pool", sizeof(struct quic_rx_crypto_frm)); @@ -5401,10 +5402,62 @@ static ssize_t quic_dgram_read(unsigned char *buf, size_t len, void *owner, return -1; } -ssize_t quic_lstnr_dgram_read(unsigned char *buf, size_t len, void *owner, - struct sockaddr_storage *saddr) +/* Retreive the DCID from a QUIC datagram or packet with as first octet. + * Returns 1 if succeeded, 0 if not. + */ +static int quic_get_dgram_dcid(unsigned char *buf, const unsigned char *end, + unsigned char **dcid, size_t *dcid_len) { + int long_header; + size_t minlen, skip; + + if (!(*buf & QUIC_PACKET_FIXED_BIT)) + goto err; + + long_header = *buf & QUIC_PACKET_LONG_HEADER_BIT; + minlen = long_header ? + QUIC_LONG_PACKET_MINLEN : QUIC_SHORT_PACKET_MINLEN + QUIC_HAP_CID_LEN; + skip = long_header ? QUIC_LONG_PACKET_DCID_OFF : QUIC_SHORT_PACKET_DCID_OFF; + if (end - buf <= minlen || !(*buf & QUIC_PACKET_FIXED_BIT)) + goto err; + + buf += skip; + *dcid_len = long_header ? *buf++ : QUIC_HAP_CID_LEN; + if (*dcid_len > QUIC_CID_MAXLEN || end - buf <= *dcid_len) + goto err; + + *dcid = buf; + + return 1; + + err: + TRACE_PROTO("wrong datagram", QUIC_EV_CONN_LPKT); + return 0; +} + +int quic_lstnr_dgram_read(unsigned char *buf, size_t len, void *owner, + struct sockaddr_storage *saddr, struct list *dgrams) +{ + struct quic_dgram *dgram; + unsigned char *dcid; + size_t dcid_len; + + if (!len || !quic_get_dgram_dcid(buf, buf + len, &dcid, &dcid_len)) + goto out; + + dgram = pool_alloc(pool_head_quic_dgram); + if (!dgram) + goto out; + + dgram->buf = buf; + dgram->len = len; + dgram->saddr = *saddr; + LIST_APPEND(dgrams, &dgram->list); + return quic_dgram_read(buf, len, owner, saddr, qc_lstnr_pkt_rcv); + + out: + return 0; } /* Function to automatically activate QUIC traces on stdout.