[MEDIUM] default-server support

This patch implements default-server support allowing to change
default server options. It can be used in [defaults] or [backend]/[listen]
sections. Currently the following options are supported:

 - error-limit
 - fall
 - inter
 - fastinter
 - downinter
 - maxconn
 - maxqueue
 - minconn
 - on-error
 - port
 - rise
 - slowstart
 - weight
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 8652505..eaec73b 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -47,7 +47,7 @@
 4.1.      Proxy keywords matrix
 4.2.      Alphabetically sorted keywords reference
 
-5.    Server options
+5.    Server and default-server options
 
 6.    HTTP header manipulation
 
@@ -724,6 +724,7 @@
 clitimeout                  X          X         X         -  (deprecated)
 contimeout                  X          -         X         X  (deprecated)
 cookie                      X          -         X         X
+default-server              X          -         X         -
 default_backend             -          X         X         -
 description                 -          X         X         X
 disabled                    X          X         X         X
@@ -1606,6 +1607,19 @@
 
   See also : "appsession", "balance source", "capture cookie", "server".
 
+default-server [param*]
+  Change default options for a server in a backend
+  May be used in sections :   defaults | frontend | listen | backend
+                                 yes   |    no    |   yes  |   yes
+  Arguments:
+    <param*>  is a list of parameters for this server. The "default-server" keywords
+              accepts an important number of options and has a complete section
+              dedicated to it. Please refer to section 5 for more details.
+
+  Examples:
+        default-server inter 1000 weight 13
+
+  See also: "server" and section 5 about server options
 
 default_backend <backend>
   Specify the backend to use when no "use_backend" rule has been matched.
@@ -3795,7 +3809,7 @@
         server first  10.1.1.1:1080 cookie first  check inter 1000
         server second 10.1.1.2:1080 cookie second check inter 1000
 
-  See also : section 5 about server options
+  See also: "default-server" and section 5 about server options
 
 
 source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | client | clientip } ]
@@ -4696,19 +4710,22 @@
   See also: "default_backend", "tcp-request", and section 7 about ACLs.
   
 
-5. Server options
+5. Server and default-server options
 -----------------
 
-The "server" keyword supports a certain number of settings which are all passed
-as arguments on the server line. The order in which those arguments appear does
-not count, and they are all optional. Some of those settings are single words
-(booleans) while others expect one or several values after them. In this case,
-the values must immediately follow the setting name. All those settings must be
-specified after the server's address if they are used :
+The "server" and "default-server" keywords support a certain number of settings
+which are all passed as arguments on the server line. The order in which those
+arguments appear does not count, and they are all optional. Some of those
+settings are single words (booleans) while others expect one or several values
+after them. In this case, the values must immediately follow the setting name.
+Except default-server, all those settings must be specified after the server's
+address if they are used:
 
   server <name> <address>[:port] [settings ...]
+  default-server [settings ...]
 
-The currently supported settings are the following ones.
+The currently supported settings are the following ones, the ones marked with
+"[D]" are also upported for default-server.
 
 addr <ipv4>
   Using the "addr" parameter, it becomes possible to use a different IP address
@@ -4747,14 +4764,14 @@
   the same cookie value, and it is in fact somewhat common between normal and
   backup servers. See also the "cookie" keyword in backend section.
 
-error-limit <count>
+[D] error-limit <count>
   If health observing is enabled, the "error-limit" parameter specifies the number
   of consecutive errors that triggers event selected by the "on-error" option.
   By default it is set to 10 consecutive errors.
 
  See also the "check", "error-limit" and "on-error".
 
-fall <count>
+[D] fall <count>
   The "fall" parameter states that a server will be considered as dead after
   <count> consecutive unsuccessful health checks. This value defaults to 3 if
   unspecified. See also the "check", "inter" and "rise" parameters.
@@ -4764,9 +4781,9 @@
   the proxy. An unused ID will automatically be assigned if unset. The first
   assigned value will be 1. This ID is currently only returned in statistics.
 
-inter <delay>
-fastinter <delay>
-downinter <delay>
+[D] inter <delay>
+[D] fastinter <delay>
+[D] downinter <delay>
   The "inter" parameter sets the interval between two consecutive health checks
   to <delay> milliseconds. If left unspecified, the delay defaults to 2000 ms.
   It is also possible to use "fastinter" and "downinter" to optimize delays
@@ -4793,7 +4810,7 @@
   keyword. This makes sense for instance when a lot of backends use the same
   servers.
 
-maxconn <maxconn>
+[D] maxconn <maxconn>
   The "maxconn" parameter specifies the maximal number of concurrent
   connections that will be sent to this server. If the number of incoming
   concurrent requests goes higher than this value, they will be queued, waiting
@@ -4803,7 +4820,7 @@
   which means unlimited. See also the "minconn" and "maxqueue" parameters, and
   the backend's "fullconn" keyword.
 
-maxqueue <maxqueue>
+[D] maxqueue <maxqueue>
   The "maxqueue" parameter specifies the maximal number of connections which
   will wait in the queue for this server. If this limit is reached, next
   requests will be redispatched to other servers instead of indefinitely
@@ -4812,7 +4829,7 @@
   default value is "0" which means the queue is unlimited. See also the
   "maxconn" and "minconn" parameters.
 
-minconn <minconn>
+[D] minconn <minconn>
   When the "minconn" parameter is set, the maxconn limit becomes a dynamic
   limit following the backend's load. The server will always accept at least
   <minconn> connections, never more than <maxconn>, and the limit will be on
@@ -4833,7 +4850,7 @@
 
   See also the "check", "on-error" and "error-limit".
 
-on-error <mode>
+[D] on-error <mode>
   Select what should happen when enough consecutive errors are detected.
   Currently, four modes are available:
   - fastinter: force fastinter
@@ -4844,7 +4861,7 @@
 
   See also the "check", "observe" and "error-limit".
 
-port <port>
+[D] port <port>
   Using the "port" parameter, it becomes possible to use a different port to
   send health-checks. On some servers, it may be desirable to dedicate a port
   to a specific component able to perform complex tests which are more suitable
@@ -4870,12 +4887,12 @@
 
   Example :  server srv1 192.168.1.1:80 redir http://image1.mydomain.com check
 
-rise <count>
+[D] rise <count>
   The "rise" parameter states that a server will be considered as operational
   after <count> consecutive successful health checks. This value defaults to 2
   if unspecified. See also the "check", "inter" and "fall" parameters.
 
-slowstart <start_time_in_ms>
+[D] slowstart <start_time_in_ms>
   The "slowstart" parameter for a server accepts a value in milliseconds which
   indicates after how long a server which has just come back up will run at
   full speed. Just as with every other time-based parameter, it can be entered
@@ -4917,7 +4934,7 @@
   one. If <proxy> is omitted the current one is used. If disable-on-404 is
   used, it has to be enabled on both proxies.
 
-weight <weight>
+[D] weight <weight>
   The "weight" parameter is used to adjust the server's weight relative to
   other servers. All servers will receive a load proportional to their weight
   relative to the sum of all weights, so the higher the weight, the higher the
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 6130cf5..78449e7 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -166,7 +166,7 @@
 		struct list inspect_rules;      /* inspection rules */
 	} tcp_req;
 	int acl_requires;                       /* Elements required to satisfy all ACLs (ACL_USE_*) */
-	struct server *srv;			/* known servers */
+	struct server *srv, defsrv;		/* known servers; default server configuration */
 	int srv_act, srv_bck;			/* # of servers eligible for LB (UP|!checked) AND (enabled+weight!=0) */
 	struct lbprm lbprm;			/* load-balancing parameters */
 	char *cookie_domain;			/* domain used to insert the cookie */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 20fb657..8986ecd 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -811,6 +811,20 @@
 	defproxy.maxconn = cfg_maxpconn;
 	defproxy.conn_retries = CONN_RETRIES;
 	defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
+
+	defproxy.defsrv.inter = DEF_CHKINTR;
+	defproxy.defsrv.fastinter = 0;
+	defproxy.defsrv.downinter = 0;
+	defproxy.defsrv.rise = DEF_RISETIME;
+	defproxy.defsrv.fall = DEF_FALLTIME;
+	defproxy.defsrv.check_port = 0;
+	defproxy.defsrv.maxqueue = 0;
+	defproxy.defsrv.minconn = 0;
+	defproxy.defsrv.maxconn = 0;
+	defproxy.defsrv.slowstart = 0;
+	defproxy.defsrv.onerror = DEF_HANA_ONERR;
+	defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
+	defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
 }
 
 /*
@@ -913,6 +927,8 @@
 		}
 
 		/* set default values */
+		memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
+
 		curproxy->state = defproxy.state;
 		curproxy->options = defproxy.options;
 		curproxy->options2 = defproxy.options2;
@@ -2538,14 +2554,13 @@
 			goto out;
 		}
 	}
-	else if (!strcmp(args[0], "server")) {  /* server address */
+	else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {  /* server address */
 		int cur_arg;
-		char *rport;
-		char *raddr;
-		short realport;
-		int do_check;
+		char *rport, *raddr;
+		short realport = 0;
+		int do_check = 0, defsrv = (*args[0] == 'd');
 
-		if (curproxy == &defproxy) {
+		if (!defsrv && curproxy == &defproxy) {
 			Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
 			err_code |= ERR_ALERT | ERR_FATAL;
 			goto out;
@@ -2574,58 +2589,68 @@
 			goto out;
 		}
 
-		/* the servers are linked backwards first */
-		newsrv->next = curproxy->srv;
-		curproxy->srv = newsrv;
-		newsrv->proxy = curproxy;
-		newsrv->conf.file = file;
-		newsrv->conf.line = linenum;
+		if (!defsrv) {
+			/* the servers are linked backwards first */
+			newsrv->next = curproxy->srv;
+			curproxy->srv = newsrv;
+			newsrv->proxy = curproxy;
+			newsrv->conf.file = file;
+			newsrv->conf.line = linenum;
 
-		LIST_INIT(&newsrv->pendconns);
-		do_check = 0;
-		newsrv->state = SRV_RUNNING; /* early server setup */
-		newsrv->last_change = now.tv_sec;
-		newsrv->id = strdup(args[1]);
+			LIST_INIT(&newsrv->pendconns);
+			do_check = 0;
+			newsrv->state = SRV_RUNNING; /* early server setup */
+			newsrv->last_change = now.tv_sec;
+			newsrv->id = strdup(args[1]);
 
-		/* several ways to check the port component :
-		 *  - IP    => port=+0, relative
-		 *  - IP:   => port=+0, relative
-		 *  - IP:N  => port=N, absolute
-		 *  - IP:+N => port=+N, relative
-		 *  - IP:-N => port=-N, relative
-		 */
-		raddr = strdup(args[2]);
-		rport = strchr(raddr, ':');
-		if (rport) {
-			*rport++ = 0;
-			realport = atol(rport);
-			if (!isdigit((unsigned char)*rport))
+			/* several ways to check the port component :
+			 *  - IP    => port=+0, relative
+			 *  - IP:   => port=+0, relative
+			 *  - IP:N  => port=N, absolute
+			 *  - IP:+N => port=+N, relative
+			 *  - IP:-N => port=-N, relative
+			 */
+			raddr = strdup(args[2]);
+			rport = strchr(raddr, ':');
+			if (rport) {
+				*rport++ = 0;
+				realport = atol(rport);
+				if (!isdigit((unsigned char)*rport))
+					newsrv->state |= SRV_MAPPORTS;
+			} else
 				newsrv->state |= SRV_MAPPORTS;
-		} else {
-			realport = 0;
-			newsrv->state |= SRV_MAPPORTS;
-		}	    
+
+			newsrv->addr = *str2sa(raddr);
+			newsrv->addr.sin_port = htons(realport);
+			free(raddr);
+
+			newsrv->check_port	= curproxy->defsrv.check_port;
+			newsrv->inter		= curproxy->defsrv.inter;
+			newsrv->fastinter	= curproxy->defsrv.fastinter;
+			newsrv->downinter	= curproxy->defsrv.downinter;
+			newsrv->rise		= curproxy->defsrv.rise;
+			newsrv->fall		= curproxy->defsrv.fall;
+			newsrv->maxqueue	= curproxy->defsrv.maxqueue;
+			newsrv->minconn		= curproxy->defsrv.minconn;
+			newsrv->maxconn		= curproxy->defsrv.maxconn;
+			newsrv->slowstart	= curproxy->defsrv.slowstart;
+			newsrv->onerror		= curproxy->defsrv.onerror;
+			newsrv->consecutive_errors_limit
+						= curproxy->defsrv.consecutive_errors_limit;
+			newsrv->uweight = newsrv->iweight
+						= curproxy->defsrv.iweight;
 
-		newsrv->addr = *str2sa(raddr);
-		newsrv->addr.sin_port = htons(realport);
-		free(raddr);
+			newsrv->curfd = -1;		/* no health-check in progress */
+			newsrv->health = newsrv->rise;	/* up, but will fall down at first failure */
 
-		newsrv->curfd = -1; /* no health-check in progress */
-		newsrv->inter = DEF_CHKINTR;
-		newsrv->fastinter = 0;		/* 0 => use newsrv->inter instead */
-		newsrv->downinter = 0;		/* 0 => use newsrv->inter instead */
-		newsrv->rise = DEF_RISETIME;
-		newsrv->fall = DEF_FALLTIME;
-		newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
-		newsrv->uweight = newsrv->iweight = 1;
-		newsrv->maxqueue = 0;
-		newsrv->slowstart = 0;
-		newsrv->onerror = DEF_HANA_ONERR;
-		newsrv->consecutive_errors_limit = DEF_HANA_ERRLIMIT;
+			cur_arg = 3;
+		} else {
+			newsrv = &curproxy->defsrv;
+			cur_arg = 1;
+		}
 
-		cur_arg = 3;
 		while (*args[cur_arg]) {
-			if (!strcmp(args[cur_arg], "id")) {
+			if (!defsrv && !strcmp(args[cur_arg], "id")) {
 				struct eb32_node *node;
 
 				if (!*args[cur_arg + 1]) {
@@ -2656,12 +2681,12 @@
 				eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
 				cur_arg += 2;
 			}
-			else if (!strcmp(args[cur_arg], "cookie")) {
+			else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
 				newsrv->cookie = strdup(args[cur_arg + 1]);
 				newsrv->cklen = strlen(args[cur_arg + 1]);
 				cur_arg += 2;
 			}
-			else if (!strcmp(args[cur_arg], "redir")) {
+			else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
 				newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
 				newsrv->rdr_len = strlen(args[cur_arg + 1]);
 				cur_arg += 2;
@@ -2755,7 +2780,7 @@
 				newsrv->downinter = val;
 				cur_arg += 2;
 			}
-			else if (!strcmp(args[cur_arg], "addr")) {
+			else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
 				newsrv->check_addr = *str2sa(args[cur_arg + 1]);
 				cur_arg += 2;
 			}
@@ -2763,7 +2788,7 @@
 				newsrv->check_port = atol(args[cur_arg + 1]);
 				cur_arg += 2;
 			}
-			else if (!strcmp(args[cur_arg], "backup")) {
+			else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
 				newsrv->state |= SRV_BACKUP;
 				cur_arg ++;
 			}
@@ -2809,7 +2834,7 @@
 				newsrv->slowstart = (val + 999) / 1000;
 				cur_arg += 2;
 			}
-			else if (!strcmp(args[cur_arg], "track")) {
+			else if (!defsrv && !strcmp(args[cur_arg], "track")) {
 
 				if (!*args[cur_arg + 1]) {
 					Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
@@ -2822,12 +2847,12 @@
 
 				cur_arg += 2;
 			}
-			else if (!strcmp(args[cur_arg], "check")) {
+			else if (!defsrv && !strcmp(args[cur_arg], "check")) {
 				global.maxsock++;
 				do_check = 1;
 				cur_arg += 1;
 			}
-			else if (!strcmp(args[cur_arg], "observe")) {
+			else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
 				if (!strcmp(args[cur_arg + 1], "none"))
 					newsrv->observe = HANA_OBS_NONE;
 				else if (!strcmp(args[cur_arg + 1], "layer4"))
@@ -2886,7 +2911,7 @@
 					goto out;
 				}
 			}
-			else if (!strcmp(args[cur_arg], "source")) {  /* address to which we bind when connecting */
+			else if (!defsrv && !strcmp(args[cur_arg], "source")) {  /* address to which we bind when connecting */
 				int port_low, port_high;
 				if (!*args[cur_arg + 1]) {
 #if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
@@ -2984,15 +3009,20 @@
 					break;
 				} /* while */
 			}
-			else if (!strcmp(args[cur_arg], "usesrc")) {  /* address to use outside: needs "source" first */
+			else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) {  /* address to use outside: needs "source" first */
 				Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
 				      file, linenum, "usesrc", "source");
 				err_code |= ERR_ALERT | ERR_FATAL;
 				goto out;
 			}
 			else {
-				Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
-				      file, linenum, newsrv->id);
+				if (!defsrv)
+					Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
+					      file, linenum, newsrv->id);
+				else
+					Alert("parsing [%s:%d]: default-server only supports options 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
+					      file, linenum);
+
 				err_code |= ERR_ALERT | ERR_FATAL;
 				goto out;
 			}
@@ -3037,12 +3067,14 @@
 			newsrv->state |= SRV_CHECKED;
 		}
 
-		if (newsrv->state & SRV_BACKUP)
-			curproxy->srv_bck++;
-		else
-			curproxy->srv_act++;
+		if (!defsrv) {
+			if (newsrv->state & SRV_BACKUP)
+				curproxy->srv_bck++;
+			else
+				curproxy->srv_act++;
 
-		newsrv->prev_state = newsrv->state;
+			newsrv->prev_state = newsrv->state;
+		}
 	}
 	else if (!strcmp(args[0], "log")) {  /* syslog server address */
 		struct logsrv logsrv;