[MEDIUM] config: parse tcp layer4 rules (tcp-request accept/reject)

These rules currently only support the "accept" and "reject" actions.
They will apply on pure layer 4 and will not support any content.
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index fc020c9..b753c3b 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -1,7 +1,7 @@
 /*
  * AF_INET/AF_INET6 SOCK_STREAM protocol layer (tcp)
  *
- * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -717,6 +717,11 @@
 	const char *ptr = NULL;
 	unsigned int val;
 	int retlen;
+	int action;
+	int warn = 0;
+	int pol = ACL_COND_NONE;
+	struct acl_cond *cond;
+	struct tcp_rule *rule;
 
 	if (!*args[1]) {
 		snprintf(err, errlen, "missing argument for '%s' in %s '%s'",
@@ -758,12 +763,6 @@
 	}
 
 	if (!strcmp(args[1], "content")) {
-		int action;
-		int warn = 0;
-		int pol = ACL_COND_NONE;
-		struct acl_cond *cond;
-		struct tcp_rule *rule;
-
 		if (curpx == defpx) {
 			snprintf(err, errlen, "%s %s is not allowed in 'defaults' sections",
 				 args[0], args[1]);
@@ -819,9 +818,69 @@
 		return warn;
 	}
 
+	/* OK so we're in front of plain L4 rules */
+	if (!strcmp(args[1], "accept"))
+		action = TCP_ACT_ACCEPT;
+	else if (!strcmp(args[1], "reject"))
+		action = TCP_ACT_REJECT;
+	else {
+		retlen = snprintf(err, errlen,
+				  "'%s' expects 'inspect-delay', 'content', 'accept' or 'reject', in %s '%s' (was '%s')",
+				  args[0], proxy_type_str(curpx), curpx->id, args[1]);
+		return -1;
+	}
+
+	if (curpx == defpx) {
+		snprintf(err, errlen, "%s %s is not allowed in 'defaults' sections",
+			 args[0], args[1]);
+		return -1;
+	}
+
+	pol = ACL_COND_NONE;
+	cond = NULL;
+
+	if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
+		if ((cond = build_acl_cond(NULL, 0, curpx, (const char **)args+2)) == NULL) {
+			retlen = snprintf(err, errlen,
+					  "error detected in %s '%s' while parsing '%s' condition",
+					  proxy_type_str(curpx), curpx->id, args[2]);
+			return -1;
+		}
+	}
+	else if (*args[2]) {
+		retlen = snprintf(err, errlen,
+				  "'%s %s' only accepts 'if' or 'unless', in %s '%s' (was '%s')",
+				  args[0], args[1], proxy_type_str(curpx), curpx->id, args[2]);
+		return -1;
+	}
+
+	if (cond && (cond->requires & (ACL_USE_RTR_ANY|ACL_USE_L6_ANY|ACL_USE_L7_ANY))) {
+		struct acl *acl;
+		const char *name;
+
+		acl = cond_find_require(cond, ACL_USE_RTR_ANY|ACL_USE_L6_ANY|ACL_USE_L7_ANY);
+		name = acl ? acl->name : "(unknown)";
+
+		if (acl->requires & (ACL_USE_L6_ANY|ACL_USE_L7_ANY)) {
+			retlen = snprintf(err, errlen,
+					  "'%s %s' may not reference acl '%s' which makes use of payload in %s '%s'. Please use '%s content' for this.",
+					  args[0], args[1], name, proxy_type_str(curpx), curpx->id, args[0]);
+			return -1;
+		}
+		if (acl->requires & ACL_USE_RTR_ANY)
+			retlen = snprintf(err, errlen,
+					  "acl '%s' involves some response-only criteria which will be ignored.",
+					  name);
+
+		warn++;
+	}
+
-	snprintf(err, errlen, "unknown argument '%s' after '%s' in %s '%s'",
-		 args[1], args[0], proxy_type_str(proxy), curpx->id);
-	return -1;
+	rule = (struct tcp_rule *)calloc(1, sizeof(*rule));
+	rule->cond = cond;
+	rule->action = action;
+	LIST_INIT(&rule->list);
+	LIST_ADDQ(&curpx->tcp_req.l4_rules, &rule->list);
+	return warn;
 }