MAJOR: acl: make acl_find_targets also resolve proxy names at config time

Proxy names are now resolved when the config is parsed and not at runtime.
This means that errors will be caught for real instead of having an ACL
silently never match. Another benefit is that the fetch will be much faster
since the lookup will not have to be performed anymore, eg for all ACLs
based on explicitly named stick-tables.

However some buggy configurations which used to silently fail in the past
will now refuse to load, hence the MAJOR tag.
diff --git a/src/acl.c b/src/acl.c
index aab7f41..dc9925d 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -27,6 +27,7 @@
 #include <proto/buffers.h>
 #include <proto/log.h>
 #include <proto/proxy.h>
+#include <proto/stick_table.h>
 
 #include <ebsttree.h>
 
@@ -2010,7 +2011,75 @@
 
 					free(expr->args->data.str.str);
 					expr->args->data.srv = srv;
-					continue;
+				}
+				else if (arg->type == ARGT_FE) {
+					struct proxy *prx;
+					char *pname;
+
+					if (!expr->args->data.str.len) {
+						Alert("proxy %s: acl '%s' %s(): missing frontend name.\n",
+						      p->id, acl->name, expr->kw->kw);
+						cfgerr++;
+						continue;
+					}
+
+					pname = expr->args->data.str.str;
+					prx = findproxy(pname, PR_CAP_FE);
+					if (!prx) {
+						Alert("proxy %s: acl '%s' %s(): unable to find frontend '%s'.\n",
+						      p->id, acl->name, expr->kw->kw, pname);
+						cfgerr++;
+						continue;
+					}
+
+					free(expr->args->data.str.str);
+					expr->args->data.prx = prx;
+				}
+				else if (arg->type == ARGT_BE) {
+					struct proxy *prx;
+					char *pname;
+
+					if (!expr->args->data.str.len) {
+						Alert("proxy %s: acl '%s' %s(): missing backend name.\n",
+						      p->id, acl->name, expr->kw->kw);
+						cfgerr++;
+						continue;
+					}
+
+					pname = expr->args->data.str.str;
+					prx = findproxy(pname, PR_CAP_BE);
+					if (!prx) {
+						Alert("proxy %s: acl '%s' %s(): unable to find backend '%s'.\n",
+						      p->id, acl->name, expr->kw->kw, pname);
+						cfgerr++;
+						continue;
+					}
+
+					free(expr->args->data.str.str);
+					expr->args->data.prx = prx;
+				}
+				else if (arg->type == ARGT_TAB) {
+					struct proxy *prx;
+					char *pname;
+
+					if (!expr->args->data.str.len) {
+						Alert("proxy %s: acl '%s' %s(): missing table name.\n",
+						      p->id, acl->name, expr->kw->kw);
+						cfgerr++;
+						continue;
+					}
+
+					pname = expr->args->data.str.str;
+					prx = find_stktable(pname);
+					if (!prx) {
+						Alert("proxy %s: acl '%s' %s(): unable to find table '%s'.\n",
+						      p->id, acl->name, expr->kw->kw, pname);
+						cfgerr++;
+						continue;
+					}
+
+					free(expr->args->data.str.str);
+					expr->args->data.prx = prx;
 				}
 				else if (arg->type == ARGT_USR) {
 					if (!expr->args->data.str.len) {
diff --git a/src/backend.c b/src/backend.c
index 43e1cef..fd2528f 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1378,7 +1378,7 @@
 /************************************************************************/
 
 /* set temp integer to the number of enabled servers on the proxy.
- * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * Accepts either 0 or 1 argument. Argument is a backend, other types will lead to
  * undefined behaviour.
  */
 static int
@@ -1386,14 +1386,8 @@
                 struct acl_expr *expr, struct acl_test *test)
 {
 	test->flags = ACL_TEST_F_VOL_TEST;
-	if (expr->args) {
-		/* another proxy was designated, we must look for it */
-		for (px = proxy; px; px = px->next)
-			if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
-				break;
-	}
-	if (!px)
-		return 0;
+	if (expr->args)
+		px = expr->args->data.prx;
 
 	if (px->srv_act)
 		temp_pattern.data.integer = px->srv_act;
@@ -1426,7 +1420,7 @@
 }
 
 /* set temp integer to the number of enabled servers on the proxy.
- * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * Accepts either 0 or 1 argument. Argument is a backend, other types will lead to
  * undefined behaviour.
  */
 static int
@@ -1434,15 +1428,10 @@
 		    struct acl_expr *expr, struct acl_test *test)
 {
 	struct server *iterator;
+
 	test->flags = ACL_TEST_F_VOL_TEST;
-	if (expr->args) {
-		/* another proxy was designated, we must look for it */
-		for (px = proxy; px; px = px->next)
-			if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
-				break;
-	}
-	if (!px)
-		return 0;
+	if (expr->args)
+		px = expr->args->data.prx;
 
 	temp_pattern.data.integer = 0;
 	iterator = px->srv;
@@ -1491,7 +1480,7 @@
 }
 
 /* set temp integer to the number of connections per second reaching the backend.
- * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * Accepts either 0 or 1 argument. Argument is a backend, other types will lead to
  * undefined behaviour.
  */
 static int
@@ -1499,21 +1488,15 @@
                        struct acl_expr *expr, struct acl_test *test)
 {
 	test->flags = ACL_TEST_F_VOL_TEST;
-	if (expr->args) {
-		/* another proxy was designated, we must look for it */
-		for (px = proxy; px; px = px->next)
-			if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
-				break;
-	}
-	if (!px)
-		return 0;
+	if (expr->args)
+		px = expr->args->data.prx;
 
 	temp_pattern.data.integer = read_freq_ctr(&px->be_sess_per_sec);
 	return 1;
 }
 
 /* set temp integer to the number of concurrent connections on the backend.
- * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * Accepts either 0 or 1 argument. Argument is a backend, other types will lead to
  * undefined behaviour.
  */
 static int
@@ -1521,21 +1504,15 @@
 		  struct acl_expr *expr, struct acl_test *test)
 {
 	test->flags = ACL_TEST_F_VOL_TEST;
-	if (expr->args) {
-		/* another proxy was designated, we must look for it */
-		for (px = proxy; px; px = px->next)
-			if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
-				break;
-	}
-	if (!px)
-		return 0;
+	if (expr->args)
+		px = expr->args->data.prx;
 
 	temp_pattern.data.integer = px->beconn;
 	return 1;
 }
 
 /* set temp integer to the total number of queued connections on the backend.
- * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * Accepts either 0 or 1 argument. Argument is a backend, other types will lead to
  * undefined behaviour.
  */
 static int
@@ -1543,14 +1520,8 @@
 		   struct acl_expr *expr, struct acl_test *test)
 {
 	test->flags = ACL_TEST_F_VOL_TEST;
-	if (expr->args) {
-		/* another proxy was designated, we must look for it */
-		for (px = proxy; px; px = px->next)
-			if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
-				break;
-	}
-	if (!px)
-		return 0;
+	if (expr->args)
+		px = expr->args->data.prx;
 
 	temp_pattern.data.integer = px->totpend;
 	return 1;
@@ -1561,7 +1532,7 @@
  * server, we return twice the total, just as if we had half a running server.
  * This is more or less correct anyway, since we expect the last server to come
  * back soon.
- * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * Accepts either 0 or 1 argument. Argument is a backend, other types will lead to
  * undefined behaviour.
  */
 static int
@@ -1571,14 +1542,8 @@
 	int nbsrv;
 
 	test->flags = ACL_TEST_F_VOL_TEST;
-	if (expr->args) {
-		/* another proxy was designated, we must look for it */
-		for (px = proxy; px; px = px->next)
-			if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
-				break;
-	}
-	if (!px)
-		return 0;
+	if (expr->args)
+		px = expr->args->data.prx;
 
 	if (px->srv_act)
 		nbsrv = px->srv_act;
diff --git a/src/frontend.c b/src/frontend.c
index bb117a5..ebe864b 100644
--- a/src/frontend.c
+++ b/src/frontend.c
@@ -508,7 +508,7 @@
 }
 
 /* set temp integer to the number of connections per second reaching the frontend.
- * Accepts either 0 or 1 argument. Argument is a string, other types will cause
+ * Accepts either 0 or 1 argument. Argument is a frontend, other types will cause
  * an undefined behaviour.
  */
 static int
@@ -516,21 +516,15 @@
                        struct acl_expr *expr, struct acl_test *test)
 {
 	test->flags = ACL_TEST_F_VOL_TEST;
-	if (expr->args) {
-		/* another proxy was designated, we must look for it */
-		for (px = proxy; px; px = px->next)
-			if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->args->data.str.str))
-				break;
-	}
-	if (!px)
-		return 0;
+	if (expr->args)
+		px = expr->args->data.prx;
 
 	temp_pattern.data.integer = read_freq_ctr(&px->fe_sess_per_sec);
 	return 1;
 }
 
 /* set temp integer to the number of concurrent connections on the frontend
- * Accepts either 0 or 1 argument. Argument is a string, other types will cause
+ * Accepts either 0 or 1 argument. Argument is a frontend, other types will cause
  * an undefined behaviour.
  */
 static int
@@ -538,14 +532,8 @@
 		  struct acl_expr *expr, struct acl_test *test)
 {
 	test->flags = ACL_TEST_F_VOL_TEST;
-	if (expr->args) {
-		/* another proxy was designated, we must look for it */
-		for (px = proxy; px; px = px->next)
-			if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->args->data.str.str))
-				break;
-	}
-	if (!px)
-		return 0;
+	if (expr->args)
+		px = expr->args->data.prx;
 
 	temp_pattern.data.integer = px->feconn;
 	return 1;
diff --git a/src/session.c b/src/session.c
index 40ceb3d..4c5671a 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1,7 +1,7 @@
 /*
  * Session management functions.
  *
- * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2012 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
@@ -2347,7 +2347,7 @@
 
 /* set temp integer to the General Purpose Counter 0 value from the session's source
  * address in the table pointed to by expr.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_get_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2360,10 +2360,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_get_gpc0(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -2411,7 +2408,7 @@
 
 /* Increment the General Purpose Counter 0 value from the session's source
  * address in the table pointed to by expr, and return it into temp integer.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_inc_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2424,10 +2421,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_inc_gpc0(&px->table, test, stktable_update_key(&px->table, key));
 }
@@ -2476,7 +2470,7 @@
 
 /* Clear the General Purpose Counter 0 value from the session's source address
  * in the table pointed to by expr, and return its previous value into temp integer.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_clr_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2489,10 +2483,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_clr_gpc0(&px->table, test, stktable_update_key(&px->table, key));
 }
@@ -2536,7 +2527,7 @@
 
 /* set temp integer to the cumulated number of connections from the session's source
  * address in the table pointed to by expr.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2549,10 +2540,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_conn_cnt(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -2601,7 +2589,7 @@
 
 /* set temp integer to the connection rate from the session's source address in the
  * table pointed to by expr, over the configured period.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_conn_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2614,17 +2602,14 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_conn_rate(&px->table, test, stktable_lookup_key(&px->table, key));
 }
 
 /* set temp integer to the number of connections from the session's source address
  * in the table pointed to by expr, after updating it.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2639,10 +2624,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	if ((ts = stktable_update_key(&px->table, key)) == NULL)
 		/* entry does not exist and could not be created */
@@ -2697,7 +2679,7 @@
 
 /* set temp integer to the number of concurrent connections from the session's source
  * address in the table pointed to by expr.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_conn_cur(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2710,10 +2692,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_conn_cur(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -2757,7 +2736,7 @@
 
 /* set temp integer to the cumulated number of session from the session's source
  * address in the table pointed to by expr.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_sess_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2770,10 +2749,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_sess_cnt(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -2822,7 +2798,7 @@
 
 /* set temp integer to the session rate from the session's source address in the
  * table pointed to by expr, over the configured period.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2835,10 +2811,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_sess_rate(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -2882,7 +2855,7 @@
 
 /* set temp integer to the cumulated number of session from the session's source
  * address in the table pointed to by expr.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_http_req_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2895,10 +2868,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_http_req_cnt(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -2947,7 +2917,7 @@
 
 /* set temp integer to the session rate from the session's source address in the
  * table pointed to by expr, over the configured period.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_http_req_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2960,10 +2930,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_http_req_rate(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -3007,7 +2974,7 @@
 
 /* set temp integer to the cumulated number of session from the session's source
  * address in the table pointed to by expr.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_http_err_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3020,10 +2987,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_http_err_cnt(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -3072,7 +3036,7 @@
 
 /* set temp integer to the session rate from the session's source address in the
  * table pointed to by expr, over the configured period.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_http_err_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3085,10 +3049,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_http_err_rate(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -3137,7 +3098,7 @@
 
 /* set temp integer to the number of kbytes received from the session's source
  * address in the table pointed to by expr.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_kbytes_in(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3150,10 +3111,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_kbytes_in(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -3204,7 +3162,7 @@
 
 /* set temp integer to the bytes rate from clients from the session's source address
  * in the table pointed to by expr, over the configured period.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3217,10 +3175,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_bytes_in_rate(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -3269,7 +3224,7 @@
 
 /* set temp integer to the number of kbytes sent to the session's source address in
  * the table pointed to by expr.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_kbytes_out(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3282,10 +3237,7 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_kbytes_out(&px->table, test, stktable_lookup_key(&px->table, key));
 }
@@ -3336,7 +3288,7 @@
 
 /* set temp integer to the bytes rate to client from the session's source address in
  * the table pointed to by expr, over the configured period.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_src_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3349,26 +3301,20 @@
 		return 0;
 
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	return acl_fetch_bytes_out_rate(&px->table, test, stktable_lookup_key(&px->table, key));
 }
 
 /* set temp integer to the number of used entries in the table pointed to by expr.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_table_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
                        struct acl_expr *expr, struct acl_test *test)
 {
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	test->flags = ACL_TEST_F_VOL_TEST;
 	temp_pattern.data.integer = px->table.current;
@@ -3376,17 +3322,14 @@
 }
 
 /* set temp integer to the number of free entries in the table pointed to by expr.
- * Accepts 0 or 1 argument of type string.
+ * Accepts 0 or 1 argument of type table.
  */
 static int
 acl_fetch_table_avl(struct proxy *px, struct session *l4, void *l7, int dir,
                             struct acl_expr *expr, struct acl_test *test)
 {
 	if (expr->args)
-		px = find_stktable(expr->args->data.str.str);
-
-	if (!px)
-		return 0; /* table not found */
+		px = expr->args->data.prx;
 
 	test->flags = ACL_TEST_F_VOL_TEST;
 	temp_pattern.data.integer = px->table.size - px->table.current;