[MEDIUM] implemented the "default_backend" keyword

The "default_backend" keyword used in a frontend sets the
default backend which will be used if no setbe rule matches.
diff --git a/include/types/proxy.h b/include/types/proxy.h
index d710be8..71f0f5c 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -76,6 +76,10 @@
 	int state;				/* proxy state */
 	struct sockaddr_in dispatch_addr;	/* the default address to connect to */
 	struct proxy *fiprm, *beprm;		/* proxy we find filter and backend params from (default: self) */
+	union {
+		struct proxy *be;		/* default backend, or NULL if none set */
+		char *name;			/* default backend name during config parse */
+	} defbe;
 	struct server *srv;			/* known servers */
 	int srv_act, srv_bck;			/* # of running servers */
 	int tot_wact, tot_wbck;			/* total weights of active and backup servers */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 9589841..38d894a 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -501,6 +501,8 @@
 			if (defproxy.monitor_uri)
 				curproxy->monitor_uri = strdup(defproxy.monitor_uri);
 			curproxy->monitor_uri_len = defproxy.monitor_uri_len;
+			if (defproxy.defbe.name)
+				curproxy->defbe.name = strdup(defproxy.defbe.name);
 		}
 
 		if (curproxy->cap & PR_CAP_BE) {
@@ -522,10 +524,14 @@
 	}
 	else if (!strcmp(args[0], "defaults")) {  /* use this one to assign default values */
 		/* some variables may have already been initialized earlier */
+		/* FIXME-20070101: we should do this too at the end of the
+		 * config parsing to free all default values.
+		 */
 		if (defproxy.check_req)     free(defproxy.check_req);
 		if (defproxy.cookie_name)   free(defproxy.cookie_name);
 		if (defproxy.capture_name)  free(defproxy.capture_name);
 		if (defproxy.monitor_uri)   free(defproxy.monitor_uri);
+		if (defproxy.defbe.name)    free(defproxy.defbe.name);
 
 		for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
 			if (defproxy.errmsg[rc].len)
@@ -981,6 +987,18 @@
 		}
 		return 0;
 	}
+	else if (!strcmp(args[0], "default_backend")) {
+		if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
+			return 0;
+
+		if (*(args[1]) == 0) {
+			Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
+			return -1;
+		}
+		if (curproxy->defbe.name)
+			free(curproxy->defbe.name);
+		curproxy->defbe.name = strdup(args[1]);
+	}
 	else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
 		if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
 			return 0;
@@ -2100,9 +2118,39 @@
 				Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
 				      file, curproxy->id);
 				cfgerr++;
+			}
+		}
+
+		/* if a default backend was specified, let's find it */
+		if (curproxy->defbe.name) {
+			struct proxy *target;
+
+			for (target = proxy; target != NULL; target = target->next) {
+				if (strcmp(target->id, curproxy->defbe.name) == 0)
+					break;
+			}
+			if (target == NULL) {
+				Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n", 
+				      file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
+				cfgerr++;
+			} else if (target == curproxy) {
+				Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
+				cfgerr++;
+			} else if (!(target->cap & PR_CAP_BE)) {
+				Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
+				      file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
+				cfgerr++;
+			} else if (target->mode != curproxy->mode) {
+				Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
+				      file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
+				cfgerr++;
+			} else {
+				free(curproxy->defbe.name);
+				curproxy->defbe.be = target;
 			}
 		}
 
+		/* find the target proxy in setbe */
 		if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
 			/* map jump target for ACT_SETBE in req_rep chain */ 
 			struct hdr_exp *exp;
diff --git a/src/proto_http.c b/src/proto_http.c
index 75fd152..0202ba2 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1087,7 +1087,19 @@
 					return 1;
 			}
 
-		} while (cur_proxy != t->be);  /* we loop only if t->be has changed */
+			if (!(t->flags & SN_BE_ASSIGNED) && cur_proxy->defbe.be) {
+				/* No backend was set, but there was a default
+				 * backend set in the frontend, so we use it and
+				 * loop again.
+				 */
+				t->be = cur_proxy->defbe.be;
+				t->be->beprm->beconn++;
+				if (t->be->beprm->beconn > t->be->beprm->beconn_max)
+					t->be->beprm->beconn_max = t->be->beprm->beconn;
+				t->be->beprm->cum_beconn++;
+				t->flags |= SN_BE_ASSIGNED;
+			}
+		} while (t->be != cur_proxy);  /* we loop only if t->be has changed */
 		
 
 		if (!(t->flags & SN_BE_ASSIGNED)) {