From: Christopher Faulet Date: Tue, 17 Dec 2019 14:45:23 +0000 (+0100) Subject: MINOR: http-rules: Make set/del-map and add/del-acl custom actions X-Git-Tag: v2.2-dev1~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=046cf44f6c021b635897ea8d8a65926a03f9eb40;p=thirdparty%2Fhaproxy.git MINOR: http-rules: Make set/del-map and add/del-acl custom actions Now, these actions use their own dedicated function and are no longer handled "in place" during the HTTP rules evaluation. Thus the action names ACT_HTTP_*_ACL and ACT_HTTP_*_MAP are removed. The action type is now mapped as following: 0 = add-acl, 1 = set-map, 2 = del-acl and 3 = del-map. --- diff --git a/include/types/action.h b/include/types/action.h index 16d669d3b1..6d77f9cd2e 100644 --- a/include/types/action.h +++ b/include/types/action.h @@ -84,10 +84,6 @@ enum act_name { ACT_HTTP_SET_LOGL, ACT_HTTP_SET_TOS, ACT_HTTP_SET_MARK, - ACT_HTTP_ADD_ACL, - ACT_HTTP_DEL_ACL, - ACT_HTTP_DEL_MAP, - ACT_HTTP_SET_MAP, ACT_HTTP_EARLY_HINT, /* http request actions. */ diff --git a/src/http_act.c b/src/http_act.c index aa8dfff495..537b1d04a5 100644 --- a/src/http_act.c +++ b/src/http_act.c @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -1212,25 +1213,118 @@ static enum act_parse_ret parse_http_redirect(const char **args, int *orig_arg, return ACT_RET_PRS_OK; } +/* This function executes a add-acl, del-acl, set-map or del-map actions. On + * success, it returns ACT_RET_CONT. Otherwsize ACT_RET_ERR is returned. + */ +static enum act_return http_action_set_map(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s, int flags) +{ + struct pat_ref *ref; + struct buffer *key = NULL, *value = NULL; + enum act_return ret = ACT_RET_CONT; + + /* collect reference */ + ref = pat_ref_lookup(rule->arg.map.ref); + if (!ref) + goto leave; + + /* allocate key */ + key = alloc_trash_chunk(); + if (!key) + goto fail_alloc; + + /* collect key */ + key->data = build_logline(s, key->area, key->size, &rule->arg.map.key); + key->area[key->data] = '\0'; + + switch (rule->action) { + case 0: // add-acl + /* add entry only if it does not already exist */ + HA_SPIN_LOCK(PATREF_LOCK, &ref->lock); + if (pat_ref_find_elt(ref, key->area) == NULL) + pat_ref_add(ref, key->area, NULL, NULL); + HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock); + break; + + case 1: // set-map + /* allocate value */ + value = alloc_trash_chunk(); + if (!value) + goto fail_alloc; + + /* collect value */ + value->data = build_logline(s, value->area, value->size, &rule->arg.map.value); + value->area[value->data] = '\0'; + + HA_SPIN_LOCK(PATREF_LOCK, &ref->lock); + if (pat_ref_find_elt(ref, key->area) != NULL) { + /* update entry if it exists */ + pat_ref_set(ref, key->area, value->area, NULL); + } + else { + /* insert a new entry */ + pat_ref_add(ref, key->area, value->area, NULL); + } + HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock); + break; + + case 2: // del-acl + case 3: // del-map + /* returned code: 1=ok, 0=ko */ + HA_SPIN_LOCK(PATREF_LOCK, &ref->lock); + pat_ref_delete(ref, key->area); + HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock); + break; + + default: + ret = ACT_RET_ERR; + } + + + leave: + free_trash_chunk(key); + free_trash_chunk(value); + return ret; + + fail_alloc: + if (!(s->flags & SF_ERR_MASK)) + s->flags |= SF_ERR_RESOURCE; + ret = ACT_RET_ERR; + goto leave; +} + /* Parse a "add-acl", "del-acl", "set-map" or "del-map" actions. It takes one or - * two log-format string as argument depending on the action. It returns - * ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error. + * two log-format string as argument depending on the action. The action is + * stored in <.action> as an int (0=add-acl, 1=set-map, 2=del-acl, + * 3=del-map). It returns ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error. */ static enum act_parse_ret parse_http_set_map(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err) { int cap, cur_arg; - rule->action = (args[*orig_arg-1][0] == 'a' ? ACT_HTTP_ADD_ACL : - (args[*orig_arg-1][0] == 's' ? ACT_HTTP_SET_MAP : - (args[*orig_arg-1][4] == 'a' ? ACT_HTTP_DEL_ACL : ACT_HTTP_DEL_MAP))); + if (args[*orig_arg-1][0] == 'a') // add-acl + rule->action = 0; + else if (args[*orig_arg-1][0] == 's') // set-map + rule->action = 1; + else if (args[*orig_arg-1][4] == 'a') // del-acl + rule->action = 2; + else if (args[*orig_arg-1][4] == 'm') // del-map + rule->action = 3; + else { + memprintf(err, "internal error: unhandled action '%s'", args[0]); + return ACT_RET_PRS_ERR; + } + rule->action_ptr = http_action_set_map; cur_arg = *orig_arg; - if (rule->action == ACT_HTTP_SET_MAP && (!*args[cur_arg] || !*args[cur_arg+1])) { + if (rule->action == 1 && (!*args[cur_arg] || !*args[cur_arg+1])) { + /* 2 args for set-map */ memprintf(err, "expects exactly 2 arguments"); return ACT_RET_PRS_ERR; } else if (!*args[cur_arg]) { + /* only one arg for other actions */ memprintf(err, "expects exactly 1 arguments"); return ACT_RET_PRS_ERR; } @@ -1255,7 +1349,7 @@ static enum act_parse_ret parse_http_set_map(const char **args, int *orig_arg, s if (!parse_logformat_string(args[cur_arg], px, &rule->arg.map.key, LOG_OPT_HTTP, cap, err)) return ACT_RET_PRS_ERR; - if (rule->action == ACT_HTTP_SET_MAP) { + if (rule->action == 1) { /* value pattern for set-map only */ cur_arg++; LIST_INIT(&rule->arg.map.value); diff --git a/src/http_ana.c b/src/http_ana.c index dc9f06e69c..1002dab4a7 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -3038,122 +3037,6 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis http_remove_header(htx, &ctx); break; - case ACT_HTTP_DEL_ACL: - case ACT_HTTP_DEL_MAP: { - struct pat_ref *ref; - struct buffer *key; - - /* collect reference */ - ref = pat_ref_lookup(rule->arg.map.ref); - if (!ref) - continue; - - /* allocate key */ - key = alloc_trash_chunk(); - if (!key) { - if (!(s->flags & SF_ERR_MASK)) - s->flags |= SF_ERR_RESOURCE; - rule_ret = HTTP_RULE_RES_ERROR; - goto end; - } - - /* collect key */ - key->data = build_logline(s, key->area, key->size, &rule->arg.map.key); - key->area[key->data] = '\0'; - - /* perform update */ - /* returned code: 1=ok, 0=ko */ - HA_SPIN_LOCK(PATREF_LOCK, &ref->lock); - pat_ref_delete(ref, key->area); - HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock); - - free_trash_chunk(key); - break; - } - - case ACT_HTTP_ADD_ACL: { - struct pat_ref *ref; - struct buffer *key; - - /* collect reference */ - ref = pat_ref_lookup(rule->arg.map.ref); - if (!ref) - continue; - - /* allocate key */ - key = alloc_trash_chunk(); - if (!key) { - if (!(s->flags & SF_ERR_MASK)) - s->flags |= SF_ERR_RESOURCE; - rule_ret = HTTP_RULE_RES_ERROR; - goto end; - } - - /* collect key */ - key->data = build_logline(s, key->area, key->size, &rule->arg.map.key); - key->area[key->data] = '\0'; - - /* perform update */ - /* add entry only if it does not already exist */ - HA_SPIN_LOCK(PATREF_LOCK, &ref->lock); - if (pat_ref_find_elt(ref, key->area) == NULL) - pat_ref_add(ref, key->area, NULL, NULL); - HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock); - - free_trash_chunk(key); - break; - } - - case ACT_HTTP_SET_MAP: { - struct pat_ref *ref; - struct buffer *key, *value; - - /* collect reference */ - ref = pat_ref_lookup(rule->arg.map.ref); - if (!ref) - continue; - - /* allocate key */ - key = alloc_trash_chunk(); - if (!key) { - if (!(s->flags & SF_ERR_MASK)) - s->flags |= SF_ERR_RESOURCE; - rule_ret = HTTP_RULE_RES_ERROR; - goto end; - } - - /* allocate value */ - value = alloc_trash_chunk(); - if (!value) { - free_trash_chunk(key); - if (!(s->flags & SF_ERR_MASK)) - s->flags |= SF_ERR_RESOURCE; - rule_ret = HTTP_RULE_RES_ERROR; - goto end; - } - - /* collect key */ - key->data = build_logline(s, key->area, key->size, &rule->arg.map.key); - key->area[key->data] = '\0'; - - /* collect value */ - value->data = build_logline(s, value->area, value->size, &rule->arg.map.value); - value->area[value->data] = '\0'; - - /* perform update */ - HA_SPIN_LOCK(PATREF_LOCK, &ref->lock); - if (pat_ref_find_elt(ref, key->area) != NULL) - /* update entry if it exists */ - pat_ref_set(ref, key->area, value->area, NULL); - else - /* insert a new entry */ - pat_ref_add(ref, key->area, value->area, NULL); - HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock); - free_trash_chunk(key); - free_trash_chunk(value); - break; - } - case ACT_HTTP_EARLY_HINT: if (!(txn->req.flags & HTTP_MSGF_VER_11)) break; @@ -3354,121 +3237,6 @@ resume_execution: http_remove_header(htx, &ctx); break; - case ACT_HTTP_DEL_ACL: - case ACT_HTTP_DEL_MAP: { - struct pat_ref *ref; - struct buffer *key; - - /* collect reference */ - ref = pat_ref_lookup(rule->arg.map.ref); - if (!ref) - continue; - - /* allocate key */ - key = alloc_trash_chunk(); - if (!key) { - if (!(s->flags & SF_ERR_MASK)) - s->flags |= SF_ERR_RESOURCE; - rule_ret = HTTP_RULE_RES_ERROR; - goto end; - } - - /* collect key */ - key->data = build_logline(s, key->area, key->size, &rule->arg.map.key); - key->area[key->data] = '\0'; - - /* perform update */ - /* returned code: 1=ok, 0=ko */ - HA_SPIN_LOCK(PATREF_LOCK, &ref->lock); - pat_ref_delete(ref, key->area); - HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock); - - free_trash_chunk(key); - break; - } - - case ACT_HTTP_ADD_ACL: { - struct pat_ref *ref; - struct buffer *key; - - /* collect reference */ - ref = pat_ref_lookup(rule->arg.map.ref); - if (!ref) - continue; - - /* allocate key */ - key = alloc_trash_chunk(); - if (!key) { - if (!(s->flags & SF_ERR_MASK)) - s->flags |= SF_ERR_RESOURCE; - rule_ret = HTTP_RULE_RES_ERROR; - goto end; - } - - /* collect key */ - key->data = build_logline(s, key->area, key->size, &rule->arg.map.key); - key->area[key->data] = '\0'; - - /* perform update */ - /* check if the entry already exists */ - HA_SPIN_LOCK(PATREF_LOCK, &ref->lock); - if (pat_ref_find_elt(ref, key->area) == NULL) - pat_ref_add(ref, key->area, NULL, NULL); - HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock); - free_trash_chunk(key); - break; - } - - case ACT_HTTP_SET_MAP: { - struct pat_ref *ref; - struct buffer *key, *value; - - /* collect reference */ - ref = pat_ref_lookup(rule->arg.map.ref); - if (!ref) - continue; - - /* allocate key */ - key = alloc_trash_chunk(); - if (!key) { - if (!(s->flags & SF_ERR_MASK)) - s->flags |= SF_ERR_RESOURCE; - rule_ret = HTTP_RULE_RES_ERROR; - goto end; - } - - /* allocate value */ - value = alloc_trash_chunk(); - if (!value) { - free_trash_chunk(key); - if (!(s->flags & SF_ERR_MASK)) - s->flags |= SF_ERR_RESOURCE; - rule_ret = HTTP_RULE_RES_ERROR; - goto end; - } - - /* collect key */ - key->data = build_logline(s, key->area, key->size, &rule->arg.map.key); - key->area[key->data] = '\0'; - - /* collect value */ - value->data = build_logline(s, value->area, value->size, &rule->arg.map.value); - value->area[value->data] = '\0'; - - /* perform update */ - HA_SPIN_LOCK(PATREF_LOCK, &ref->lock); - if (pat_ref_find_elt(ref, key->area) != NULL) - /* update entry if it exists */ - pat_ref_set(ref, key->area, value->area, NULL); - else - /* insert a new entry */ - pat_ref_add(ref, key->area, value->area, NULL); - HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock); - free_trash_chunk(key); - free_trash_chunk(value); - break; - } - case ACT_HTTP_REDIR: rule_ret = HTTP_RULE_RES_DONE; if (!http_apply_redirect_rule(rule->arg.redir, s, txn))