]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: checks: correctly configure the address family and protocol
authorWilly Tarreau <w@1wt.eu>
Fri, 9 May 2014 21:38:15 +0000 (23:38 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 9 May 2014 23:26:37 +0000 (01:26 +0200)
Currently, mixing an IPv4 and an IPv6 address in checks happens to
work by pure luck because the two protocols use the same functions
at the socket level and both use IPPROTO_TCP. However, they're
definitely wrong as the protocol for the check address is retrieved
from the server's address.

Now the protocol assigned to the connection is the same as the one
the address in use belongs to (eg: the server's address or the
explicit check address).

src/checks.c
src/server.c

index fceb2c74efda6c4046a22730e8f6e4140f6b2194..5eb5a76c8451a5141aa0bd19ab350aae9a6b0680 100644 (file)
@@ -1509,6 +1509,7 @@ static struct task *process_chk(struct task *t)
        struct check *check = t->context;
        struct server *s = check->server;
        struct connection *conn = check->conn;
+       struct protocol *proto;
        int rv;
        int ret;
        int expired = tick_is_expired(t->expire, now_ms);
@@ -1573,12 +1574,16 @@ static struct task *process_chk(struct task *t)
                /* no client address */
                clear_addr(&conn->addr.from);
 
-               if (is_addr(&s->check_common.addr))
+               if (is_addr(&s->check_common.addr)) {
                        /* we'll connect to the check addr specified on the server */
                        conn->addr.to = s->check_common.addr;
-               else
+                       proto = s->check_common.proto;
+               }
+               else {
                        /* we'll connect to the addr on the server */
                        conn->addr.to = s->addr;
+                       proto = s->proto;
+               }
 
                if (check->port) {
                        set_host_port(&conn->addr.to, check->port);
@@ -1606,8 +1611,8 @@ static struct task *process_chk(struct task *t)
                 * connect() when a pure TCP check is used (without PROXY protocol).
                 */
                ret = SN_ERR_INTERNAL;
-               if (s->check_common.proto->connect)
-                       ret = s->check_common.proto->connect(conn, check->type, (check->type) ? 0 : 2);
+               if (proto->connect)
+                       ret = proto->connect(conn, check->type, (check->type) ? 0 : 2);
                conn->flags |= CO_FL_WAKE_DATA;
                if (s->check.send_proxy) {
                        conn->send_proxy_ofs = 1;
@@ -2075,15 +2080,16 @@ static void tcpcheck_main(struct connection *conn)
                        /* no client address */
                        clear_addr(&conn->addr.from);
 
-                       if (is_addr(&s->check_common.addr))
+                       if (is_addr(&s->check_common.addr)) {
                                /* we'll connect to the check addr specified on the server */
                                conn->addr.to = s->check_common.addr;
-                       else
+                               proto = s->check_common.proto;
+                       }
+                       else {
                                /* we'll connect to the addr on the server */
                                conn->addr.to = s->addr;
-
-                       /* protocol */
-                       proto = protocol_by_family(conn->addr.to.ss_family);
+                               proto = s->proto;
+                       }
 
                        /* port */
                        if (check->current_step->port)
index 565a108be8043b84b5ef747eba4a159b13470a55..51bb85aff85d19cfb9693a0ef81fc26697d9ca8b 100644 (file)
@@ -597,6 +597,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
                                }
 
                                newsrv->check_common.addr = *sk;
+                               newsrv->check_common.proto = protocol_by_family(sk->ss_family);
                                cur_arg += 2;
                        }
                        else if (!strcmp(args[cur_arg], "port")) {