MINOR: stream: Replace last_rule_file/line fields by a more generic field

The last evaluated rule is now saved in a generic structure, named
last_entity, with a type to identify it. The idea is to be able to store
other kind of entity that may interrupt a specific processing.

The type of the last evaluated rule is set to 1. It will be replace later by
an enum to be more explicit. In addition, the pointer to the rule itself is
saved instead of its location.

The sample fetch "last_entity" was added to retrieve the information about
it. In this case, it is the rule localtion, the config file containing the
rule followed by the line where the rule is defined, separated by a
colon. This sample fetch is not documented yet.
This commit is contained in:
Christopher Faulet 2024-10-31 11:23:12 +01:00
parent dcf334168c
commit c9fa78e747
4 changed files with 115 additions and 85 deletions

View File

@ -289,8 +289,11 @@ struct stream {
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) */

View File

@ -2739,8 +2739,8 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
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;
@ -2748,8 +2748,8 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
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;
}
@ -2757,30 +2757,30 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
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 */
@ -2790,16 +2790,16 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
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:
@ -2807,8 +2807,8 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
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: {
@ -2818,8 +2818,8 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
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;
}
@ -2913,8 +2913,8 @@ static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct lis
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;
@ -2922,8 +2922,8 @@ static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct lis
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;
}
@ -2931,30 +2931,30 @@ static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct lis
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 */
@ -2964,16 +2964,16 @@ static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct lis
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: {
@ -2983,8 +2983,8 @@ static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct lis
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. */

View File

@ -389,8 +389,8 @@ struct stream *stream_new(struct session *sess, struct stconn *sc, struct buffer
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) {
@ -4095,25 +4095,51 @@ static int smp_fetch_cur_tunnel_timeout(const struct arg *args, struct sample *s
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;
}
@ -4178,6 +4204,7 @@ static struct sample_fetch_kw_list smp_kws = {ILH, {
{ "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, },

View File

@ -166,8 +166,8 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit)
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;
@ -175,26 +175,26 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit)
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 */
@ -202,13 +202,13 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit)
/* 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;
}
}
@ -350,8 +350,8 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
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;
@ -359,27 +359,27 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
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 */
@ -387,13 +387,13 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
/* 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) {
@ -401,8 +401,8 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
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;
}
}