diff --git a/include/haproxy/server.h b/include/haproxy/server.h index 3829bce2b..730493362 100644 --- a/include/haproxy/server.h +++ b/include/haproxy/server.h @@ -33,6 +33,7 @@ #include #include #include +#include __decl_thread(extern HA_SPINLOCK_T idle_conn_srv_lock); @@ -305,6 +306,16 @@ static inline void srv_minmax_conn_apply(struct server *srv) } } +/* Returns true if server is used as transparent mode. */ +static inline int srv_is_transparent(const struct server *srv) +{ + /* A reverse server does not have any address but it is not used as a + * transparent one. + */ + return (!is_addr(&srv->addr) && !(srv->flags & SRV_F_REVERSE)) || + (srv->flags & SRV_F_MAPPORTS); +} + #endif /* _HAPROXY_SERVER_H */ /* diff --git a/src/backend.c b/src/backend.c index ef132376b..a2deaed47 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1326,7 +1326,7 @@ static int connect_server(struct stream *s) struct connection *cli_conn = objt_conn(strm_orig(s)); struct connection *srv_conn = NULL; struct server *srv; - const int reuse_mode = s->be->options & PR_O_REUSE_MASK; + int reuse_mode = s->be->options & PR_O_REUSE_MASK; int reuse = 0; int init_mux = 0; int err; @@ -1342,6 +1342,10 @@ static int connect_server(struct stream *s) * it can be NULL for dispatch mode or transparent backend */ srv = objt_server(s->target); + /* Override reuse-mode if reverse-connect is used. */ + if (srv && srv->flags & SRV_F_REVERSE) + reuse_mode = PR_O_REUSE_ALWS; + err = alloc_dst_address(&s->scb->dst, srv, s); if (err != SRV_STATUS_OK) return SF_ERR_INTERNAL; @@ -1393,7 +1397,7 @@ static int connect_server(struct stream *s) #endif /* USE_OPENSSL */ /* 3. destination address */ - if (srv && (!is_addr(&srv->addr) || srv->flags & SRV_F_MAPPORTS)) + if (srv && srv_is_transparent(srv)) hash_params.dst_addr = s->scb->dst; /* 4. source address */ @@ -1587,6 +1591,12 @@ static int connect_server(struct stream *s) skip_reuse: /* no reuse or failed to reuse the connection above, pick a new one */ if (!srv_conn) { + if (srv && (srv->flags & SRV_F_REVERSE)) { + DBG_TRACE_USER("cannot open a new connection for reverse server", STRM_EV_STRM_PROC|STRM_EV_CS_ST, s); + s->conn_err_type = STRM_ET_CONN_ERR; + return SF_ERR_INTERNAL; + } + srv_conn = conn_new(s->target); if (srv_conn) { DBG_TRACE_STATE("alloc new be connection", STRM_EV_STRM_PROC|STRM_EV_CS_ST, s);