/* The acl will be linked to from the proxy where it is declared */
struct acl {
struct list list; /* chaining */
char *name; /* acl name */
struct list expr; /* list of acl_exprs */
int cache_idx; /* ACL index in cache */
unsigned int requires; /* or'ed bit mask of all acl_expr's ACL_USE_* */
};
rule 应该是 action + condition 组成
有些动作自身可能也需要记录一些信息。不同的 rule 对应动作的信息可能不同,比如 reqirep 等
block rules 的动作比较单一, condition 满足之后处理结果均相同
condition,完成 rule 检测的判断条件 对应数据结构: struct acl_cond
struct acl_cond {
struct list list; /* Some specific tests may use multiple conditions */
struct list suites; /* list of acl_term_suites */
int pol; /* polarity: ACL_COND_IF / ACL_COND_UNLESS */
unsigned int requires; /* or'ed bit mask of all acl's ACL_USE_* */
const char *file; /* config file where the condition is declared */
int line; /* line in the config file where the condition is declared */
};
condition 包含多个 ACL 组。组的分割逻辑是逻辑或(|| 或者 or),即 struct list suites 的成员,组的数据结构 struct acl_term_suite
struct acl_term_suite {
struct list list; /* chaining of term suites */
struct list terms; /* list of acl_terms */
};
该数据结构可以包含多个 ACL,以及每个 ACL 可能的一个取反标识 '!'
所有表达式中相邻的 ACL 且其逻辑关系为逻辑与(&&) 的构成一个 ACL 组
比如 if acl1 !acl2 or acl3 acl4,则构成两个 acl_term_suite,分别是 acl1 !acl2 和 acl3 acl4
每个 ACL 及其可能的取反标记对应的数据结构: struct acl_term
struct acl_term {
struct list list; /* chaining */
struct acl *acl; /* acl pointed to by this term */
int neg; /* 1 if the ACL result must be negated */
};
一个 ACL 包含多个 expr
3. rule 的执行
概括起来很简单,执行判断条件。符合条件,然后执行对应动作。
下面是 rspadd 的示例代码:
123456789101112131415
/* add response headers from the rule sets in the same order */
list_for_each_entry(wl, &rule_set->rsp_add, list) {
if (txn->status < 200)
break;
if (wl->cond) {
int ret = acl_exec_cond(wl->cond, px, t, txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
ret = acl_pass(ret);
if (((struct acl_cond *)wl->cond)->pol == ACL_COND_UNLESS)
ret = !ret;
if (!ret)
continue;
}
if (unlikely(http_header_add_tail(&txn->rsp, &txn->hdr_idx, wl->s) < 0))
goto return_bad_resp;
}