#include <haproxy/api-t.h>
#include <haproxy/namespace-t.h>
#include <haproxy/proto_reverse_connect-t.h>
+#include <haproxy/quic_sock-t.h>
#include <haproxy/thread.h>
/* Bit values for receiver->flags */
struct list proto_list; /* list in the protocol header */
#ifdef USE_QUIC
struct mt_list rxbuf_list; /* list of buffers to receive and dispatch QUIC datagrams. */
+ enum quic_sock_mode quic_mode; /* QUIC socket allocation strategy */
#endif
struct {
struct task *task; /* Task used to open connection for reverse. */
goto udp_return;
}
+ /* Duplicate quic_mode setting from bind_conf. Useful to overwrite it
+ * at runtime per receiver instance.
+ */
+ listener->rx.quic_mode = listener->bind_conf->quic_mode;
+
/* Set IP_PKTINFO to retrieve destination address on recv. */
fd = listener->rx.fd;
switch (addr.ss_family) {
conn_id->qc = qc;
- if (l->bind_conf->quic_mode == QUIC_SOCK_MODE_CONN &&
+ if (HA_ATOMIC_LOAD(&l->rx.quic_mode) == QUIC_SOCK_MODE_CONN &&
(global.tune.options & GTUNE_QUIC_SOCK_PER_CONN) &&
is_addr(local_addr)) {
TRACE_USER("Allocate a socket for QUIC connection", QUIC_EV_CONN_INIT, qc);
#define TRACE_SOURCE &trace_quic
+/* Log only first EACCES bind() error runtime occurence. */
+static volatile char quic_bind_eacces_warn = 0;
+
/* Retrieve a connection's source address. Returns -1 on failure. */
int quic_sock_get_src(struct connection *conn, struct sockaddr *addr, socklen_t len)
{
void qc_alloc_fd(struct quic_conn *qc, const struct sockaddr_storage *src,
const struct sockaddr_storage *dst)
{
- struct proxy *p = qc->li->bind_conf->frontend;
+ struct bind_conf *bc = qc->li->bind_conf;
+ struct proxy *p = bc->frontend;
int fd = -1;
int ret;
goto err;
ret = bind(fd, (struct sockaddr *)src, get_addr_len(src));
- if (ret < 0)
+ if (ret < 0) {
+ if (errno == EACCES) {
+ if (!quic_bind_eacces_warn) {
+ send_log(p, LOG_WARNING,
+ "Permission error on QUIC socket binding for proxy %s. Consider using setcap cap_net_bind_service (Linux only) or running as root.\n",
+ p->id);
+ quic_bind_eacces_warn = 1;
+ }
+
+ /* Fallback to listener socket for this receiver instance. */
+ HA_ATOMIC_STORE(&qc->li->rx.quic_mode, QUIC_SOCK_MODE_LSTNR);
+ }
goto err;
+ }
ret = connect(fd, (struct sockaddr *)dst, get_addr_len(dst));
if (ret < 0)