From: Frédéric Lécaille <[email protected]>
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