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.
This commit is contained in:
Willy Tarreau 2012-09-20 16:48:07 +02:00
parent 81a8117b41
commit 4348fad1c1
13 changed files with 153 additions and 197 deletions

View File

@ -131,6 +131,7 @@ static inline struct bind_conf *bind_conf_alloc(struct list *lh, const char *fil
LIST_ADDQ(lh, &bind_conf->by_fe);
if (arg)
bind_conf->arg = strdup(arg);
LIST_INIT(&bind_conf->listeners);
return bind_conf;
}

View File

@ -106,6 +106,7 @@ struct bind_conf {
#endif
int is_ssl; /* SSL is required for these listeners */
struct list by_fe; /* next binding for the same frontend, or NULL */
struct list listeners; /* list of listeners using this bind config */
char *arg; /* argument passed to "bind" for better error reporting */
char *file; /* file where the section appears */
int line; /* line where the section appears */
@ -127,7 +128,6 @@ struct listener {
int nbconn; /* current number of connections on this listener */
int maxconn; /* maximum connections allowed on this listener */
unsigned int backlog; /* if set, listen backlog */
struct listener *next; /* next address for the same proxy, or NULL */
struct list proto_list; /* list in the protocol header */
int (*accept)(struct listener *l, int fd, struct sockaddr_storage *addr); /* upper layer's accept() */
struct task * (*handler)(struct task *t); /* protocol handler. It is a task */
@ -147,6 +147,8 @@ struct listener {
char *interface; /* interface name or NULL */
int maxseg; /* for TCP, advertised MSS */
struct list by_fe; /* chaining in frontend's list of listeners */
struct list by_bind; /* chaining in bind_conf's list of listeners */
struct bind_conf *bind_conf; /* "bind" line settings, include SSL settings among other things */
/* warning: this struct is huge, keep it at the bottom */
@ -159,13 +161,12 @@ struct listener {
/* Descriptor for a "bind" keyword. The ->parse() function returns 0 in case of
* success, or a combination of ERR_* flags if an error is encountered. The
* function pointer can be NULL if not implemented. The function also has an
* access to the current "bind" conf, which is the conf of the last listener,
* reachable via px->listen->bind_conf. The ->skip value tells the parser how
* many words have to be skipped after the keyword.
* access to the current "bind" config line. The ->skip value tells the parser
* how many words have to be skipped after the keyword.
*/
struct bind_kw {
const char *kw;
int (*parse)(char **args, int cur_arg, struct proxy *px, struct listener *last, char **err);
int (*parse)(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err);
int skip; /* nb of args to skip */
};

View File

@ -200,7 +200,6 @@ struct error_snapshot {
};
struct proxy {
struct listener *listen; /* the listen addresses and sockets */
struct in_addr mon_net, mon_mask; /* don't forward connections from this net (network order) FIXME: should support IPv6 */
int state; /* proxy state */
int options; /* PR_O_REDISP, PR_O_TRANSP, ... */
@ -361,6 +360,7 @@ struct proxy {
struct eb_root used_listener_id;/* list of listener IDs in use */
struct eb_root used_server_id; /* list of server IDs in use */
struct list bind; /* list of bind settings */
struct list listeners; /* list of listeners belonging to this frontend */
} conf; /* config information */
void *parent; /* parent of the proxy when applicable */
};

View File

@ -122,7 +122,7 @@ struct stream_interface {
struct {
struct proxy *px;
struct server *sv;
struct listener *l;
void *l;
int px_st; /* STAT_PX_ST* */
unsigned int flags; /* STAT_* */
int iid, type, sid; /* proxy id, type and service id if bounding of stats is enabled */

View File

@ -192,7 +192,7 @@ static struct cfg_kw_list cfg_keywords = {
* 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 @@ static int str2listener(char *str, struct proxy *curproxy, const char *file, int
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 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
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 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
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;
}
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;
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;
}
}
}
} /* neither "peer" nor "peers" */
@ -1446,19 +1455,16 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
/* 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 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
/* 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 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
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 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
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 @@ stats_error_parsing:
* 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 @@ int check_config_validity()
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 @@ out_uri_auth_compat:
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 @@ out_uri_auth_compat:
/* 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 @@ out_uri_auth_compat:
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 @@ out_uri_auth_compat:
((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 */

View File

@ -181,6 +181,8 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
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 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
}
}
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 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
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 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
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 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
* 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 @@ static int stats_dump_proxy(struct stream_interface *si, struct proxy *px, struc
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;

View File

@ -605,7 +605,7 @@ void init(int argc, char **argv)
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 @@ void deinit(void)
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);

View File

@ -504,18 +504,18 @@ acl_fetch_so_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt
}
/* 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 @@ static int bind_parse_backlog(char **args, int cur_arg, struct proxy *px, struct
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 @@ static int bind_parse_id(char **args, int cur_arg, struct proxy *px, struct list
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 @@ static int bind_parse_id(char **args, int cur_arg, struct proxy *px, struct list
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 @@ static int bind_parse_maxconn(char **args, int cur_arg, struct proxy *px, struct
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 @@ static int bind_parse_name(char **args, int cur_arg, struct proxy *px, struct li
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 @@ static int bind_parse_nice(char **args, int cur_arg, struct proxy *px, struct li
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;

View File

@ -1104,7 +1104,7 @@ int peer_accept(struct session *s)
*/
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 @@ void peers_register_table(struct peers *peers, struct stktable *table)
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 @@ void peers_register_table(struct peers *peers, struct stktable *table)
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;

View File

@ -1701,55 +1701,41 @@ static int val_payload_lv(struct arg *arg, char **err_msg)
#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 @@ static int bind_parse_mss(char **args, int cur_arg, struct proxy *px, struct lis
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 @@ static int bind_parse_mss(char **args, int cur_arg, struct proxy *px, struct lis
#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;

View File

@ -349,17 +349,11 @@ static int uxst_unbind_listeners(struct protocol *proto)
}
/* 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 @@ static int bind_parse_mode(char **args, int cur_arg, struct proxy *px, struct li
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 @@ static int bind_parse_gid(char **args, int cur_arg, struct proxy *px, struct lis
}
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 @@ static int bind_parse_group(char **args, int cur_arg, struct proxy *px, struct l
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 @@ static int bind_parse_uid(char **args, int cur_arg, struct proxy *px, struct lis
}
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 @@ static int bind_parse_user(char **args, int cur_arg, struct proxy *px, struct li
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;
}

View File

@ -446,6 +446,7 @@ void init_new_proxy(struct proxy *p)
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 @@ int start_proxies(int verbose)
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 @@ int pause_proxy(struct proxy *p)
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 @@ void stop_proxy(struct proxy *p)
{
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 @@ int resume_proxy(struct proxy *p)
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;

View File

@ -819,7 +819,7 @@ smp_fetch_ssl_sni(struct proxy *px, struct session *l4, void *l7, unsigned int o
}
/* 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 @@ static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct
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 @@ static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct lis
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;
}