[MAJOR] session: add track-counters to track counters related to the session

This patch adds the ability to set a pointer in the session to an
entry in a stick table which holds various counters related to a
specific pattern.

Right now the syntax matches the target syntax and only the "src"
pattern can be specified, to track counters related to the session's
IPv4 source address. There is a special function to extract it and
convert it to a key. But the goal is to be able to later support as
many patterns as for the stick rules, and get rid of the specific
function.

The "track-counters" directive may only be set in a "tcp-request"
statement right now. Only the first one applies. Probably that later
we'll support multi-criteria tracking for a single session and that
we'll have to name tracking pointers.

No counter is updated right now, only the refcount is. Some subsequent
patches will have to bring that feature.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index f313b71..871310b 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -4688,6 +4688,7 @@
 	while (curproxy != NULL) {
 		struct switching_rule *rule;
 		struct sticking_rule *mrule;
+		struct tcp_rule *trule;
 		struct listener *listener;
 		unsigned int next_id;
 
@@ -4936,6 +4937,43 @@
 			}
 		}
 
+		/* find the target table for 'tcp-request' layer 4 rules */
+		list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
+			struct proxy *target;
+
+			if (trule->action != TCP_ACT_TRK_CTR)
+				continue;
+
+			if (trule->act_prm.trk_ctr.table.n)
+				target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
+			else
+				target = curproxy;
+
+			if (!target) {
+				Alert("Proxy '%s': unable to find table '%s' referenced by track-counter.\n",
+				      curproxy->id, trule->act_prm.trk_ctr.table.n);
+				cfgerr++;
+			}
+			else if (target->table.size == 0) {
+				Alert("Proxy '%s': table '%s' used but not configured.\n",
+				      curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
+				cfgerr++;
+			}
+			else if (trule->act_prm.trk_ctr.type != target->table.type) {
+				Alert("Proxy '%s': type of track-counters pattern not usable with type of stick-table '%s'.\n",
+				      curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
+				cfgerr++;
+			}
+			else {
+				free(trule->act_prm.trk_ctr.table.n);
+				trule->act_prm.trk_ctr.table.t = &target->table;
+				/* Note: if we decide to enhance the track-counters syntax, we may be able
+				 * to pass a list of counters to track and allocate them right here using
+				 * stktable_alloc_data_type().
+				 */
+			}
+		}
+
 		if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
 		    !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
 		    (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {