From: Frédéric Lécaille <flecai...@haproxy.com> Make "bind" line also parse the local peer bind address. Add "default-bind" option to parse the binding options excepted the bind address. Prevent "bind" lines to be mixed with "peer" line to help in handling the migration. --- src/cfgparse.c | 153 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 122 insertions(+), 31 deletions(-)
diff --git a/src/cfgparse.c b/src/cfgparse.c index ef69b37d..2a6a4839 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -516,7 +516,8 @@ static int init_peers_frontend(const char *file, int linenum, p->id = strdup(id); free(p->conf.file); p->conf.args.file = p->conf.file = strdup(file); - p->conf.args.line = p->conf.line = linenum; + if (linenum != -1) + p->conf.args.line = p->conf.line = linenum; return 0; } @@ -546,6 +547,44 @@ static struct bind_conf *bind_conf_uniq_alloc(struct proxy *p, return bind_conf; } + +/* + * Allocate a new struct peer parsed at line <linenum> in file <file> + * to be added to <peers>. + * Returns the new allocated structure if succeeded, NULL if not. + */ +static struct peer *cfg_peers_add_peer(struct peers *peers, + const char *file, int linenum, + const char *id, int local) +{ + struct peer *p; + + p = calloc(1, sizeof *p); + if (!p) { + ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); + return NULL; + } + + /* the peers are linked backwards first */ + peers->count++; + p->next = peers->remote; + peers->remote = p; + p->conf.file = strdup(file); + p->conf.line = linenum; + p->last_change = now.tv_sec; + p->xprt = xprt_get(XPRT_RAW); + p->sock_init_arg = NULL; + HA_SPIN_INIT(&p->lock); + if (id) + p->id = strdup(id); + if (local) { + p->local = 1; + peers->local = p; + } + + return p; +} + /* * Parse a line in a <listen>, <frontend> or <backend> section. * Returns the error code, 0 if OK, or any combination of : @@ -565,8 +604,9 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) struct listener *l; int err_code = 0; char *errmsg = NULL; + static int bind_line, peer_line; - if (strcmp(args[0], "bind") == 0) { + if (strcmp(args[0], "bind") == 0 || strcmp(args[0], "default-bind") == 0) { int cur_arg; static int kws_dumped; struct bind_conf *bind_conf; @@ -582,6 +622,44 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, linenum, NULL, xprt_get(XPRT_RAW)); + if (*args[0] == 'b') { + struct sockaddr_storage *sk; + int port, port1, port2; + + if (peer_line) { + ha_alert("parsing [%s:%d] : mixing \"peer\" and \"bind\" line is forbidden\n", file, linenum); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + sk = str2sa_range(args[1], &port, &port1, &port2, &errmsg, NULL, NULL, 0); + if (!sk) { + ha_alert("parsing [%s:%d]: '%s %s': %s\n", + file, linenum, args[0], args[1], errmsg); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + bind_line = 1; + if (cfg_peers->local) { + newpeer = cfg_peers->local; + } + else { + /* This peer is local. + * Note that we do not set the peer ID. This latter is initialized + * when parsing "peer" or "server" line. + */ + newpeer = cfg_peers_add_peer(curpeers, file, linenum, NULL, 1); + if (!newpeer) { + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + } + newpeer->addr = *sk; + newpeer->proto = protocol_by_family(newpeer->addr.ss_family); + cur_arg++; + } + while (*args[cur_arg] && (kw = bind_find_kw(args[cur_arg]))) { int ret; @@ -616,13 +694,15 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) } } else if (strcmp(args[0], "default-server") == 0) { - if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) { + if (init_peers_frontend(file, -1, NULL, curpeers) != 0) { err_code |= ERR_ALERT | ERR_ABORT; goto out; } err_code |= parse_server(file, linenum, args, curpeers->peers_fe, NULL); } 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; if (!*args[1]) { ha_alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; @@ -668,27 +748,50 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) } else if (strcmp(args[0], "peer") == 0 || strcmp(args[0], "server") == 0) { /* peer or server definition */ - if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) { - ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); - err_code |= ERR_ALERT | ERR_ABORT; - goto out; - } + int local_peer; - /* the peers are linked backwards first */ - curpeers->count++; - newpeer->next = curpeers->remote; - curpeers->remote = newpeer; - newpeer->conf.file = strdup(file); - newpeer->conf.line = linenum; - - newpeer->last_change = now.tv_sec; - newpeer->id = strdup(args[1]); + local_peer = !strcmp(args[1], localpeer); + /* The local peer may have already partially been parsed on a "bind" line. */ + if (*args[0] == 'p') { + if (bind_line) { + ha_alert("parsing [%s:%d] : mixing \"peer\" and \"bind\" line is forbidden\n", file, linenum); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + peer_line = 1; + } + if (cfg_peers->local && !cfg_peers->local->id && local_peer) { + /* The local peer has already been initialized on a "bind" line. + * Let's use it and store its ID. + */ + newpeer = cfg_peers->local; + newpeer->id = strdup(localpeer); + } + else { + if (local_peer && cfg_peers->local) { + ha_alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d. %s\n", + file, linenum, args[0], args[1], + curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line, cfg_peers->local->id); + err_code |= ERR_FATAL; + goto out; + } + newpeer = cfg_peers_add_peer(curpeers, file, linenum, args[1], local_peer); + if (!newpeer) { + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + } - if (init_peers_frontend(file, linenum, newpeer->id, curpeers) != 0) { + /* Line number and peer ID are updated only if this peer is the local one. */ + if (init_peers_frontend(file, + newpeer->local ? linenum: -1, + newpeer->local ? newpeer->id : NULL, + curpeers) != 0) { err_code |= ERR_ALERT | ERR_ABORT; goto out; } + /* This initializes curpeer->peers->peers_fe->srv. */ err_code |= parse_server(file, linenum, args, curpeers->peers_fe, NULL); if (!curpeers->peers_fe->srv) goto out; @@ -699,22 +802,11 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) newpeer->sock_init_arg = NULL; HA_SPIN_INIT(&newpeer->lock); - if (strcmp(newpeer->id, localpeer) != 0) { + if (!newpeer->local) { newpeer->srv = curpeers->peers_fe->srv; goto out; } - if (cfg_peers->local) { - ha_alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n", - file, linenum, args[0], args[1], - curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line); - err_code |= ERR_FATAL; - goto out; - } - - /* Current is local peer, it define a frontend */ - newpeer->local = 1; - bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { @@ -738,7 +830,6 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */ global.maxsock += l->maxconn; } - cfg_peers->local = newpeer; } /* neither "peer" nor "peers" */ else if (!strcmp(args[0], "disabled")) { /* disables this peers section */ curpeers->state = PR_STSTOPPED; -- 2.11.0