]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: listeners: use dual-linked lists to chain listeners with frontends
authorWilly Tarreau <w@1wt.eu>
Thu, 20 Sep 2012 14:48:07 +0000 (16:48 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 20 Sep 2012 14:48:07 +0000 (16:48 +0200)
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.

13 files changed:
include/proto/listener.h
include/types/listener.h
include/types/proxy.h
include/types/stream_interface.h
src/cfgparse.c
src/dumpstats.c
src/haproxy.c
src/listener.c
src/peers.c
src/proto_tcp.c
src/proto_uxst.c
src/proxy.c
src/ssl_sock.c

index bd571890c0b59469e92449d1ee3eeee842265e54..d7b21d5a050bc13bfb4ddc659a5cdd16c7e61eee 100644 (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;
 }
 
index fda7cea8031b0e387d0855d6b269189c7fe6d5f2..b8d64c4440c2b97037f56f92c9d8db1927e37146 100644 (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 */
 };
 
index dde002a42604e3bd1be68c23283ef20ac1fed3f5..5c078d9e492f642b1d9a6d4d21ee813a28af0aab 100644 (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 */
 };
index 8b069c8df64bcbe8d56659cf07d2b38751f53bc3..728447eef95e4085a5c4af6d73ce39a3d52c79a5 100644 (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 */
index d2f0dcf72dc325989223c9c380697a4b80fdda30..07cc83720991dcd26cba9ecaebb29e308b7af834 100644 (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 */
index ab4c416373798bf7014515b92201d044c51dfa68..5cd903b75b07d1f7fece5efb97394e9e2db42fc3 100644 (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;
 
index 05df3da69bc21f5b1e53789b98b642c5fbde19b5..07c4f3f5aab45738166b82d61cf1928114f803fd 100644 (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);
index 09a025745f43e7af2d427cdc7427522e490146cb..802ddab2d71f114a468b4bf7bbb0c86e68dd603d 100644 (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;
index 09e45f7331a147c20ebee9e7780eb1cfd1855756..62329dc451cfdbfff51da6052f72714f40099bb2 100644 (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;
index 79e4d0d60959201ffe4fa6ebb38fe3521d9cf653..c1972459262563f619b18c0cd09af33d3865450b 100644 (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;
index 5f56ad51cdaddfc33db92b74acade7c97c3bac15..58fd06d36141183c2142c44b9ac8d9b847210944 100644 (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;
 }
index 35e58b03e082a809b57e4c184647a91da5298648..8db70b60126e9357df67ab75e5d39af6b325bad2 100644 (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;
 
index 2d5e6663be909f7cbb643e81fc16afe3fcc950df..056a4e34da40f3ec7b80dd33db262e58282f027c 100644 (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;
 }