]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: peers: fix localpeer regression with 'bind+server' config style
authorAurelien DARRAGON <adarragon@haproxy.com>
Wed, 17 Apr 2024 16:43:25 +0000 (18:43 +0200)
committerAurelien DARRAGON <adarragon@haproxy.com>
Thu, 18 Apr 2024 09:18:13 +0000 (11:18 +0200)
A dumb mistake was made in f6ae25858 ("MINOR: peers: rely on srv->addr
and remove peer->addr"). I completely overlooked the part where the bind
address settings are used as implicit server's address settings when the
peers are declared using the new bind+server config style (which is the
new recommended method to declare peers as it follows the same logic as
the one used in other proxy sections).

As such, the peers synchro fails to work between previous and new process
(localpeer mechanism) upon reload when declaring peers with way:

global
localpeer local

peers mypeers
bind 127.0.0.1:10001
server local

And one has to use the 'old' config style to make it work:

global
localpeer local

peers mypeers
peer local 127.0.0.1:10001

--

To fix the issue, let's explicitly set the server's addr:port
according to the bind's address settings (only the first listener is
considered) when local peer was declared using the 'bind+server' method.

No backport needed.

src/cfgparse.c

index b159a5a039f92c0df869ac84517dc12cc5564f25..b3d60bd470fa183a993a2119963ead81f87f4a71 100644 (file)
@@ -658,6 +658,7 @@ static struct peer *cfg_peers_add_peer(struct peers *peers,
 int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
 {
        static struct peers *curpeers = NULL;
+       static struct sockaddr_storage *bind_addr = NULL;
        static int nb_shards = 0;
        struct peer *newpeer = NULL;
        const char *err;
@@ -728,12 +729,20 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
                         * Newly allocated listener is at the end of the list
                         */
                        l = LIST_ELEM(bind_conf->listeners.p, typeof(l), by_bind);
+                       bind_addr = &l->rx.addr;
 
                        global.maxsock++; /* for the listening socket */
 
                        bind_line = 1;
                        if (cfg_peers->local) {
+                               /* Local peer already defined using "server" line has no
+                                * address yet, we should update its server's addr:port
+                                * settings
+                                */
                                newpeer = cfg_peers->local;
+                               BUG_ON(!newpeer->srv);
+                               newpeer->srv->addr = *bind_addr;
+                               newpeer->srv->svc_port = get_host_port(bind_addr);
                        }
                        else {
                                /* This peer is local.
@@ -776,6 +785,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
        else if (strcmp(args[0], "peers") == 0) { /* new peers section */
                /* Initialize these static variables when entering a new "peers" section*/
                bind_line = peer_line = 0;
+               bind_addr = NULL;
                if (!*args[1]) {
                        ha_alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
                        err_code |= ERR_ALERT | ERR_ABORT;
@@ -886,6 +896,15 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
                        goto out;
                }
 
+               if (!parse_addr && bind_addr) {
+                       /* local peer declared using "server": has name but no
+                        * address: we use the known "bind" line addr settings
+                        * as implicit server's addr and port.
+                        */
+                       curpeers->peers_fe->srv->addr = *bind_addr;
+                       curpeers->peers_fe->srv->svc_port = get_host_port(bind_addr);
+               }
+
                if (nb_shards && curpeers->peers_fe->srv->shard > nb_shards) {
                        ha_warning("parsing [%s:%d] : '%s %s' : %d peer shard greater value than %d shards value is ignored.\n",
                                   file, linenum, args[0], args[1], curpeers->peers_fe->srv->shard, nb_shards);