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 */
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 {
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)
{
/* 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)
{
}
*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;
(akwn->flags & KWF_MATCH_PREFIX) ? "*" : "");
}
}
+
+/* adds the keyword list kw_list to the head <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);
+}
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:
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:
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);
}
/*
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:
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. */
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)
*/
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);
}
/*
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:
/* 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:
/* 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.
/* 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.
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));
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);
}
/**************************************************************************/