Skip to content

Commit

Permalink
Merge pull request #1200 from tempesta-tech/ik-fix-frang-errors
Browse files Browse the repository at this point in the history
Fix farious frang errors
  • Loading branch information
vankoven authored Aug 1, 2019
2 parents 9913589 + 140f5dd commit 18f852d
Show file tree
Hide file tree
Showing 16 changed files with 1,350 additions and 786 deletions.
9 changes: 8 additions & 1 deletion etc/tempesta_fw.conf
Original file line number Diff line number Diff line change
Expand Up @@ -921,10 +921,14 @@

# TAG: frang_limits
#
# The section containing static limits for the classifier.
# The section containing static limits for the classifier. Can appear at top
# level, inside 'vhost' directive, inside 'location' directive. Once the
# directive is listed in the configuration it redefines default values for the
# following and nested sections of 'vhost' and 'location' directives.
#
# Syntax:
# frang_limits {
# ip_block off|on;
# request_rate NUM;
# request_burst NUM;
# connection_rate NUM;
Expand All @@ -935,6 +939,9 @@
# http_uri_len NUM;
# http_field_len NUM;
# http_body_len NUM;
# http_header_cnt NUM;
# http_header_chunk_cnt NUM;
# http_body_chunk_cnt NUM;
# http_host_required true|false;
# http_methods [METHOD]...;
# http_ct_required true|false;
Expand Down
45 changes: 45 additions & 0 deletions tempesta_fw/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,16 @@ tfw_cfg_parse_int(const char *s, int *out_int)
}
EXPORT_SYMBOL(tfw_cfg_parse_int);

int
tfw_cfg_parse_long(const char *s, long *out_long)
{
int base = detect_base(&s);
if (!base)
return -EINVAL;
return kstrtol(s, base, out_long);
}
EXPORT_SYMBOL(tfw_cfg_parse_long);

int
tfw_cfg_parse_uint(const char *s, unsigned int *out_uint)
{
Expand Down Expand Up @@ -1661,6 +1671,41 @@ tfw_cfg_set_int(TfwCfgSpec *cs, TfwCfgEntry *e)
}
EXPORT_SYMBOL(tfw_cfg_set_int);

int
tfw_cfg_set_long(TfwCfgSpec *cs, TfwCfgEntry *e)
{
int r;
long val, *dest_long;
TfwCfgSpecInt *cse;

BUG_ON(!cs->dest);

if ((r = tfw_cfg_check_single_val(e)))
goto err;

r = tfw_cfg_parse_long(e->vals[0], &val);
if (r)
goto err;

/* Check value restrictions if we have any in the spec extension. */
cse = cs->spec_ext;
if (cse) {
r = tfw_cfg_check_multiple_of(val, cse->multiple_of);
r |= tfw_cfg_check_range(val, cse->range.min, cse->range.max);
if (r)
goto err;
}

dest_long = cs->dest;
*dest_long = val;
return 0;

err:
TFW_ERR_NL("can't parse long integer");
return -EINVAL;
}
EXPORT_SYMBOL(tfw_cfg_set_long);

static void
tfw_cfg_cleanup_str(TfwCfgSpec *cs)
{
Expand Down
2 changes: 2 additions & 0 deletions tempesta_fw/cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ enum {
/* Generic TfwCfgSpec->handler functions. */
int tfw_cfg_set_bool(TfwCfgSpec *self, TfwCfgEntry *parsed_entry);
int tfw_cfg_set_int(TfwCfgSpec *spec, TfwCfgEntry *parsed_entry);
int tfw_cfg_set_long(TfwCfgSpec *spec, TfwCfgEntry *parsed_entry);
int tfw_cfg_set_str(TfwCfgSpec *spec, TfwCfgEntry *parsed_entry);
int tfw_cfg_handle_children(TfwCfgSpec *self, TfwCfgEntry *parsed_entry);
void tfw_cfg_cleanup_children(TfwCfgSpec *cs);
Expand All @@ -414,6 +415,7 @@ int tfw_cfg_check_multiple_of(long value, int divisor);
int tfw_cfg_check_val_n(const TfwCfgEntry *e, int val_n);
int tfw_cfg_check_single_val(const TfwCfgEntry *e);
int tfw_cfg_parse_int(const char *s, int *out_int);
int tfw_cfg_parse_long(const char *s, long *out_long);
int tfw_cfg_parse_uint(const char *s, unsigned int *out_uint);
int tfw_cfg_parse_intvl(const char *s, unsigned long *i0, unsigned long *i1);
int tfw_cfg_map_enum(const TfwCfgEnum mappings[],
Expand Down
1 change: 1 addition & 0 deletions tempesta_fw/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ int tfw_client_for_each(int (*fn)(void *));
void tfw_client_set_expires_time(unsigned int expires_time);
void tfw_cli_conn_release(TfwCliConn *cli_conn);
int tfw_cli_conn_send(TfwCliConn *cli_conn, TfwMsg *msg);
int tfw_cli_conn_close_all_sync(TfwClient *cli);

#endif /* __TFW_CLIENT_H__ */
45 changes: 45 additions & 0 deletions tempesta_fw/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -3213,6 +3213,28 @@ tfw_http_req_process(TfwConn *conn, const TfwFsmData *data)
*
* In the same time location may differ between requests, so the
* sticky module can't fill it.
*
* TODO:
* There are multiple ways to get target vhost:
* - search in HTTP chains (defined in the configuration by admin),
* very slow on big configurations;
* - get vhost from the HTTP session information (by Sticky cookie);
* - get Vhost according to TLS SNI header parsing.
* But vhost returned from all that functions can be very different
* depending on HTTP chain configuration due to its flexibility and
* client (attacker) behaviour.
* The most secure and slow way: compare all of them and reject if
* at least some do not match. Can be too strict, service quality can
* be degraded.
* The fastest way: compute as minimum as possible: use TLS first
* (anyway we use it to send right certificate), then cookie, then HTTP
* chain. There can be possibility that a request will be forwarded to
* a wrong server. May happen when a single certificate is used to
* speak with multiple vhosts (multi-domain (SAN) certificate as
* globally default TLS certificate in Tempesta config file).
* The most reliable way: use the highest OSI level vhost: by HTTP
* session, if no -> by http chain, if no -> by TLS conn.
*
*/
if (!req->vhost) {
req->vhost = tfw_http_tbl_vhost((TfwMsg *)req, &block);
Expand Down Expand Up @@ -3958,6 +3980,7 @@ tfw_http_hm_srv_send(TfwServer *srv, char *data, unsigned long len)
.len = len,
};
LIST_HEAD(equeue);
bool block = false;

if (!(req = tfw_http_msg_alloc_req_light()))
return;
Expand All @@ -3970,6 +3993,28 @@ tfw_http_hm_srv_send(TfwServer *srv, char *data, unsigned long len)
__set_bit(TFW_HTTP_B_HMONITOR, req->flags);
req->jrxtstamp = jiffies;

/*
* Vhost and location store policies definitions that can be
* required on various stages of request-response processing.
* E.g. response to HM request still needs to be processed by frang,
* and vhost keeps the frang configuration.
*
* The request is created using lightweight function, req->uri_path
* is not set, thus default location is used.
*
* TBD: it's more natural to configure HM not in server group section,
* but in vhost: instead of table lookups target vhost could be chosen
* directly.
*/
req->vhost = tfw_http_tbl_vhost((TfwMsg *)req, &block);
if (unlikely(!req->vhost || block)) {
TFW_WARN_ADDR("Unable to assign vhost for health monitoring "
"request of backend server", &srv->addr,
TFW_WITH_PORT);
goto cleanup;
}
req->location = req->vhost->loc_dflt;

srv_conn = srv->sg->sched->sched_srv_conn((TfwMsg *)req, srv);
if (!srv_conn) {
TFW_WARN_ADDR("Unable to find connection for health"
Expand Down
4 changes: 4 additions & 0 deletions tempesta_fw/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ enum {
TFW_HTTP_B_CONN_EXTRA,
/* Chunked transfer encoding. */
TFW_HTTP_B_CHUNKED,
/* Message has chunked trailer headers part. */
TFW_HTTP_B_CHUNKED_TRAILER,
/* The message body is limited by the connection closing. */
TFW_HTTP_B_UNLIMITED,
/* Media type is multipart/form-data. */
Expand All @@ -238,6 +240,8 @@ enum {
TFW_HTTP_B_CT_MULTIPART_HAS_BOUNDARY,
/* Singular header presents more than once. */
TFW_HTTP_B_FIELD_DUPENTRY,
/* Message is fully parsed */
TFW_HTTP_B_FULLY_PARSED,

/* Request flags. */
TFW_HTTP_FLAGS_REQ,
Expand Down
Loading

0 comments on commit 18f852d

Please sign in to comment.