MINOR: cfgparse: SSL/TLS binding in "peers" sections.
Make "bind" keywork be supported in "peers" sections.
All "bind" settings are supported on this line.
Add "default-bind" option to parse the binding options excepted the bind address.
Do not parse anymore the bind address for local peers on "server" lines.
Do not use anymore list_for_each_entry() to set the "peers" section
listener parameters because there is only one listener by "peers" section.
May be backported to 1.5 and newer.
diff --git a/include/proto/server.h b/include/proto/server.h
index b3a9b87..436ffb5 100644
--- a/include/proto/server.h
+++ b/include/proto/server.h
@@ -39,7 +39,7 @@
int srv_downtime(const struct server *s);
int srv_lastsession(const struct server *s);
int srv_getinter(const struct check *check);
-int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy);
+int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy, int parse_addr);
int update_server_addr(struct server *s, void *ip, int ip_sin_family, const char *updater);
const char *update_server_addr_port(struct server *s, const char *addr, const char *port, char *updater);
struct server *server_find_by_id(struct proxy *bk, int id);
diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c
index 1af86de..2a7ed53 100644
--- a/src/cfgparse-listen.c
+++ b/src/cfgparse-listen.c
@@ -675,7 +675,7 @@
if (!strcmp(args[0], "server") ||
!strcmp(args[0], "default-server") ||
!strcmp(args[0], "server-template")) {
- err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
+ err_code |= parse_server(file, linenum, args, curproxy, &defproxy, 1);
if (err_code & ERR_FATAL)
goto out;
}
diff --git a/src/cfgparse.c b/src/cfgparse.c
index a5343ea..a12c4ee 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -515,11 +515,75 @@
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;
}
+/* Only change ->file, ->line and ->arg struct bind_conf member values
+ * if already present.
+ */
+static struct bind_conf *bind_conf_uniq_alloc(struct proxy *p,
+ const char *file, int line,
+ const char *arg, struct xprt_ops *xprt)
+{
+ struct bind_conf *bind_conf;
+
+ if (!LIST_ISEMPTY(&p->conf.bind)) {
+ bind_conf = LIST_ELEM((&p->conf.bind)->n, typeof(bind_conf), by_fe);
+ free(bind_conf->file);
+ bind_conf->file = strdup(file);
+ bind_conf->line = line;
+ if (arg) {
+ free(bind_conf->arg);
+ bind_conf->arg = strdup(arg);
+ }
+ }
+ else {
+ bind_conf = bind_conf_alloc(p, file, line, arg, xprt);
+ }
+
+ 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 :
@@ -539,15 +603,117 @@
struct listener *l;
int err_code = 0;
char *errmsg = NULL;
+ static int bind_line, peer_line;
+
+ if (strcmp(args[0], "bind") == 0 || strcmp(args[0], "default-bind") == 0) {
+ int cur_arg;
+ static int kws_dumped;
+ struct bind_conf *bind_conf;
+ struct bind_kw *kw;
+ char *kws;
- if (strcmp(args[0], "default-server") == 0) {
+ cur_arg = 1;
+
if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) {
err_code |= ERR_ALERT | ERR_ABORT;
goto out;
}
+
+ bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, linenum,
+ NULL, xprt_get(XPRT_RAW));
+ if (*args[0] == 'b') {
+ struct listener *l;
+
+ 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;
+ }
+
+ if (!str2listener(args[1], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
+ if (errmsg && *errmsg) {
+ indent_msg(&errmsg, 2);
+ ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
+ }
+ else
+ ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
+ file, linenum, args[0], args[1], args[2]);
+ err_code |= ERR_FATAL;
+ goto out;
+ }
+ l = LIST_ELEM(bind_conf->listeners.n, typeof(l), by_bind);
+ l->maxaccept = 1;
+ l->maxconn = curpeers->peers_fe->maxconn;
+ l->backlog = curpeers->peers_fe->backlog;
+ l->accept = session_accept_fd;
+ l->analysers |= curpeers->peers_fe->fe_req_ana;
+ l->default_target = curpeers->peers_fe->default_target;
+ l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
+ global.maxsock += l->maxconn;
+
+ 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 = l->addr;
+ newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
+ cur_arg++;
+ }
+
+ while (*args[cur_arg] && (kw = bind_find_kw(args[cur_arg]))) {
+ int ret;
+
+ ret = kw->parse(args, cur_arg, curpeers->peers_fe, bind_conf, &errmsg);
+ err_code |= ret;
+ if (ret) {
+ if (errmsg && *errmsg) {
+ indent_msg(&errmsg, 2);
+ ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
+ }
+ else
+ ha_alert("parsing [%s:%d]: error encountered while processing '%s'\n",
+ file, linenum, args[cur_arg]);
+ if (ret & ERR_FATAL)
+ goto out;
+ }
+ cur_arg += 1 + kw->skip;
+ }
+ kws = NULL;
+ if (!kws_dumped) {
+ kws_dumped = 1;
+ bind_dump_kws(&kws);
+ indent_msg(&kws, 4);
+ }
+ if (*args[cur_arg] != 0) {
+ ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section.%s%s\n",
+ file, linenum, args[cur_arg], cursection,
+ kws ? " Registered keywords :" : "", kws ? kws: "");
+ free(kws);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (strcmp(args[0], "default-server") == 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);
+ err_code |= parse_server(file, linenum, args, curpeers->peers_fe, NULL, 0);
}
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;
@@ -593,28 +759,51 @@
}
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;
}
- err_code |= parse_server(file, linenum, args, curpeers->peers_fe, NULL);
+ /* This initializes curpeer->peers->peers_fe->srv. */
+ err_code |= parse_server(file, linenum, args, curpeers->peers_fe, NULL, !local_peer);
if (!curpeers->peers_fe->srv)
goto out;
@@ -624,23 +813,16 @@
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;
+ /* The lines above are reserved to "peer" lines. */
+ if (*args[0] == 's')
goto out;
- }
-
- /* Current is local peer, it define a frontend */
- newpeer->local = 1;
- bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
+ 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)) {
if (errmsg && *errmsg) {
@@ -653,17 +835,16 @@
err_code |= ERR_FATAL;
goto out;
}
- list_for_each_entry(l, &bind_conf->listeners, by_bind) {
- l->maxaccept = 1;
- l->maxconn = curpeers->peers_fe->maxconn;
- l->backlog = curpeers->peers_fe->backlog;
- l->accept = session_accept_fd;
- l->analysers |= curpeers->peers_fe->fe_req_ana;
- l->default_target = curpeers->peers_fe->default_target;
- l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
- global.maxsock += l->maxconn;
- }
- cfg_peers->local = newpeer;
+
+ l = LIST_ELEM(bind_conf->listeners.n, typeof(l), by_bind);
+ l->maxaccept = 1;
+ l->maxconn = curpeers->peers_fe->maxconn;
+ l->backlog = curpeers->peers_fe->backlog;
+ l->accept = session_accept_fd;
+ l->analysers |= curpeers->peers_fe->fe_req_ana;
+ l->default_target = curpeers->peers_fe->default_target;
+ l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
+ global.maxsock += l->maxconn;
} /* neither "peer" nor "peers" */
else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
curpeers->state = PR_STSTOPPED;
@@ -3637,9 +3818,20 @@
else {
p = curpeers->remote;
while (p) {
- if (p->srv && p->srv->use_ssl &&
- xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
- cfgerr += xprt_get(XPRT_SSL)->prepare_srv(p->srv);
+ if (p->srv) {
+ if (p->srv->use_ssl && xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
+ cfgerr += xprt_get(XPRT_SSL)->prepare_srv(p->srv);
+ }
+ else if (!LIST_ISEMPTY(&curpeers->peers_fe->conf.bind)) {
+ struct list *l;
+ struct bind_conf *bind_conf;
+
+ l = &curpeers->peers_fe->conf.bind;
+ bind_conf = LIST_ELEM(l->n, typeof(bind_conf), by_fe);
+ if (bind_conf->xprt->prepare_bind_conf &&
+ bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
+ cfgerr++;
+ }
p = p->next;
}
if (!peers_init_sync(curpeers)) {
diff --git a/src/server.c b/src/server.c
index cea50c2..678b723 100644
--- a/src/server.c
+++ b/src/server.c
@@ -2078,7 +2078,7 @@
return i - srv->tmpl_info.nb_low;
}
-int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy)
+int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy, int parse_addr)
{
struct server *newsrv = NULL;
const char *err = NULL;
@@ -2106,7 +2106,7 @@
err_code |= ERR_WARN;
/* There is no mandatory first arguments for default server. */
- if (srv) {
+ if (srv && parse_addr) {
if (!*args[2]) {
/* 'server' line number of argument check. */
ha_alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
@@ -2186,6 +2186,9 @@
* - IP:+N => port=+N, relative
* - IP:-N => port=-N, relative
*/
+ if (!parse_addr)
+ goto skip_addr;
+
sk = str2sa_range(args[cur_arg], &port, &port1, &port2, &errmsg, NULL, &fqdn, 0);
if (!sk) {
ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
@@ -2242,10 +2245,11 @@
goto out;
}
+ cur_arg++;
+ skip_addr:
/* Copy default server settings to new server settings. */
srv_settings_cpy(newsrv, &curproxy->defsrv, 0);
HA_SPIN_INIT(&newsrv->lock);
- cur_arg++;
} else {
newsrv = &curproxy->defsrv;
cur_arg = 1;