]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stream: Replace last_rule_file/line fields by a more generic field
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 31 Oct 2024 10:23:12 +0000 (11:23 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 31 Oct 2024 15:36:39 +0000 (16:36 +0100)
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.

include/haproxy/stream-t.h
src/http_ana.c
src/stream.c
src/tcp_rules.c

index 363b7eb7550c2e9ffcda50decf8acb8cd2475eab..9589c304842b738f277aabee5e7fb13fa0e5645b 100644 (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) */
index ab9124d792cc3a8d16ecb55d1f495dac4e0b07c0..d83709af792a74199230903c878b44101dd84964 100644 (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 @@ resume_execution:
                                        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 @@ resume_execution:
                                                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 @@ resume_execution:
                                        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 @@ resume_execution:
                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 @@ resume_execution:
                                        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. */
index 34696bd2c7a451715641708cd84c5b085a19f6a7..618f350f73b365d59406e25725dab5d094e3a9f4 100644 (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, },
index 2613056f7dd7d976111349368ff3090264184242..d3263b075b8f6ba751ce6f4ec18839f3e7e68987 100644 (file)
@@ -166,8 +166,8 @@ resume_execution:
                                                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 @@ resume_execution:
                                                        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 @@ resume_execution:
 
                        /* 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 @@ resume_execution:
                                                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 @@ resume_execution:
                                                        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 @@ resume_execution:
 
                        /* 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 @@ resume_execution:
                                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;
                        }
                }