From f51f438875a435da34aca75b5e7dd4cc97d7a095 Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Wed, 17 Apr 2024 18:43:25 +0200 Subject: [PATCH] BUG/MEDIUM: peers: fix localpeer regression with 'bind+server' config style 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 | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/cfgparse.c b/src/cfgparse.c index b159a5a03..b3d60bd47 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -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);