MAJOR: listeners: use dual-linked lists to chain listeners with frontends
Navigating through listeners was very inconvenient and error-prone. Not to
mention that listeners were linked in reverse order and reverted afterwards.
In order to definitely get rid of these issues, we now do the following :
- frontends have a dual-linked list of bind_conf
- frontends have a dual-linked list of listeners
- bind_conf have a dual-linked list of listeners
- listeners have a pointer to their bind_conf
This way we can now navigate from anywhere to anywhere and always find the
proper bind_conf for a given listener, as well as find the list of listeners
for a current bind_conf.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index d2f0dcf..07cc837 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -192,7 +192,7 @@
* This can be repeated as many times as necessary, separated by a coma.
* Function returns 1 for success or 0 if error.
*/
-static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
+static int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line)
{
struct listener *l;
char *next, *dupstr;
@@ -266,8 +266,10 @@
for (; port <= end; port++) {
l = (struct listener *)calloc(1, sizeof(struct listener));
- l->next = curproxy->listen;
- curproxy->listen = l;
+ LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
+ LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
+ l->frontend = curproxy;
+ l->bind_conf = bind_conf;
l->fd = -1;
l->addr = ss;
@@ -1212,6 +1214,8 @@
static struct peers *curpeers = NULL;
struct peer *newpeer = NULL;
const char *err;
+ struct bind_conf *bind_conf;
+ struct listener *l;
int err_code = 0;
if (strcmp(args[0], "peers") == 0) { /* new peers section */
@@ -1340,19 +1344,24 @@
curpeers->peers_fe->timeout.connect = 5000;
curpeers->peers_fe->accept = peer_accept;
curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
- if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
+
+ bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
+
+ if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum)) {
err_code |= ERR_FATAL;
goto out;
}
+
+ list_for_each_entry(l, &bind_conf->listeners, by_bind) {
+ l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
+ l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
+ l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
+ l->accept = session_accept;
+ l->handler = process_session;
+ l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
+ l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
+ global.maxsock += l->maxconn;
+ }
- curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
- curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
- curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
- curpeers->peers_fe->listen->accept = session_accept;
- curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
- curpeers->peers_fe->listen->handler = process_session;
- curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
- curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
- global.maxsock += curpeers->peers_fe->listen->maxconn;
}
}
} /* neither "peer" nor "peers" */
@@ -1446,19 +1455,16 @@
/* parse the listener address if any */
if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
- struct listener *new, *last = curproxy->listen;
+ struct listener *l;
- if (!str2listener(args[2], curproxy, file, linenum)) {
+ bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
+
+ if (!str2listener(args[2], curproxy, bind_conf, file, linenum)) {
err_code |= ERR_FATAL;
goto out;
}
- bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
-
- new = curproxy->listen;
- while (new != last) {
- new->bind_conf = bind_conf;
- new = new->next;
+ list_for_each_entry(l, &bind_conf->listeners, by_bind) {
global.maxsock++;
}
}
@@ -1671,7 +1677,7 @@
/* Now let's parse the proxy-specific keywords */
if (!strcmp(args[0], "bind")) { /* new listen addresses */
- struct listener *new_listen, *last_listen;
+ struct listener *l;
int cur_arg;
if (curproxy == &defproxy) {
@@ -1689,29 +1695,24 @@
goto out;
}
- last_listen = curproxy->listen;
bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
/* NOTE: the following line might create several listeners if there
* are comma-separated IPs or port ranges. So all further processing
* will have to be applied to all listeners created after last_listen.
*/
- if (!str2listener(args[1], curproxy, file, linenum)) {
+ if (!str2listener(args[1], curproxy, bind_conf, file, linenum)) {
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
- new_listen = curproxy->listen;
- while (new_listen != last_listen) {
- new_listen->bind_conf = bind_conf;
- new_listen = new_listen->next;
+ list_for_each_entry(l, &bind_conf->listeners, by_bind) {
+ /* Set default global rights and owner for unix bind */
+ if (l->addr.ss_family == AF_UNIX)
+ memcpy(&(l->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
global.maxsock++;
}
- /* Set default global rights and owner for unix bind */
- if (curproxy->listen->addr.ss_family == AF_UNIX) {
- memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
- }
cur_arg = 2;
while (*(args[cur_arg])) {
static int bind_dumped;
@@ -1731,7 +1732,7 @@
goto out;
}
- code = kw->parse(args, cur_arg, curproxy, last_listen, &err);
+ code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
err_code |= code;
if (code) {
@@ -4517,9 +4518,13 @@
* the server either. We'll check if we have
* a known port on the first listener.
*/
- struct listener *l = curproxy->listen;
- while (l && !(newsrv->check_port = get_host_port(&l->addr)))
- l = l->next;
+ struct listener *l;
+
+ list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
+ newsrv->check_port = get_host_port(&l->addr);
+ if (newsrv->check_port)
+ break;
+ }
}
if (!newsrv->check_port) {
Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
@@ -5683,7 +5688,7 @@
break;
}
- if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
+ if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
proxy_type_str(curproxy), curproxy->id);
cfgerr++;
@@ -6495,20 +6500,6 @@
curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
}
- listener = NULL;
- while (curproxy->listen) {
- struct listener *next;
-
- next = curproxy->listen->next;
- curproxy->listen->next = listener;
- listener = curproxy->listen;
-
- if (!next)
- break;
-
- curproxy->listen = next;
- }
-
/* Configure SSL for each bind line.
* Note: if configuration fails at some point, the ->ctx member
* remains NULL so that listeners can later detach.
@@ -6537,8 +6528,7 @@
/* adjust this proxy's listeners */
next_id = 1;
- listener = curproxy->listen;
- while (listener) {
+ list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
if (!listener->luid) {
/* listener ID not set, use automatic numbering with first
* spare entry starting with next_luid.
@@ -6569,7 +6559,6 @@
listener->backlog = curproxy->backlog;
listener->timeout = &curproxy->timeout.client;
listener->accept = session_accept;
- listener->frontend = curproxy;
listener->handler = process_session;
listener->analysers |= curproxy->fe_req_ana;
@@ -6584,9 +6573,6 @@
((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
!(curproxy->no_options2 & PR_O2_SMARTACC)))
listener->options |= LI_O_NOQUICKACK;
-
- /* We want the use_backend and default_backend rules to apply */
- listener = listener->next;
}
/* Release unused SSL configs */
diff --git a/src/dumpstats.c b/src/dumpstats.c
index ab4c416..5cd903b 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -181,6 +181,8 @@
struct proxy *defpx, const char *file, int line,
char **err)
{
+ struct bind_conf *bind_conf;
+
if (!strcmp(args[1], "socket")) {
struct sockaddr_un *su;
int cur_arg;
@@ -209,6 +211,8 @@
}
}
+ bind_conf = bind_conf_alloc(&global.stats_fe->conf.bind, file, line, args[2]);
+
global.stats_sock.state = LI_INIT;
global.stats_sock.options = LI_O_UNLIMITED;
global.stats_sock.accept = session_accept;
@@ -220,9 +224,9 @@
global.stats_sock.perm.ux.level = ACCESS_LVL_OPER; /* default access level */
global.stats_sock.maxconn = global.stats_fe->maxconn;
global.stats_sock.timeout = &global.stats_fe->timeout.client;
-
- global.stats_sock.next = global.stats_fe->listen;
- global.stats_fe->listen = &global.stats_sock;
+ global.stats_sock.bind_conf = bind_conf;
+ LIST_ADDQ(&global.stats_fe->conf.listeners, &global.stats_sock.by_fe);
+ LIST_ADDQ(&bind_conf->listeners, &global.stats_sock.by_bind);
cur_arg = 3;
while (*args[cur_arg]) {
@@ -969,7 +973,7 @@
sv->counters.sps_max = 0;
}
- for (li = px->listen; li; li = li->next)
+ list_for_each_entry(li, &px->conf.listeners, by_bind)
if (li->counters) {
if (clrall)
memset(li->counters, 0, sizeof(*li->counters));
@@ -1149,7 +1153,7 @@
* its listeners. The blocked ones will be dequeued.
*/
px->maxconn = v;
- for (l = px->listen; l != NULL; l = l->next) {
+ list_for_each_entry(l, &px->conf.listeners, by_bind) {
l->maxconn = v;
if (l->state == LI_FULL)
resume_listener(l);
@@ -2508,17 +2512,17 @@
return 0;
}
- si->applet.ctx.stats.l = px->listen; /* may be NULL */
+ si->applet.ctx.stats.l = px->conf.listeners.n;
si->applet.ctx.stats.px_st = STAT_PX_ST_LI;
/* fall through */
case STAT_PX_ST_LI:
/* stats.l has been initialized above */
- for (; si->applet.ctx.stats.l != NULL; si->applet.ctx.stats.l = l->next) {
+ for (; si->applet.ctx.stats.l != &px->conf.listeners; si->applet.ctx.stats.l = l->by_fe.n) {
if (buffer_almost_full(&rep->buf))
return 0;
- l = si->applet.ctx.stats.l;
+ l = LIST_ELEM(si->applet.ctx.stats.l, struct listener *, by_fe);
if (!l->counters)
continue;
diff --git a/src/haproxy.c b/src/haproxy.c
index 05df3da..07c4f3f 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -605,7 +605,7 @@
break;
for (px = proxy; px; px = px->next)
- if (px->state == PR_STNEW && px->listen)
+ if (px->state == PR_STNEW && !LIST_ISEMPTY(&px->conf.listeners))
break;
if (pr || px) {
@@ -1032,21 +1032,17 @@
s = s_next;
}/* end while(s) */
- l = p->listen;
- while (l) {
- l_next = l->next;
+ list_for_each_entry_safe(l, l_next, &p->conf.listeners, by_fe) {
unbind_listener(l);
delete_listener(l);
- l->bind_conf = NULL;
+ LIST_DEL(&l->by_fe);
+ LIST_DEL(&l->by_bind);
free(l->name);
free(l->counters);
free(l);
- l = l_next;
- }/* end while(l) */
+ }
- bind_back = bind_conf = NULL;
- /* Release unused SSL configs.
- */
+ /* Release unused SSL configs. */
list_for_each_entry_safe(bind_conf, bind_back, &p->conf.bind, by_fe) {
#ifdef USE_OPENSSL
ssl_sock_free_all_ctx(bind_conf);
diff --git a/src/listener.c b/src/listener.c
index 09a0257..802ddab 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -504,18 +504,18 @@
}
/* parse the "accept-proxy" bind keyword */
-static int bind_parse_accept_proxy(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_accept_proxy(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
- for (l = px->listen; l != last; l = l->next)
+ list_for_each_entry(l, &conf->listeners, by_bind)
l->options |= LI_O_ACC_PROXY;
return 0;
}
/* parse the "backlog" bind keyword */
-static int bind_parse_backlog(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_backlog(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
int val;
@@ -533,19 +533,19 @@
return ERR_ALERT | ERR_FATAL;
}
- for (l = px->listen; l != last; l = l->next)
+ list_for_each_entry(l, &conf->listeners, by_bind)
l->backlog = val;
return 0;
}
/* parse the "id" bind keyword */
-static int bind_parse_id(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_id(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct eb32_node *node;
- struct listener *l;
+ struct listener *l, *new;
- if (px->listen->next != last) {
+ if (conf->listeners.n != conf->listeners.p) {
if (err)
memprintf(err, "'%s' can only be used with a single socket", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
@@ -557,16 +557,17 @@
return ERR_ALERT | ERR_FATAL;
}
- px->listen->luid = atol(args[cur_arg + 1]);
- px->listen->conf.id.key = px->listen->luid;
+ new = LIST_NEXT(&conf->listeners, struct listener *, by_bind);
+ new->luid = atol(args[cur_arg + 1]);
+ new->conf.id.key = new->luid;
- if (px->listen->luid <= 0) {
+ if (new->luid <= 0) {
if (err)
memprintf(err, "'%s' : custom id has to be > 0", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
- node = eb32_lookup(&px->conf.used_listener_id, px->listen->luid);
+ node = eb32_lookup(&px->conf.used_listener_id, new->luid);
if (node) {
l = container_of(node, struct listener, conf.id);
if (err)
@@ -576,12 +577,12 @@
return ERR_ALERT | ERR_FATAL;
}
- eb32_insert(&px->conf.used_listener_id, &px->listen->conf.id);
+ eb32_insert(&px->conf.used_listener_id, &new->conf.id);
return 0;
}
/* parse the "maxconn" bind keyword */
-static int bind_parse_maxconn(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_maxconn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
int val;
@@ -599,14 +600,14 @@
return ERR_ALERT | ERR_FATAL;
}
- for (l = px->listen; l != last; l = l->next)
+ list_for_each_entry(l, &conf->listeners, by_bind)
l->maxconn = val;
return 0;
}
/* parse the "name" bind keyword */
-static int bind_parse_name(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_name(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
@@ -616,14 +617,14 @@
return ERR_ALERT | ERR_FATAL;
}
- for (l = px->listen; l != last; l = l->next)
+ list_for_each_entry(l, &conf->listeners, by_bind)
l->name = strdup(args[cur_arg + 1]);
return 0;
}
/* parse the "nice" bind keyword */
-static int bind_parse_nice(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_nice(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
int val;
@@ -641,7 +642,7 @@
return ERR_ALERT | ERR_FATAL;
}
- for (l = px->listen; l != last; l = l->next)
+ list_for_each_entry(l, &conf->listeners, by_bind)
l->nice = val;
return 0;
diff --git a/src/peers.c b/src/peers.c
index 09e45f7..62329dc 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -1104,7 +1104,7 @@
*/
static struct session *peer_session_create(struct peer *peer, struct peer_session *ps)
{
- struct listener *l = ((struct proxy *)peer->peers->peers_fe)->listen;
+ struct listener *l = LIST_NEXT(&peer->peers->peers_fe->conf.listeners, struct listener *, by_fe);
struct proxy *p = (struct proxy *)l->frontend; /* attached frontend */
struct session *s;
struct http_txn *txn;
@@ -1459,6 +1459,7 @@
struct shared_table *st;
struct peer * curpeer;
struct peer_session *ps;
+ struct listener *listener;
st = (struct shared_table *)calloc(1,sizeof(struct shared_table));
st->table = table;
@@ -1478,7 +1479,8 @@
peers->peers_fe->maxconn += 3;
}
- peers->peers_fe->listen->maxconn = peers->peers_fe->maxconn;
+ list_for_each_entry(listener, &peers->peers_fe->conf.listeners, by_fe)
+ listener->maxconn = peers->peers_fe->maxconn;
st->sync_task = task_new();
st->sync_task->process = process_peer_sync;
st->sync_task->expire = TICK_ETERNITY;
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 79e4d0d..c197245 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -1701,55 +1701,41 @@
#ifdef CONFIG_HAP_LINUX_TPROXY
/* parse the "transparent" bind keyword */
-static int bind_parse_transparent(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_transparent(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
- if (px->listen->addr.ss_family != AF_INET && px->listen->addr.ss_family != AF_INET6) {
- if (err)
- memprintf(err, "'%s' option is only supported on IPv4 and IPv6 sockets", args[cur_arg]);
- return ERR_ALERT | ERR_FATAL;
+ list_for_each_entry(l, &conf->listeners, by_bind) {
+ if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6)
+ l->options |= LI_O_FOREIGN;
}
- for (l = px->listen; l != last; l = l->next)
- l->options |= LI_O_FOREIGN;
-
return 0;
}
#endif
#ifdef TCP_DEFER_ACCEPT
/* parse the "defer-accept" bind keyword */
-static int bind_parse_defer_accept(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_defer_accept(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
- if (px->listen->addr.ss_family != AF_INET && px->listen->addr.ss_family != AF_INET6) {
- if (err)
- memprintf(err, "'%s' option is only supported on IPv4 and IPv6 sockets", args[cur_arg]);
- return ERR_ALERT | ERR_FATAL;
+ list_for_each_entry(l, &conf->listeners, by_bind) {
+ if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6)
+ l->options |= LI_O_DEF_ACCEPT;
}
- for (l = px->listen; l != last; l = l->next)
- l->options |= LI_O_DEF_ACCEPT;
-
return 0;
}
#endif
#ifdef TCP_MAXSEG
/* parse the "mss" bind keyword */
-static int bind_parse_mss(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_mss(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
int mss;
- if (px->listen->addr.ss_family != AF_INET && px->listen->addr.ss_family != AF_INET6) {
- if (err)
- memprintf(err, "'%s' option is only supported on IPv4 and IPv6 sockets", args[cur_arg]);
- return ERR_ALERT | ERR_FATAL;
- }
-
if (!*args[cur_arg + 1]) {
if (err)
memprintf(err, "'%s' : missing MSS value", args[cur_arg]);
@@ -1763,8 +1749,10 @@
return ERR_ALERT | ERR_FATAL;
}
- for (l = px->listen; l != last; l = l->next)
- l->maxseg = mss;
+ list_for_each_entry(l, &conf->listeners, by_bind) {
+ if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6)
+ l->maxseg = mss;
+ }
return 0;
}
@@ -1772,24 +1760,20 @@
#ifdef SO_BINDTODEVICE
/* parse the "mss" bind keyword */
-static int bind_parse_interface(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_interface(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
- if (px->listen->addr.ss_family != AF_INET && px->listen->addr.ss_family != AF_INET6) {
- if (err)
- memprintf(err, "'%s' option is only supported on IPv4 and IPv6 sockets", args[cur_arg]);
- return ERR_ALERT | ERR_FATAL;
- }
-
if (!*args[cur_arg + 1]) {
if (err)
memprintf(err, "'%s' : missing interface name", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
- for (l = px->listen; l != last; l = l->next)
- l->interface = strdup(args[cur_arg + 1]);
+ list_for_each_entry(l, &conf->listeners, by_bind) {
+ if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6)
+ l->interface = strdup(args[cur_arg + 1]);
+ }
global.last_checks |= LSTCHK_NETADM;
return 0;
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index 5f56ad5..58fd06d 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -349,17 +349,11 @@
}
/* parse the "mode" bind keyword */
-static int bind_parse_mode(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_mode(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
int val;
- if (px->listen->addr.ss_family != AF_UNIX) {
- if (err)
- memprintf(err, "'%s' option is only supported on unix sockets", args[cur_arg]);
- return ERR_ALERT | ERR_FATAL;
- }
-
if (!*args[cur_arg + 1]) {
if (err)
memprintf(err, "'%s' : missing mode (octal integer expected)", args[cur_arg]);
@@ -368,24 +362,20 @@
val = strtol(args[cur_arg + 1], NULL, 8);
- for (l = px->listen; l != last; l = l->next)
- l->perm.ux.mode = val;
+ list_for_each_entry(l, &conf->listeners, by_bind) {
+ if (l->addr.ss_family == AF_UNIX)
+ l->perm.ux.mode = val;
+ }
return 0;
}
/* parse the "gid" bind keyword */
-static int bind_parse_gid(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_gid(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
int val;
- if (px->listen->addr.ss_family != AF_UNIX) {
- if (err)
- memprintf(err, "'%s' option is only supported on unix sockets", args[cur_arg]);
- return ERR_ALERT | ERR_FATAL;
- }
-
if (!*args[cur_arg + 1]) {
if (err)
memprintf(err, "'%s' : missing value", args[cur_arg]);
@@ -393,24 +383,20 @@
}
val = atol(args[cur_arg + 1]);
- for (l = px->listen; l != last; l = l->next)
- l->perm.ux.gid = val;
+ list_for_each_entry(l, &conf->listeners, by_bind) {
+ if (l->addr.ss_family == AF_UNIX)
+ l->perm.ux.gid = val;
+ }
return 0;
}
/* parse the "group" bind keyword */
-static int bind_parse_group(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_group(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
struct group *group;
- if (px->listen->addr.ss_family != AF_UNIX) {
- if (err)
- memprintf(err, "'%s' option is only supported on unix sockets", args[cur_arg]);
- return ERR_ALERT | ERR_FATAL;
- }
-
if (!*args[cur_arg + 1]) {
if (err)
memprintf(err, "'%s' : missing group name", args[cur_arg]);
@@ -424,24 +410,20 @@
return ERR_ALERT | ERR_FATAL;
}
- for (l = px->listen; l != last; l = l->next)
- l->perm.ux.gid = group->gr_gid;
+ list_for_each_entry(l, &conf->listeners, by_bind) {
+ if (l->addr.ss_family == AF_UNIX)
+ l->perm.ux.gid = group->gr_gid;
+ }
return 0;
}
/* parse the "uid" bind keyword */
-static int bind_parse_uid(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_uid(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
int val;
- if (px->listen->addr.ss_family != AF_UNIX) {
- if (err)
- memprintf(err, "'%s' option is only supported on unix sockets", args[cur_arg]);
- return ERR_ALERT | ERR_FATAL;
- }
-
if (!*args[cur_arg + 1]) {
if (err)
memprintf(err, "'%s' : missing value", args[cur_arg]);
@@ -449,24 +431,20 @@
}
val = atol(args[cur_arg + 1]);
- for (l = px->listen; l != last; l = l->next)
- l->perm.ux.uid = val;
+ list_for_each_entry(l, &conf->listeners, by_bind) {
+ if (l->addr.ss_family == AF_UNIX)
+ l->perm.ux.uid = val;
+ }
return 0;
}
/* parse the "user" bind keyword */
-static int bind_parse_user(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_user(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct listener *l;
struct passwd *user;
- if (px->listen->addr.ss_family != AF_UNIX) {
- if (err)
- memprintf(err, "'%s' option is only supported on unix sockets", args[cur_arg]);
- return ERR_ALERT | ERR_FATAL;
- }
-
if (!*args[cur_arg + 1]) {
if (err)
memprintf(err, "'%s' : missing user name", args[cur_arg]);
@@ -480,8 +458,10 @@
return ERR_ALERT | ERR_FATAL;
}
- for (l = px->listen; l != last; l = l->next)
- l->perm.ux.uid = user->pw_uid;
+ list_for_each_entry(l, &conf->listeners, by_bind) {
+ if (l->addr.ss_family == AF_UNIX)
+ l->perm.ux.uid = user->pw_uid;
+ }
return 0;
}
diff --git a/src/proxy.c b/src/proxy.c
index 35e58b0..8db70b6 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -446,6 +446,7 @@
LIST_INIT(&p->logformat);
LIST_INIT(&p->format_unique_id);
LIST_INIT(&p->conf.bind);
+ LIST_INIT(&p->conf.listeners);
/* Timeouts are defined as -1 */
proxy_reset_timeouts(p);
@@ -475,7 +476,7 @@
continue; /* already initialized */
pxerr = 0;
- for (listener = curproxy->listen; listener != NULL; listener = listener->next) {
+ list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
if (listener->state != LI_ASSIGNED)
continue; /* already started */
@@ -639,7 +640,7 @@
Warning("Pausing %s %s.\n", proxy_cap_str(p->cap), p->id);
send_log(p, LOG_WARNING, "Pausing %s %s.\n", proxy_cap_str(p->cap), p->id);
- for (l = p->listen; l != NULL; l = l->next) {
+ list_for_each_entry(l, &p->conf.listeners, by_fe) {
if (!pause_listener(l))
p->state = PR_STERROR;
}
@@ -666,7 +667,7 @@
{
struct listener *l;
- for (l = p->listen; l != NULL; l = l->next) {
+ list_for_each_entry(l, &p->conf.listeners, by_fe) {
unbind_listener(l);
if (l->state >= LI_ASSIGNED) {
delete_listener(l);
@@ -694,7 +695,7 @@
send_log(p, LOG_WARNING, "Enabling %s %s.\n", proxy_cap_str(p->cap), p->id);
fail = 0;
- for (l = p->listen; l != NULL; l = l->next) {
+ list_for_each_entry(l, &p->conf.listeners, by_fe) {
if (!resume_listener(l)) {
int port;
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 2d5e666..056a4e3 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -819,7 +819,7 @@
}
/* parse the "ciphers" bind keyword */
-static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
if (!*args[cur_arg + 1]) {
if (err)
@@ -827,12 +827,12 @@
return ERR_ALERT | ERR_FATAL;
}
- px->listen->bind_conf->ciphers = strdup(args[cur_arg + 1]);
+ conf->ciphers = strdup(args[cur_arg + 1]);
return 0;
}
/* parse the "crt" bind keyword */
-static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
if (!*args[cur_arg + 1]) {
if (err)
@@ -840,37 +840,37 @@
return ERR_ALERT | ERR_FATAL;
}
- if (ssl_sock_load_cert(args[cur_arg + 1], px->listen->bind_conf, px, err) > 0)
+ if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
return ERR_ALERT | ERR_FATAL;
return 0;
}
/* parse the "nosslv3" bind keyword */
-static int bind_parse_nosslv3(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_nosslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
- px->listen->bind_conf->nosslv3 = 1;
+ conf->nosslv3 = 1;
return 0;
}
/* parse the "notlsv1" bind keyword */
-static int bind_parse_notlsv1(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_notlsv1(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
- px->listen->bind_conf->notlsv1 = 1;
+ conf->notlsv1 = 1;
return 0;
}
/* parse the "prefer-server-ciphers" bind keyword */
-static int bind_parse_psc(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_psc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
- px->listen->bind_conf->prefer_server_ciphers = 1;
+ conf->prefer_server_ciphers = 1;
return 0;
}
/* parse the "ssl" bind keyword */
-static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err)
+static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
- px->listen->bind_conf->is_ssl = 1;
+ conf->is_ssl = 1;
return 0;
}