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/include/proto/listener.h b/include/proto/listener.h
index bd57189..d7b21d5 100644
--- a/include/proto/listener.h
+++ b/include/proto/listener.h
@@ -131,6 +131,7 @@
 		LIST_ADDQ(lh, &bind_conf->by_fe);
 	if (arg)
 		bind_conf->arg = strdup(arg);
+	LIST_INIT(&bind_conf->listeners);
 	return bind_conf;
 }
 
diff --git a/include/types/listener.h b/include/types/listener.h
index fda7cea..b8d64c4 100644
--- a/include/types/listener.h
+++ b/include/types/listener.h
@@ -106,6 +106,7 @@
 #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 @@
 	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 @@
 	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 @@
 /* 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 */
 };
 
diff --git a/include/types/proxy.h b/include/types/proxy.h
index dde002a..5c078d9 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -200,7 +200,6 @@
 };
 
 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 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 */
 };
diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h
index 8b069c8..728447e 100644
--- a/include/types/stream_interface.h
+++ b/include/types/stream_interface.h
@@ -122,7 +122,7 @@
 			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 */