]> git.kaiwu.me - haproxy.git/commit
BUG/MINOR: quic: use datagram destination as source for version negotiation
authorYeonggi Kim <yg.kim@navercorp.com>
Thu, 15 Oct 2026 23:45:56 +0000 (08:45 +0900)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 16 Oct 2026 07:31:06 +0000 (09:31 +0200)
commite5a306040ec953305e78a25f8c20af9364c659af
tree02662388930f4b92c294c32a9aa8227aaf6344a1
parentf633d891786dfca7580f48e966b8017094746ad6
BUG/MINOR: quic: use datagram destination as source for version negotiation

When a QUIC listener is bound on a wildcard address, the source address
of emitted datagrams must be the local address targeted by the client,
else the kernel selects it from the route to the client. Both may differ
when several addresses are assigned to the host, for example VIPs
configured on a loopback interface behind a load balancer in direct
routing mode. In this case, QUIC clients relying on a connected UDP
socket silently drop the datagram.

Version Negotiation packets are emitted without connection, via
send_version_negotiation() which used a bare sendto() on the listener
socket without source address. In the above conditions, a client which
offers an unsupported QUIC version never receives the list of supported
versions, so it cannot switch to one of them.

Fix this by adding a source address parameter to
send_version_negotiation(), before the destination one, similarly to the
previous patches for Retry and stateless reset. Its caller sets it to
the datagram destination address, and emission now relies on
quic_lstnr_sock_send(), which only uses it if the listener is bound on a
wildcard address. Apart from the source address, the emission is
unchanged.

This should fix github issue #3503.

This should be backported up to 2.8. Note that it relies on the first
two patches of the series:
  - MINOR: quic: use the listener for Retry and Version Negotiation emission
  - MINOR: quic: define a function to emit a datagram on a listener socket
Prior to 3.4, quic_dgram addresses are of sockaddr_storage type, so the
casts are not necessary. Prior to 2.9, send_version_negotiation() is a
static function defined in quic_conn.c.
include/haproxy/quic_tx.h
src/quic_rx.c
src/quic_tx.c