Skip to content

Commit

Permalink
Add HTTP tables processing (#731).
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksostapenko committed May 15, 2018
1 parent b3a9f98 commit 126ed95
Show file tree
Hide file tree
Showing 13 changed files with 864 additions and 567 deletions.
29 changes: 17 additions & 12 deletions tempesta_fw/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@ entry_set_name(TfwCfgEntry *e)
BUG_ON(!e);
BUG_ON(e->name);

TFW_WARN_NL("TEST10!!! 'entry_set_name()' -> e->name = '%s', e->ftoken = '%s'\n", e->name, e->ftoken);
if (!rule) {
name = e->ftoken;
len = strlen(e->ftoken);
Expand Down Expand Up @@ -702,8 +701,6 @@ entry_set_cond(TfwCfgEntry *e, token_t cond_type, const char *src, int len)
BUG_ON(!e->ftoken);
BUG_ON(e->name);

TFW_WARN_NL("TEST7!!! 'parse_cfg_entry()' -> PS_RULE_COND, (must be 4 or 5) ps->prev_t = '%d'\n", cond_type);

TFW_DBG3("set entry rule name '%.*s', 1st operand '%.*s', 2nd operand"
" '%.*s', and condition type '%d'\n", name_len, name,
(int)strlen(e->ftoken), e->ftoken, len, src, cond_type);
Expand All @@ -720,9 +717,7 @@ entry_set_cond(TfwCfgEntry *e, token_t cond_type, const char *src, int len)
if (!(e->name = alloc_and_copy_literal(name, name_len)))
return -ENOMEM;

rule->type = cond_type == TOKEN_DEQSIGN
? TFW_CFG_COND_EQUAL
: TFW_CFG_COND_NONEQUAL;
rule->inv = cond_type == TOKEN_DEQSIGN ? false : true;
return 0;
}

Expand Down Expand Up @@ -763,11 +758,21 @@ parse_cfg_entry(TfwCfgParserState *ps)

/* Every _PFSM_MOVE() invokes _read_next_token(), so when we enter
* any state, we get a new token automatically.
* So:
* name key = value;
* ^
* current literal is here; we need to store it as the name.
*///!!! change comment
* Three different situations may occur here:
* 1. In case of plain directive parsing:
* name key = value;
* ^
* 2. In case of rule parsing:
* key == (!=) value -> action [= val]
* ^
* 3. In case of parsing of pure action rule:
* -> action [= val]
* ^
* current token is here; so at first we need to differentiate third
* situation, and in first two ones - save first token in special location
* to decide later whether use it as name for plain directive or as
* condition key for rule; in last two cases predefined rule name is used.
*/
FSM_STATE(PS_START_NEW_ENTRY) {
entry_reset(&ps->e);
ps->e.line_no = ps->line_no;
Expand Down Expand Up @@ -830,7 +835,7 @@ parse_cfg_entry(TfwCfgParserState *ps)
read_next_token(ps);
PFSM_COND_JMP_EXIT_ERROR(ps->t != TOKEN_SEMICOLON);
FSM_JMP(PS_SEMICOLON);
}//!!! comments in rule states
}

/*
* Now we have a situation where at current position we don't know
Expand Down
55 changes: 38 additions & 17 deletions tempesta_fw/cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,6 @@
#define TFW_CFG_ENTRY_VAL_MAX 16
#define TFW_CFG_ENTRY_ATTR_MAX 16

typedef enum {
TFW_CFG_COND_EQUAL = 0,
TFW_CFG_COND_NONEQUAL
} tfw_cfg_cond_t;

//!!! comment
typedef struct {
tfw_cfg_cond_t type;
const char *fst;
const char *snd;
const char *act;
const char *val;
} TfwCfgRule;

#define TFW_CFG_RULE_NAME "rule"

/**
Expand Down Expand Up @@ -100,16 +86,51 @@ typedef struct {
* Both sections and directives are expressed by TfwCfgEntry{} structure.
* The difference is in @have_children flag which is true for sections.
*
* This is a temporary structure that lives only during the parsing and
* acts as an interface between the parser FSM and TfwCfgSpec{}->handler.
* TfwCfgEntry{} structure also supports an alternative way to specify
* directives - in form of rules; structure TfwCfgRule{} (and field @rule
* of TfwCfgEntry{} structure) is responsible for rules parsing. The
* following rule:
* uri != "static*" -> mark = 1;
*
* if parsed, will have following representaion in TfwCfgEntry{}:
* TfwCfgEntry {
* .name = "rule",
* ...
* .rule = {
* .fst = "uri",
* .snd = "static*",
* .act = "mark",
* .val = "1",
* .inv = true
* },
* ...
* }
*
* In above example @inv field of TfwCfgRule{} structure is responsible for
* comparison sign interpretation in rule condition part:
* "==" => false / "!=" => true
*
* @ftoken is an auxiliary internal field of TfwCfgEntry{} structure which
* helps parser to differentiate plain directives from rules.
*
* TfwCfgEntry{} is a temporary structure that lives only during the parsing
* and acts as an interface between the parser FSM and TfwCfgSpec{}->handler.
* The parser accumulates data in a TfwCfgEntry{} instance. When the
* current entry is complete, the parser executes the handler and then
* destroys the instance.
*
* These two members help to show a proper parsing error to a user:
* @line_no - Current line number in the configuration file.
* @line - Pointer to the start of the current line.
*///!!! add comment about @rule and @ftoken;
*/
typedef struct {
const char *fst;
const char *snd;
const char *act;
const char *val;
bool inv;
} TfwCfgRule;

typedef struct {
struct {
bool have_children : 1;
Expand Down
43 changes: 27 additions & 16 deletions tempesta_fw/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -1899,13 +1899,6 @@ tfw_http_msg_create_sibling(TfwHttpMsg *hm, struct sk_buff **skb,
return NULL;
}

/*
* New message created, so it should be in whitelist if
* previous message was (for client connections).
*/
if (TFW_CONN_TYPE(hm->conn) & Conn_Clnt)
shm->flags |= hm->flags & TFW_HTTP_F_WHITELIST;

/*
* The sibling message is set up to start with a new SKB.
* The new SKB is split off from the original SKB and has
Expand All @@ -1917,6 +1910,17 @@ tfw_http_msg_create_sibling(TfwHttpMsg *hm, struct sk_buff **skb,
tfw_http_conn_msg_free(shm);
return NULL;
}

/*
* New message created, so it should be in whitelist if
* previous message was (for client connections). Also
* we have new skb here and 'mark' propagation is needed.
*/
if (TFW_CONN_TYPE(hm->conn) & Conn_Clnt) {
shm->flags |= hm->flags & TFW_HTTP_F_WHITELIST;
nskb->mark = (*skb)->mark;
}

ss_skb_queue_tail(&shm->msg.skb_head, nskb);
*skb = nskb;

Expand Down Expand Up @@ -2596,12 +2600,23 @@ tfw_http_req_add_seq_queue(TfwHttpReq *req)
static int
tfw_http_req_set_context(TfwHttpReq *req)
{
if (!(req->vhost = tfw_vhost_match((TfwMsg *)req)))
return -EINVAL;
bool block = false;

if ((req->vhost = tfw_sched_get_vhost((TfwMsg *)req, &block))) {
req->location = tfw_location_match(req->vhost, &req->uri_path);
return 0;
}
if (block) {
TFW_INC_STAT_BH(clnt.msgs_filtout);
tfw_client_block(req, 500, "request has been filtered out"
" via http table");
} else {
TFW_INC_STAT_BH(clnt.msgs_otherr);
tfw_client_drop(req, 500, "cannot find vhost for request");
}
return -EINVAL;

req->location = tfw_location_match(req->vhost, &req->uri_path);

return 0;
}

static inline bool
Expand Down Expand Up @@ -2739,12 +2754,8 @@ tfw_http_req_process(TfwConn *conn, const TfwFsmData *data)
}

/* Assign the right Vhost for this request. */
if (tfw_http_req_set_context(req)) {
TFW_INC_STAT_BH(clnt.msgs_otherr);
tfw_client_drop(req, 500, "cannot find"
"Vhost for request");
if (tfw_http_req_set_context(req))
return TFW_BLOCK;
}

r = tfw_gfsm_move(&conn->state, TFW_HTTP_FSM_REQ_MSG, &data_up);
TFW_DBG3("TFW_HTTP_FSM_REQ_MSG return code %d\n", r);
Expand Down
Loading

0 comments on commit 126ed95

Please sign in to comment.