void *current_rule; /* this is used to store the current rule to be resumed. */
int rules_exp; /* expiration date for current rules execution */
int tunnel_timeout;
- 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) */
+
+ struct {
+ void *ptr; /* Pointer on the entity (def: NULL) */
+ int type; /* entity type (0: undef, 1: rule) */
+ } last_entity; /* last evaluated entity that interrupted processing */
unsigned int stream_epoch; /* copy of stream_epoch when the stream was created */
struct hlua *hlua[2]; /* lua runtime context (0: global, 1: per-thread) */
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
case ACT_RET_YIELD:
s->current_rule = rule;
send_log(s->be, LOG_WARNING,
"Internal error: action yields while it is no long allowed "
"for the http-request actions.");
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
rule_ret = HTTP_RULE_RES_ERROR;
goto end;
}
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
}
continue; /* eval the next rule */
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
case ACT_HTTP_REQ_TARPIT:
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
case ACT_HTTP_REDIR: {
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
}
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
case ACT_RET_YIELD:
s->current_rule = rule;
send_log(s->be, LOG_WARNING,
"Internal error: action yields while it is no long allowed "
"for the http-response/http-after-response actions.");
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
rule_ret = HTTP_RULE_RES_ERROR;
goto end;
}
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
}
continue; /* eval the next rule */
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
case ACT_HTTP_REDIR: {
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
}
/* other flags exists, but normally, they never be matched. */
s->current_rule_list = NULL;
s->current_rule = NULL;
s->rules_exp = TICK_ETERNITY;
- s->last_rule_file = NULL;
- s->last_rule_line = 0;
+ s->last_entity.type = 0;
+ s->last_entity.ptr = NULL;
s->stkctr = NULL;
if (pool_head_stk_ctr) {
static int smp_fetch_last_rule_file(const struct arg *args, struct sample *smp, const char *km, void *private)
{
+ struct act_rule *rule;
+
smp->flags = SMP_F_VOL_TXN;
smp->data.type = SMP_T_STR;
- if (!smp->strm || !smp->strm->last_rule_file)
+ if (!smp->strm || smp->strm->last_entity.type != 1)
return 0;
+ rule = smp->strm->last_entity.ptr;
smp->flags |= SMP_F_CONST;
- smp->data.u.str.area = (char *)smp->strm->last_rule_file;
- smp->data.u.str.data = strlen(smp->strm->last_rule_file);
+ smp->data.u.str.area = (char *)rule->conf.file;
+ smp->data.u.str.data = strlen(rule->conf.file);
return 1;
}
static int smp_fetch_last_rule_line(const struct arg *args, struct sample *smp, const char *km, void *private)
{
+ struct act_rule *rule;
+
smp->flags = SMP_F_VOL_TXN;
smp->data.type = SMP_T_SINT;
- if (!smp->strm || !smp->strm->last_rule_line)
+ if (!smp->strm || smp->strm->last_entity.type != 1)
+ return 0;
+
+ rule = smp->strm->last_entity.ptr;
+ smp->data.u.sint = rule->conf.line;
+ return 1;
+}
+
+static int smp_fetch_last_entity(const struct arg *args, struct sample *smp, const char *km, void *private)
+{
+ smp->flags = SMP_F_VOL_TXN;
+ smp->data.type = SMP_T_STR;
+ if (!smp->strm)
+ return 0;
+
+ if (smp->strm->last_entity.type == 1) {
+ struct act_rule *rule = smp->strm->last_entity.ptr;
+ struct buffer *trash = get_trash_chunk();
+
+ trash->data = snprintf(trash->area, trash->size, "%s:%d", rule->conf.file, rule->conf.line);
+ smp->data.u.str = *trash;
+ }
+ else
return 0;
- smp->data.u.sint = smp->strm->last_rule_line;
return 1;
}
{ "cur_client_timeout", smp_fetch_cur_client_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, },
{ "cur_server_timeout", smp_fetch_cur_server_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
{ "cur_tunnel_timeout", smp_fetch_cur_tunnel_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
+ { "last_entity", smp_fetch_last_entity, 0, NULL, SMP_T_STR, SMP_USE_INTRN, },
{ "last_rule_file", smp_fetch_last_rule_file, 0, NULL, SMP_T_STR, SMP_USE_INTRN, },
{ "last_rule_line", smp_fetch_last_rule_line, 0, NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "txn.conn_retries", smp_fetch_conn_retries, 0, NULL, SMP_T_SINT, SMP_USE_L4SRV, },
break;
case ACT_RET_STOP:
case ACT_RET_DONE:
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
case ACT_RET_YIELD:
s->current_rule = rule;
send_log(s->be, LOG_WARNING,
"Internal error: yield not allowed if the inspect-delay expired "
"for the tcp-request content actions.");
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto internal;
}
goto missing_data;
case ACT_RET_DENY:
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto deny;
case ACT_RET_ABRT:
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto abort;
case ACT_RET_ERR:
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto internal;
case ACT_RET_INV:
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto invalid;
}
continue; /* eval the next rule */
/* 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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
}
else if (rule->action == ACT_ACTION_DENY) {
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto deny;
}
}
break;
case ACT_RET_STOP:
case ACT_RET_DONE:
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
case ACT_RET_YIELD:
s->current_rule = rule;
send_log(s->be, LOG_WARNING,
"Internal error: yield not allowed if the inspect-delay expired "
"for the tcp-response content actions.");
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto internal;
}
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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto deny;
case ACT_RET_ABRT:
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto abort;
case ACT_RET_ERR:
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto internal;
case ACT_RET_INV:
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto invalid;
}
continue; /* eval the next rule */
/* 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;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
}
else if (rule->action == ACT_ACTION_DENY) {
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto deny;
}
else if (rule->action == ACT_TCP_CLOSE) {
sc_must_kill_conn(s->scb);
sc_abort(s->scb);
sc_shutdown(s->scb);
- s->last_rule_file = rule->conf.file;
- s->last_rule_line = rule->conf.line;
+ s->last_entity.type = 1;
+ s->last_entity.ptr = rule;
goto end;
}
}