[MEDIUM] don't limit peers nor stats socket to maxconn nor maxconnrate

The peers and the stats socket are control sockets, they must not be
limited by traffic rules.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index f098a31..45d9677 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -1278,6 +1278,8 @@
 				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" */
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 6d97f5da..964ba83 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -206,7 +206,7 @@
 		}
 
 		global.stats_sock.state = LI_INIT;
-		global.stats_sock.options = LI_O_NONE;
+		global.stats_sock.options = LI_O_UNLIMITED;
 		global.stats_sock.accept = session_accept;
 		global.stats_fe->accept = stats_accept;
 		global.stats_sock.handler = process_session;
diff --git a/src/haproxy.c b/src/haproxy.c
index 7aa9fd4..f783c3d 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -68,6 +68,7 @@
 #include <types/global.h>
 #include <types/proto_tcp.h>
 #include <types/acl.h>
+#include <types/peers.h>
 
 #include <proto/auth.h>
 #include <proto/acl.h>
@@ -603,6 +604,18 @@
 	global.maxsock += global.maxconn * 2; /* each connection needs two sockets */
 	global.maxsock += global.maxpipes * 2; /* each pipe needs two FDs */
 
+	if (global.stats_fe)
+		global.maxsock += global.stats_fe->maxconn;
+
+	if (peers) {
+		/* peers also need to bypass global maxconn */
+		struct peers *p = peers;
+
+		for (p = peers; p; p = p->next)
+			if (p->peers_fe)
+				global.maxsock += p->peers_fe->maxconn;
+	}
+
 	if (global.tune.maxpollevents <= 0)
 		global.tune.maxpollevents = MAX_POLL_EVENTS;
 
diff --git a/src/peers.c b/src/peers.c
index 26a3154..bbe99d4 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -1271,7 +1271,8 @@
 	l->nbconn++; /* warning! right now, it's up to the handler to decrease this */
 	p->feconn++;/* beconn will be increased later */
 	jobs++;
-	actconn++;
+	if (!(s->listener->options & LI_O_UNLIMITED))
+		actconn++;
 	totalconn++;
 
 	return s;
diff --git a/src/session.c b/src/session.c
index a9dfef8..5032d88 100644
--- a/src/session.c
+++ b/src/session.c
@@ -2086,7 +2086,8 @@
 	s->fe->feconn--;
 	if (s->flags & SN_BE_ASSIGNED)
 		s->be->beconn--;
-	actconn--;
+	if (!(s->listener->options & LI_O_UNLIMITED))
+		actconn--;
 	jobs--;
 	s->listener->nbconn--;
 	if (s->listener->state == LI_FULL)
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 365f52b..d673aba 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -1156,7 +1156,7 @@
 		return 0;
 	}
 
-	if (global.cps_lim) {
+	if (global.cps_lim && !(l->options & LI_O_UNLIMITED)) {
 		int max = freq_ctr_remain(&global.conn_per_sec, global.cps_lim, 0);
 
 		if (unlikely(!max)) {
@@ -1193,7 +1193,7 @@
 		struct sockaddr_storage addr;
 		socklen_t laddr = sizeof(addr);
 
-		if (unlikely(actconn >= global.maxconn)) {
+		if (unlikely(actconn >= global.maxconn) && !(l->options & LI_O_UNLIMITED)) {
 			limit_listener(l, &global_listener_queue);
 			task_schedule(global_listener_queue_task, tick_add(now_ms, 1000)); /* try again in 1 second */
 			return 0;
@@ -1252,12 +1252,14 @@
 		}
 
 		/* increase the per-process number of cumulated connections */
-		update_freq_ctr(&global.conn_per_sec, 1);
-		if (global.conn_per_sec.curr_ctr > global.cps_max)
-			global.cps_max = global.conn_per_sec.curr_ctr;
+		if (!(l->options & LI_O_UNLIMITED)) {
+			update_freq_ctr(&global.conn_per_sec, 1);
+			if (global.conn_per_sec.curr_ctr > global.cps_max)
+				global.cps_max = global.conn_per_sec.curr_ctr;
+			actconn++;
+		}
 
 		jobs++;
-		actconn++;
 		totalconn++;
 		l->nbconn++;
 
@@ -1273,8 +1275,9 @@
 			 * error due to a resource shortage, and we must stop the
 			 * listener (ret < 0).
 			 */
+			if (!(l->options & LI_O_UNLIMITED))
+				actconn--;
 			jobs--;
-			actconn--;
 			l->nbconn--;
 			if (ret == 0) /* successful termination */
 				continue;