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/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;