BUG/MINOR: connection: Use the client's dst family for adressless servers
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 1 Mar 2021 10:33:59 +0000 (11:33 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 1 Mar 2021 17:58:03 +0000 (18:58 +0100)
When the selected server has no address, the destination address of the
client is used. However, for now, only the address is set, not the
family. Thus depending on how the server is configured and the client's
destination address, the server address family may be wrong.

For instance, with such server :

   server srv 0.0.0.0:0

The server address family is AF_INET. The server connection will fail if a
client is asking for an IPv6 destination.

To fix the bug, we take care to set the rigth family, the family of the
client destination address.

This patch should fix the issue #202. It must be backported to all stable
versions.

(cherry picked from commit ae3056157c17b181c754556836a5d8336fb9823f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 63f4db3ffb9ccc5ed24c39118fee7a882529df3f)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 123f1352303b9d7d3087504029c7bb3c5eb85429)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

src/backend.c

index 53a2464..12a426f 100644 (file)
@@ -852,8 +852,10 @@ int assign_server_address(struct stream *s)
                        if (!conn_get_dst(cli_conn)) {
                                /* do nothing if we can't retrieve the address */
                        } else if (cli_conn->dst->ss_family == AF_INET) {
+                               ((struct sockaddr_in *)s->target_addr)->sin_family = AF_INET;
                                ((struct sockaddr_in *)s->target_addr)->sin_addr = ((struct sockaddr_in *)cli_conn->dst)->sin_addr;
                        } else if (cli_conn->dst->ss_family == AF_INET6) {
+                               ((struct sockaddr_in6 *)s->target_addr)->sin6_family = AF_INET6;
                                ((struct sockaddr_in6 *)s->target_addr)->sin6_addr = ((struct sockaddr_in6 *)cli_conn->dst)->sin6_addr;
                        }
                }