Skip to content

Commit

Permalink
Add option for set cache policy based on cookie name or pattern
Browse files Browse the repository at this point in the history
Fixes #1544

Signed-off-by: Aleksey Mikhaylov <[email protected]>
  • Loading branch information
ttaym committed Feb 14, 2022
1 parent 25a420c commit 283bce9
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 47 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ Module.symvers
.settings
.pydevproject

# vscode project settings
.vscode

# Python compiler cache files
*.pyc

Expand Down
2 changes: 2 additions & 0 deletions fw/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ enum {
TFW_HTTP_FLAGS_REQ,
/* Sticky cookie is found and verified. */
TFW_HTTP_B_HAS_STICKY = TFW_HTTP_FLAGS_REQ,
/* Request calculated as fitting some caching by cookie rule */
TFW_HTTP_B_CACHE_CALC,
/* Request is non-idempotent. */
TFW_HTTP_B_NON_IDEMP,
/* Request stated 'Accept: text/html' header */
Expand Down
114 changes: 91 additions & 23 deletions fw/http_match.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ match_hdr_raw(const TfwHttpReq *req, const TfwHttpMatchRule *rule)
static bool
match_hdr(const TfwHttpReq *req, const TfwHttpMatchRule *rule)
{
tfw_http_hdr_t id = rule->hid;
tfw_http_hdr_t id = rule->val.hid;

BUG_ON(id < 0);
if (id == TFW_HTTP_HDR_RAW)
Expand Down Expand Up @@ -408,6 +408,12 @@ match_mark(const TfwHttpReq *req, const TfwHttpMatchRule *rule)
return mark == rule->arg.num;
}

static bool
match_cookie(const TfwHttpReq *req, const TfwHttpMatchRule *rule)
{
return true;
}

typedef bool (*match_fn)(const TfwHttpReq *, const TfwHttpMatchRule *);

static const match_fn match_fn_tbl[_TFW_HTTP_MATCH_F_COUNT] = {
Expand All @@ -417,6 +423,7 @@ static const match_fn match_fn_tbl[_TFW_HTTP_MATCH_F_COUNT] = {
[TFW_HTTP_MATCH_F_METHOD] = match_method,
[TFW_HTTP_MATCH_F_URI] = match_uri,
[TFW_HTTP_MATCH_F_MARK] = match_mark,
[TFW_HTTP_MATCH_F_COOKIE] = match_cookie,
};

/**
Expand Down Expand Up @@ -471,6 +478,7 @@ tfw_http_tbl_arg_type(tfw_http_match_fld_t field)
[TFW_HTTP_MATCH_F_METHOD] = TFW_HTTP_MATCH_A_METHOD,
[TFW_HTTP_MATCH_F_URI] = TFW_HTTP_MATCH_A_STR,
[TFW_HTTP_MATCH_F_MARK] = TFW_HTTP_MATCH_A_NUM,
[TFW_HTTP_MATCH_F_COOKIE] = TFW_HTTP_MATCH_A_STR,
};

BUG_ON(field <= 0 || field >= _TFW_HTTP_MATCH_F_COUNT);
Expand Down Expand Up @@ -599,7 +607,8 @@ tfw_http_rule_arg_init(TfwHttpMatchRule *rule, const char *arg, size_t arg_len)
rule->arg.len = arg_len;
memcpy(rule->arg.str, arg, arg_len);
if (rule->field == TFW_HTTP_MATCH_F_HDR
&& rule->hid == TFW_HTTP_HDR_RAW)
&& rule->val.type == TFW_HTTP_MATCH_V_HEADER
&& rule->val.hid == TFW_HTTP_HDR_RAW)
{
char *p = rule->arg.str;
while ((*p = tolower(*p)))
Expand All @@ -609,14 +618,37 @@ tfw_http_rule_arg_init(TfwHttpMatchRule *rule, const char *arg, size_t arg_len)
return 0;
}

static
size_t
tfw_http_escape_pre_post(char *out , const char *str)
{
int i;
size_t len = 0;
bool escaped = false;

for (i = 0; str[i]; ++i) {
if (str[i] == '*' && !escaped && (i == 0 || !str[i + 1]))
continue;
if (str[i] != '\\' || escaped) {
escaped = false;
*out = str[i];
++len;
++out;
}
else if (str[i] == '\\') {
escaped = true;
}
}

return len;
}

const char *
tfw_http_arg_adjust(const char *arg, tfw_http_match_fld_t field,
const char *raw_hdr_name, size_t *size_out,
tfw_http_match_arg_t *type_out,
tfw_http_match_op_t *op_out)
{
int i;
bool escaped;
char *arg_out, *pos;
size_t name_len = 0, full_name_len = 0, len = strlen(arg);
bool wc_arg = (arg[0] == '*' && len == 1);
Expand All @@ -631,7 +663,7 @@ tfw_http_arg_adjust(const char *arg, tfw_http_match_fld_t field,
if (wc_arg && !raw_hdr_name)
return NULL;

if (raw_hdr_name) {
if (raw_hdr_name && field != TFW_HTTP_MATCH_F_COOKIE) {
name_len = strlen(raw_hdr_name);
full_name_len = name_len + SLEN(S_DLM);
}
Expand All @@ -641,7 +673,7 @@ tfw_http_arg_adjust(const char *arg, tfw_http_match_fld_t field,
return ERR_PTR(-ENOMEM);
}

if (raw_hdr_name) {
if (raw_hdr_name && field != TFW_HTTP_MATCH_F_COOKIE) {
memcpy(arg_out, raw_hdr_name, name_len);
memcpy(arg_out + name_len, S_DLM, SLEN(S_DLM));
}
Expand Down Expand Up @@ -676,27 +708,63 @@ tfw_http_arg_adjust(const char *arg, tfw_http_match_fld_t field,
*op_out = TFW_HTTP_MATCH_O_SUFFIX;
}

len = full_name_len;
escaped = false;
pos = arg_out + full_name_len;
for (i = 0; arg[i]; ++i) {
if (arg[i] == '*' && !escaped && (i == 0 || !arg[i + 1]))
continue;
if (arg[i] != '\\' || escaped) {
escaped = false;
*pos = arg[i];
++len;
++pos;
}
else if (arg[i] == '\\') {
escaped = true;
}
}
*size_out = len + 1;
len = tfw_http_escape_pre_post(pos, arg);
*size_out += full_name_len + len + 1;

return arg_out;
}

const char *
tfw_http_val_adjust(const char *val, tfw_http_match_fld_t field,
tfw_http_match_val_t *type_out,
tfw_http_match_op_t *op_out)
{
size_t len;
char *val_out;
bool wc_val;

if (field != TFW_HTTP_MATCH_F_COOKIE) {
*type_out = TFW_HTTP_MATCH_V_HEADER;
return NULL;
}
*type_out = TFW_HTTP_MATCH_V_COOKIE;

if (!val) {
T_ERR_NL("http_tbl: cookie pattern is empty, but must be filled\n");
return ERR_PTR(-EINVAL);
}

len = strlen(val);
wc_val = (val[0] == '*' && len == 1);

if (wc_val) {
T_ERR_NL("http_tbl: cookie pattern cannot be all wildcard only\n");
return ERR_PTR(-EINVAL);
}

if (!(val_out = kzalloc(len + 1, GFP_KERNEL))) {
T_ERR_NL("http_match: unable to allocate rule field value.\n");
return ERR_PTR(-ENOMEM);
}

*op_out = TFW_HTTP_MATCH_O_EQ;
if (wc_val || (len > 1 && val[len - 1] == '*' && val[len - 2] != '\\'))
*op_out = TFW_HTTP_MATCH_O_PREFIX;
if (!wc_val && val[0] == '*') {
if (*op_out == TFW_HTTP_MATCH_O_PREFIX)
T_WARN_NL("http_match: unable to match"
" double-wildcard patterns '%s', so"
" prefix pattern will be applied\n", val);
else
*op_out = TFW_HTTP_MATCH_O_SUFFIX;
}

tfw_http_escape_pre_post(val_out, val);

return val_out;
}


int
tfw_http_verify_hdr_field(tfw_http_match_fld_t field, const char **hdr_name,
unsigned int *hid_out)
Expand Down
29 changes: 28 additions & 1 deletion fw/http_match.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,17 @@ typedef enum {
TFW_HTTP_MATCH_F_METHOD,
TFW_HTTP_MATCH_F_URI,
TFW_HTTP_MATCH_F_MARK,
TFW_HTTP_MATCH_F_COOKIE,
_TFW_HTTP_MATCH_F_COUNT
} tfw_http_match_fld_t;

typedef enum {
TFW_HTTP_MATCH_V_NA = 0,
TFW_HTTP_MATCH_V_HEADER,
TFW_HTTP_MATCH_V_COOKIE,
_TFW_HTTP_MATCH_V_COUNT
} tfw_http_match_val_t;

typedef enum {
TFW_HTTP_MATCH_O_NA = 0,
TFW_HTTP_MATCH_O_WILDCARD,
Expand Down Expand Up @@ -65,6 +73,7 @@ typedef enum {
TFW_HTTP_MATCH_ACT_VHOST,
TFW_HTTP_MATCH_ACT_MARK,
TFW_HTTP_MATCH_ACT_BLOCK,
TFW_HTTP_MATCH_ACT_FLAG,
_TFW_HTTP_MATCH_ACT_COUNT
} tfw_http_rule_act_t;

Expand All @@ -79,12 +88,27 @@ typedef struct {
};
} TfwHttpMatchArg;

typedef struct {
tfw_http_match_val_t type;
union {
unsigned int hid;
struct {
tfw_http_match_op_t op;
const char *str; /* Allocated sring, free it after */
} ptn; /* Pattern */
};
} TfwHttpMatchVal;

typedef struct {
tfw_http_rule_act_t type;
union {
TfwHttpChain *chain;
TfwVhost *vhost;
unsigned int mark;
struct {
unsigned int fid;
bool set;
} flg;
};
} TfwHttpAction;

Expand All @@ -93,7 +117,7 @@ typedef struct {
tfw_http_match_fld_t field; /* Field of a HTTP message to compare. */
tfw_http_match_op_t op; /* Comparison operator. */
TfwHttpAction act; /* Rule action. */
unsigned int hid; /* Header ID. */
TfwHttpMatchVal val; /* A field value to be compared with the arg. */
unsigned int inv; /* Comparison inversion (inequality) flag.*/
TfwHttpMatchArg arg; /* A value to be compared with the field.
note: the @arg has variable length. */
Expand Down Expand Up @@ -130,6 +154,9 @@ const char *tfw_http_arg_adjust(const char *arg, tfw_http_match_fld_t field,
const char *raw_hdr_name, size_t *size_out,
tfw_http_match_arg_t *type_out,
tfw_http_match_op_t *op_out);
const char *tfw_http_val_adjust(const char *val, tfw_http_match_fld_t field,
tfw_http_match_val_t *type_out,
tfw_http_match_op_t *op_out);
int tfw_http_verify_hdr_field(tfw_http_match_fld_t field, const char **h_name,
unsigned int *hid_out);

Expand Down
Loading

0 comments on commit 283bce9

Please sign in to comment.