BUG/MEDIUM: tcp: transparent bind to the source only when address is set
Thomas Heil reported that health checks did not work anymore when a backend or server has "usesrc clientip". This is because the source address is not set and tcp_bind_socket() tries to bind to that address anyway. The solution consists in explicitly clearing the source address in the checks and to make tcp_bind_socket() avoid binding when the address is not set. This also has an indirect benefit that a useless bind() syscall will be avoided when using "source 0.0.0.0 usesrc clientip" in health checks.
This commit is contained in:
parent
422a0a5161
commit
5f2877a7dd
@ -1308,6 +1308,9 @@ static struct task *process_chk(struct task *t)
|
|||||||
set_target_server(&conn->target, s);
|
set_target_server(&conn->target, s);
|
||||||
conn_prepare(conn, &check_conn_cb, s->check.proto, s->check.xprt, s);
|
conn_prepare(conn, &check_conn_cb, s->check.proto, s->check.xprt, s);
|
||||||
|
|
||||||
|
/* no client address */
|
||||||
|
clear_addr(&conn->addr.from);
|
||||||
|
|
||||||
if (is_addr(&s->check.addr))
|
if (is_addr(&s->check.addr))
|
||||||
/* we'll connect to the check addr specified on the server */
|
/* we'll connect to the check addr specified on the server */
|
||||||
conn->addr.to = s->check.addr;
|
conn->addr.to = s->check.addr;
|
||||||
|
@ -170,14 +170,18 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so
|
|||||||
|
|
||||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
|
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
|
||||||
if (foreign_ok) {
|
if (foreign_ok) {
|
||||||
ret = bind(fd, (struct sockaddr *)&bind_addr, get_addr_len(&bind_addr));
|
if (is_addr(&bind_addr)) {
|
||||||
if (ret < 0)
|
ret = bind(fd, (struct sockaddr *)&bind_addr, get_addr_len(&bind_addr));
|
||||||
return 2;
|
if (ret < 0)
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ret = bind(fd, (struct sockaddr *)local, get_addr_len(local));
|
if (is_addr(local)) {
|
||||||
if (ret < 0)
|
ret = bind(fd, (struct sockaddr *)local, get_addr_len(local));
|
||||||
return 1;
|
if (ret < 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!flags)
|
if (!flags)
|
||||||
@ -295,15 +299,17 @@ int tcp_connect_server(struct connection *conn, int data)
|
|||||||
if (srv != NULL && srv->state & SRV_BIND_SRC) {
|
if (srv != NULL && srv->state & SRV_BIND_SRC) {
|
||||||
int ret, flags = 0;
|
int ret, flags = 0;
|
||||||
|
|
||||||
switch (srv->state & SRV_TPROXY_MASK) {
|
if (is_addr(&conn->addr.from)) {
|
||||||
case SRV_TPROXY_ADDR:
|
switch (srv->state & SRV_TPROXY_MASK) {
|
||||||
case SRV_TPROXY_CLI:
|
case SRV_TPROXY_ADDR:
|
||||||
flags = 3;
|
case SRV_TPROXY_CLI:
|
||||||
break;
|
flags = 3;
|
||||||
case SRV_TPROXY_CIP:
|
break;
|
||||||
case SRV_TPROXY_DYN:
|
case SRV_TPROXY_CIP:
|
||||||
flags = 1;
|
case SRV_TPROXY_DYN:
|
||||||
break;
|
flags = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SO_BINDTODEVICE
|
#ifdef SO_BINDTODEVICE
|
||||||
@ -368,15 +374,17 @@ int tcp_connect_server(struct connection *conn, int data)
|
|||||||
else if (be->options & PR_O_BIND_SRC) {
|
else if (be->options & PR_O_BIND_SRC) {
|
||||||
int ret, flags = 0;
|
int ret, flags = 0;
|
||||||
|
|
||||||
switch (be->options & PR_O_TPXY_MASK) {
|
if (is_addr(&conn->addr.from)) {
|
||||||
case PR_O_TPXY_ADDR:
|
switch (be->options & PR_O_TPXY_MASK) {
|
||||||
case PR_O_TPXY_CLI:
|
case PR_O_TPXY_ADDR:
|
||||||
flags = 3;
|
case PR_O_TPXY_CLI:
|
||||||
break;
|
flags = 3;
|
||||||
case PR_O_TPXY_CIP:
|
break;
|
||||||
case PR_O_TPXY_DYN:
|
case PR_O_TPXY_CIP:
|
||||||
flags = 1;
|
case PR_O_TPXY_DYN:
|
||||||
break;
|
flags = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SO_BINDTODEVICE
|
#ifdef SO_BINDTODEVICE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user