MINOR: rules: record the last http/tcp rule that gave a final verdict

When a tcp-{request,response} content or http-request/http-response
rule delivers a final verdict (deny, accept, redirect etc), the last
evaluated one will now be recorded in the stream. The purpose is to
permit to log the last one that performed a final action. For now
the log is not produced.
diff --git a/include/haproxy/stream-t.h b/include/haproxy/stream-t.h
index f75a181..3fd5090 100644
--- a/include/haproxy/stream-t.h
+++ b/include/haproxy/stream-t.h
@@ -182,6 +182,8 @@
 	struct list *current_rule_list;         /* this is used to store the current executed rule list. */
 	void *current_rule;                     /* this is used to store the current rule to be resumed. */
 	int rules_exp;                          /* expiration date for current rules execution */
+	const char *last_rule_file;             /* last evaluated final rule's file (def: NULL) */
+	int last_rule_line;                     /* last evaluated final rule's line (def: 0) */
 
 	unsigned int stream_epoch;              /* copy of stream_epoch when the stream was created */
 	struct hlua *hlua;                      /* lua runtime context */
diff --git a/src/http_ana.c b/src/http_ana.c
index 8371148..84ddbf3 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -2744,6 +2744,8 @@
 					break;
 				case ACT_RET_STOP:
 					rule_ret = HTTP_RULE_RES_STOP;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 				case ACT_RET_YIELD:
 					s->current_rule = rule;
@@ -2751,20 +2753,30 @@
 					goto end;
 				case ACT_RET_ERR:
 					rule_ret = HTTP_RULE_RES_ERROR;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 				case ACT_RET_DONE:
 					rule_ret = HTTP_RULE_RES_DONE;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 				case ACT_RET_DENY:
 					if (txn->status == -1)
 						txn->status = 403;
 					rule_ret = HTTP_RULE_RES_DENY;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 				case ACT_RET_ABRT:
 					rule_ret = HTTP_RULE_RES_ABRT;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 				case ACT_RET_INV:
 					rule_ret = HTTP_RULE_RES_BADREQ;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 			}
 			continue; /* eval the next rule */
@@ -2774,12 +2786,16 @@
 		switch (rule->action) {
 			case ACT_ACTION_ALLOW:
 				rule_ret = HTTP_RULE_RES_STOP;
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto end;
 
 			case ACT_ACTION_DENY:
 				txn->status = rule->arg.http_reply->status;
 				txn->http_reply = rule->arg.http_reply;
 				rule_ret = HTTP_RULE_RES_DENY;
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto end;
 
 			case ACT_HTTP_REQ_TARPIT:
@@ -2787,6 +2803,8 @@
 				txn->status = rule->arg.http_reply->status;
 				txn->http_reply = rule->arg.http_reply;
 				rule_ret = HTTP_RULE_RES_DENY;
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto end;
 
 			case ACT_HTTP_REDIR: {
@@ -2796,6 +2814,8 @@
 					break;
 
 				rule_ret = ret ? HTTP_RULE_RES_ABRT : HTTP_RULE_RES_ERROR;
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto end;
 			}
 
@@ -2887,6 +2907,8 @@
 					break;
 				case ACT_RET_STOP:
 					rule_ret = HTTP_RULE_RES_STOP;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 				case ACT_RET_YIELD:
 					s->current_rule = rule;
@@ -2894,20 +2916,30 @@
 					goto end;
 				case ACT_RET_ERR:
 					rule_ret = HTTP_RULE_RES_ERROR;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 				case ACT_RET_DONE:
 					rule_ret = HTTP_RULE_RES_DONE;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 				case ACT_RET_DENY:
 					if (txn->status == -1)
 						txn->status = 502;
 					rule_ret = HTTP_RULE_RES_DENY;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 				case ACT_RET_ABRT:
 					rule_ret = HTTP_RULE_RES_ABRT;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 				case ACT_RET_INV:
 					rule_ret = HTTP_RULE_RES_BADREQ;
+					s->last_rule_file = rule->conf.file;
+					s->last_rule_line = rule->conf.line;
 					goto end;
 			}
 			continue; /* eval the next rule */
@@ -2917,12 +2949,16 @@
 		switch (rule->action) {
 			case ACT_ACTION_ALLOW:
 				rule_ret = HTTP_RULE_RES_STOP; /* "allow" rules are OK */
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto end;
 
 			case ACT_ACTION_DENY:
 				txn->status = rule->arg.http_reply->status;
 				txn->http_reply = rule->arg.http_reply;
 				rule_ret = HTTP_RULE_RES_DENY;
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto end;
 
 			case ACT_HTTP_REDIR: {
@@ -2932,6 +2968,8 @@
 					break;
 
 				rule_ret = ret ? HTTP_RULE_RES_ABRT : HTTP_RULE_RES_ERROR;
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto end;
 			}
 			/* other flags exists, but normally, they never be matched. */
diff --git a/src/stream.c b/src/stream.c
index cdd1498..382dd86 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -385,6 +385,8 @@
 	s->current_rule_list = NULL;
 	s->current_rule = NULL;
 	s->rules_exp = TICK_ETERNITY;
+	s->last_rule_file = NULL;
+	s->last_rule_line = 0;
 
 	/* Copy SC counters for the stream. We don't touch refcounts because
 	 * any reference we have is inherited from the session. Since the stream
diff --git a/src/tcp_rules.c b/src/tcp_rules.c
index 886dd9e..82c1c59 100644
--- a/src/tcp_rules.c
+++ b/src/tcp_rules.c
@@ -163,6 +163,8 @@
 						break;
 					case ACT_RET_STOP:
 					case ACT_RET_DONE:
+						s->last_rule_file = rule->conf.file;
+						s->last_rule_line = rule->conf.line;
 						goto end;
 					case ACT_RET_YIELD:
 						s->current_rule = rule;
@@ -174,12 +176,20 @@
 						}
 						goto missing_data;
 					case ACT_RET_DENY:
+						s->last_rule_file = rule->conf.file;
+						s->last_rule_line = rule->conf.line;
 						goto deny;
 					case ACT_RET_ABRT:
+						s->last_rule_file = rule->conf.file;
+						s->last_rule_line = rule->conf.line;
 						goto abort;
 					case ACT_RET_ERR:
+						s->last_rule_file = rule->conf.file;
+						s->last_rule_line = rule->conf.line;
 						goto internal;
 					case ACT_RET_INV:
+						s->last_rule_file = rule->conf.file;
+						s->last_rule_line = rule->conf.line;
 						goto invalid;
 				}
 				continue; /* eval the next rule */
@@ -187,9 +197,13 @@
 
 			/* If not action function defined, check for known actions */
 			if (rule->action == ACT_ACTION_ALLOW) {
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto end;
 			}
 			else if (rule->action == ACT_ACTION_DENY) {
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto deny;
 			}
 		}
@@ -331,6 +345,8 @@
 						break;
 					case ACT_RET_STOP:
 					case ACT_RET_DONE:
+						s->last_rule_file = rule->conf.file;
+						s->last_rule_line = rule->conf.line;
 						goto end;
 					case ACT_RET_YIELD:
 						s->current_rule = rule;
@@ -343,12 +359,20 @@
 						channel_dont_close(rep);
 						goto missing_data;
 					case ACT_RET_DENY:
+						s->last_rule_file = rule->conf.file;
+						s->last_rule_line = rule->conf.line;
 						goto deny;
 					case ACT_RET_ABRT:
+						s->last_rule_file = rule->conf.file;
+						s->last_rule_line = rule->conf.line;
 						goto abort;
 					case ACT_RET_ERR:
+						s->last_rule_file = rule->conf.file;
+						s->last_rule_line = rule->conf.line;
 						goto internal;
 					case ACT_RET_INV:
+						s->last_rule_file = rule->conf.file;
+						s->last_rule_line = rule->conf.line;
 						goto invalid;
 				}
 				continue; /* eval the next rule */
@@ -356,9 +380,13 @@
 
 			/* If not action function defined, check for known actions */
 			if (rule->action == ACT_ACTION_ALLOW) {
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto end;
 			}
 			else if (rule->action == ACT_ACTION_DENY) {
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto deny;
 			}
 			else if (rule->action == ACT_TCP_CLOSE) {
@@ -366,6 +394,8 @@
 				si_must_kill_conn(chn_prod(rep));
 				si_shutr(chn_prod(rep));
 				si_shutw(chn_prod(rep));
+				s->last_rule_file = rule->conf.file;
+				s->last_rule_line = rule->conf.line;
 				goto end;
 			}
 		}