diff --git a/include/haproxy/action-t.h b/include/haproxy/action-t.h index 96b0243ae..c10360e2b 100644 --- a/include/haproxy/action-t.h +++ b/include/haproxy/action-t.h @@ -206,6 +206,7 @@ struct act_rule { void *p[4]; } act; /* generic pointers to be used by custom actions */ } arg; /* arguments used by some actions */ + struct thread_exec_ctx exec_ctx; /* execution context */ struct { char *file; /* file name where the rule appears (or NULL) */ int line; /* line number where the rule appears */ @@ -217,7 +218,9 @@ struct action_kw { enum act_parse_ret (*parse)(const char **args, int *cur_arg, struct proxy *px, struct act_rule *rule, char **err); int flags; + /* 4 bytes here */ void *private; + struct thread_exec_ctx exec_ctx; /* execution context */ }; struct action_kw_list { diff --git a/include/haproxy/action.h b/include/haproxy/action.h index 3841df990..1dad89ff8 100644 --- a/include/haproxy/action.h +++ b/include/haproxy/action.h @@ -35,6 +35,7 @@ int act_resolution_cb(struct resolv_requester *requester, struct dns_counters *c int act_resolution_error_cb(struct resolv_requester *requester, int error_code); const char *action_suggest(const char *word, const struct list *keywords, const char **extra); void free_act_rule(struct act_rule *rule); +void act_add_list(struct list *head, struct action_kw_list *kw_list); static inline struct action_kw *action_lookup(struct list *keywords, const char *kw) { diff --git a/src/action.c b/src/action.c index 8a1486d10..9c5153b1c 100644 --- a/src/action.c +++ b/src/action.c @@ -25,7 +25,8 @@ /* Check an action ruleset validity. It returns the number of error encountered - * and err_code is updated if a warning is emitted. + * and err_code is updated if a warning is emitted. It also takes this + * opportunity for filling the execution context based on available info. */ int check_action_rules(struct list *rules, struct proxy *px, int *err_code) { @@ -40,6 +41,13 @@ int check_action_rules(struct list *rules, struct proxy *px, int *err_code) } *err_code |= warnif_tcp_http_cond(px, rule->cond); ha_free(&errmsg); + + if (!rule->exec_ctx.type) { + if (rule->kw && rule->kw->exec_ctx.type) + rule->exec_ctx = rule->kw->exec_ctx; + else if (rule->action_ptr) + rule->exec_ctx = EXEC_CTX_MAKE(TH_EX_CTX_FUNC, rule->action_ptr); + } } return err; @@ -378,3 +386,21 @@ void dump_act_rules(const struct list *rules, const char *pfx) (akwn->flags & KWF_MATCH_PREFIX) ? "*" : ""); } } + +/* adds the keyword list kw_list to the head */ +void act_add_list(struct list *head, struct action_kw_list *kw_list) +{ + int i; + + for (i = 0; kw_list->kw[i].kw != NULL; i++) { + /* store declaration file/line if known */ + if (kw_list->kw[i].exec_ctx.type) + continue; + + if (caller_initcall) { + kw_list->kw[i].exec_ctx.type = TH_EX_CTX_INITCALL; + kw_list->kw[i].exec_ctx.initcall = caller_initcall; + } + } + LIST_APPEND(head, &kw_list->list); +} diff --git a/src/http_ana.c b/src/http_ana.c index 7cd6529f1..d878d806d 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -2881,7 +2881,8 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis s->waiting_entity.ptr = NULL; } - switch (rule->action_ptr(rule, px, sess, s, act_opts)) { + switch (EXEC_CTX_WITH_RET(rule->exec_ctx, + rule->action_ptr(rule, px, sess, s, act_opts))) { case ACT_RET_CONT: break; case ACT_RET_STOP: @@ -3073,7 +3074,8 @@ resume_execution: s->waiting_entity.ptr = NULL; } - switch (rule->action_ptr(rule, px, sess, s, act_opts)) { + switch (EXEC_CTX_WITH_RET(rule->exec_ctx, + rule->action_ptr(rule, px, sess, s, act_opts))) { case ACT_RET_CONT: break; case ACT_RET_STOP: diff --git a/src/http_rules.c b/src/http_rules.c index 8a3f9ec17..ee4543083 100644 --- a/src/http_rules.c +++ b/src/http_rules.c @@ -52,17 +52,17 @@ struct action_kw_list http_after_res_keywords = { void http_req_keywords_register(struct action_kw_list *kw_list) { - LIST_APPEND(&http_req_keywords.list, &kw_list->list); + act_add_list(&http_req_keywords.list, kw_list); } void http_res_keywords_register(struct action_kw_list *kw_list) { - LIST_APPEND(&http_res_keywords.list, &kw_list->list); + act_add_list(&http_res_keywords.list, kw_list); } void http_after_res_keywords_register(struct action_kw_list *kw_list) { - LIST_APPEND(&http_after_res_keywords.list, &kw_list->list); + act_add_list(&http_after_res_keywords.list, kw_list); } /* diff --git a/src/quic_rules.c b/src/quic_rules.c index 050548a8e..0da0aadf6 100644 --- a/src/quic_rules.c +++ b/src/quic_rules.c @@ -37,7 +37,8 @@ int quic_init_exec_rules(struct listener *li, struct quic_dgram *dgram) continue; if (rule->action_ptr) { - switch (rule->action_ptr(rule, px, &rule_sess, NULL, 0)) { + switch (EXEC_CTX_WITH_RET(rule->exec_ctx, + rule->action_ptr(rule, px, &rule_sess, NULL, 0))) { case ACT_RET_CONT: break; case ACT_RET_DONE: @@ -142,7 +143,7 @@ struct action_kw_list quic_init_actions_list = { void quic_init_actions_register(struct action_kw_list *kw_list) { - LIST_APPEND(&quic_init_actions_list.list, &kw_list->list); + act_add_list(&quic_init_actions_list.list, kw_list); } /* Return the struct quic-initial action associated to a keyword. */ diff --git a/src/stream.c b/src/stream.c index 68aff8c26..2382c4a36 100644 --- a/src/stream.c +++ b/src/stream.c @@ -3380,7 +3380,7 @@ static enum act_parse_ret stream_parse_use_service(const char **args, int *cur_a void service_keywords_register(struct action_kw_list *kw_list) { - LIST_APPEND(&service_keywords, &kw_list->list); + act_add_list(&service_keywords, kw_list); } struct action_kw *service_find(const char *kw) diff --git a/src/tcp_rules.c b/src/tcp_rules.c index 785fcf85b..63ccc9610 100644 --- a/src/tcp_rules.c +++ b/src/tcp_rules.c @@ -45,22 +45,22 @@ struct list tcp_res_cont_keywords = LIST_HEAD_INIT(tcp_res_cont_keywords); */ void tcp_req_conn_keywords_register(struct action_kw_list *kw_list) { - LIST_APPEND(&tcp_req_conn_keywords, &kw_list->list); + act_add_list(&tcp_req_conn_keywords, kw_list); } void tcp_req_sess_keywords_register(struct action_kw_list *kw_list) { - LIST_APPEND(&tcp_req_sess_keywords, &kw_list->list); + act_add_list(&tcp_req_sess_keywords, kw_list); } void tcp_req_cont_keywords_register(struct action_kw_list *kw_list) { - LIST_APPEND(&tcp_req_cont_keywords, &kw_list->list); + act_add_list(&tcp_req_cont_keywords, kw_list); } void tcp_res_cont_keywords_register(struct action_kw_list *kw_list) { - LIST_APPEND(&tcp_res_cont_keywords, &kw_list->list); + act_add_list(&tcp_res_cont_keywords, kw_list); } /* @@ -187,7 +187,8 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit) resume_execution: /* Always call the action function if defined */ if (rule->action_ptr) { - switch (rule->action_ptr(rule, s->be, s->sess, s, act_opts)) { + switch (EXEC_CTX_WITH_RET(rule->exec_ctx, + rule->action_ptr(rule, s->be, s->sess, s, act_opts))) { case ACT_RET_CONT: break; case ACT_RET_STOP: @@ -405,7 +406,8 @@ resume_execution: /* Always call the action function if defined */ if (rule->action_ptr) { - switch (rule->action_ptr(rule, s->be, s->sess, s, act_opts)) { + switch (EXEC_CTX_WITH_RET(rule->exec_ctx, + rule->action_ptr(rule, s->be, s->sess, s, act_opts))) { case ACT_RET_CONT: break; case ACT_RET_STOP: @@ -570,7 +572,9 @@ int tcp_exec_l4_rules(struct session *sess) /* Always call the action function if defined */ if (rule->action_ptr) { - switch (rule->action_ptr(rule, sess->fe, sess, NULL, ACT_OPT_FINAL | ACT_OPT_FIRST)) { + switch (EXEC_CTX_WITH_RET(rule->exec_ctx, + rule->action_ptr(rule, sess->fe, sess, NULL, + ACT_OPT_FINAL | ACT_OPT_FIRST))) { case ACT_RET_YIELD: /* yield is not allowed at this point. If this return code is * used it is a bug, so I prefer to abort the process. @@ -659,7 +663,9 @@ int tcp_exec_l5_rules(struct session *sess) /* Always call the action function if defined */ if (rule->action_ptr) { - switch (rule->action_ptr(rule, sess->fe, sess, NULL, ACT_OPT_FINAL | ACT_OPT_FIRST)) { + switch (EXEC_CTX_WITH_RET(rule->exec_ctx, + rule->action_ptr(rule, sess->fe, sess, NULL, + ACT_OPT_FINAL | ACT_OPT_FIRST))) { case ACT_RET_YIELD: /* yield is not allowed at this point. If this return code is * used it is a bug, so I prefer to abort the process. diff --git a/src/tcpcheck.c b/src/tcpcheck.c index 86c798e73..362673ddd 100644 --- a/src/tcpcheck.c +++ b/src/tcpcheck.c @@ -2417,7 +2417,8 @@ enum tcpcheck_eval_ret tcpcheck_eval_action_kw(struct check *check, struct tcpch enum act_return act_ret; act_rule =rule->action_kw.rule; - act_ret = act_rule->action_ptr(act_rule, check->proxy, check->sess, NULL, 0); + act_ret = EXEC_CTX_WITH_RET(act_rule->exec_ctx, + act_rule->action_ptr(act_rule, check->proxy, check->sess, NULL, 0)); if (act_ret != ACT_RET_CONT) { chunk_printf(&trash, "TCPCHK ACTION unexpected result at step %d\n", tcpcheck_get_step_id(check, rule)); @@ -2636,7 +2637,7 @@ int tcpcheck_main(struct check *check) void tcp_check_keywords_register(struct action_kw_list *kw_list) { - LIST_APPEND(&tcp_check_keywords.list, &kw_list->list); + act_add_list(&tcp_check_keywords.list, kw_list); } /**************************************************************************/