[MEDIUM] added the 'block' keyword to the config language

The new 'block' keyword makes it possible to block a request based on
ACL test results. Block accepts two optional arguments : 'if' <cond>
and 'unless' <cond>.

The request will be blocked with a 403 response if the condition is validated
(if) or if it is not (unless). Do not rely on this one too much, as it's more
of a proof of concept helping in developing other matches.
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 6a96f94..c403e59 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -84,6 +84,7 @@
 		char *name;			/* default backend name during config parse */
 	} defbe;
 	struct list acl;                        /* ACL declared on this proxy */
+	struct list block_cond;                 /* early blocking conditions (chained) */
 	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 c4c6c8c..41d7066 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -494,6 +494,7 @@
 		proxy = curproxy;
 		LIST_INIT(&curproxy->pendconns);
 		LIST_INIT(&curproxy->acl);
+		LIST_INIT(&curproxy->block_cond);
 
 		curproxy->id = strdup(args[1]);
 		curproxy->cap = rc;
@@ -912,6 +913,28 @@
 		}
 		curproxy->conn_retries = atol(args[1]);
 	}
+	else if (!strcmp(args[0], "block")) {  /* early blocking based on ACLs */
+		int pol = ACL_COND_NONE;
+		struct acl_cond *cond;
+
+		if (!strcmp(args[1], "if"))
+			pol = ACL_COND_IF;
+		else if (!strcmp(args[1], "unless"))
+			pol = ACL_COND_UNLESS;
+
+		if (pol == ACL_COND_NONE) {
+			Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
+			      file, linenum, args[0]);
+			return -1;
+		}
+
+		if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
+			Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
+			      file, linenum);
+			return -1;
+		}
+		LIST_ADDQ(&curproxy->block_cond, &cond->list);
+	}
 	else if (!strcmp(args[0], "stats")) {
 		if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
 			return 0;
diff --git a/src/proto_http.c b/src/proto_http.c
index 706ef46..6d4c152 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1674,9 +1674,25 @@
 		 */
 
 		do {
+			struct acl_cond *cond;
 			struct proxy *rule_set = t->be;
 			cur_proxy = t->be;
 
+			/* first check whether we have some ACLs set to block this request */
+			list_for_each_entry(cond, &cur_proxy->block_cond, list) {
+				int ret = acl_exec_cond(cond, cur_proxy, t, txn);
+				if (cond->pol == ACL_COND_UNLESS)
+					ret = !ret;
+
+				if (ret) {
+					txn->status = 403;
+					/* let's log the request time */
+					t->logs.t_request = tv_ms_elapsed(&t->logs.tv_accept, &now);
+					client_retnclose(t, error_message(t, HTTP_ERR_403));
+					goto return_prx_cond;
+				}
+			}
+
 			/* try headers filters */
 			if (rule_set->req_exp != NULL) {
 				if (apply_filters_to_request(t, req, rule_set->req_exp) < 0)