Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework HTTP message forwarning #1955

Open
wants to merge 44 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
98f41a2
For plain http second skb was allocated
const-t Jun 21, 2023
3aad4e1
Rework HTTP1 response adjusting
const-t Jun 23, 2023
9d274f9
TfwMsgIter moved to TfwHttpMsg structure(SQUASH ME)
const-t Aug 15, 2023
1343cf9
Rework HTTP1 request adjusting (Part 1/2)
const-t Aug 9, 2023
3a49daa
Rework HTTP1 request adjusting (Part 2/2)
const-t Aug 15, 2023
de1a185
Fix error handling
const-t Aug 30, 2023
f9e5ba5
HTTP 1.1 method parsing
const-t Aug 31, 2023
13b2fed
Fix debug logging
const-t Aug 31, 2023
2030321
Build http message using parsed method
const-t Aug 31, 2023
3da80b8
Unified resp_hdr_add logic for HTTP2 and HTTP1
const-t Sep 7, 2023
8f9b6f2
Comments fixed
const-t Sep 7, 2023
a2ce8ad
Fixed return value for TFW_HTTP_MSG_HDR_XFRM
const-t Sep 7, 2023
a9824ef
Remove unused `TfwHttpTransIter.curr_ptr`
const-t Sep 7, 2023
b3a3384
Remove unused constants
const-t Sep 7, 2023
c8dff9e
Remove unused macro
const-t Sep 7, 2023
fc77c0f
Removed comment for AUTO_SEGS_N value not changed
const-t Sep 7, 2023
54e3429
`old_head` removed from TfwHttpReq
const-t Sep 8, 2023
4642f1e
Dynamic table unknown method processing
const-t Sep 20, 2023
d0f88ad
Fix type and identation, remove unused function
const-t Sep 21, 2023
233c380
TfwHttpMsgCleanup aligning fix
const-t Sep 22, 2023
2e8f028
Fix after rebase
const-t Sep 22, 2023
9173d91
Code cleanup
const-t May 28, 2024
3edf4a0
Remove unused functions and introduce new one
const-t May 28, 2024
b947fd7
Headers modification optimization
const-t May 31, 2024
d5fabc9
Unified resp_hdr_add logic for HTTP2 and HTTP1 fix
const-t Jun 4, 2024
9606b1b
fix commit [HTTP 1.1 method parsing]
const-t Jun 5, 2024
1032c19
fix commit [Rework HTTP1 request adjusting]
const-t Jun 5, 2024
5e6e63e
Fix header table corruption
const-t Jun 7, 2024
5b85fa9
Preserve skb mark when copy headers
const-t Jun 7, 2024
5e03141
`mark_spec_hbh`: Do not walk over headers table
const-t Jun 10, 2024
ee20bba
Host parsing
const-t Jun 18, 2024
15f2175
Review fixes:
const-t Jul 4, 2024
c0b00c7
Fix Host parsing
const-t Dec 12, 2024
090e807
Host comparison
const-t Dec 18, 2024
36fab23
Add comment about http1.1 in the request to upstream
const-t Dec 18, 2024
05780c2
Host header overriding
const-t Dec 18, 2024
b9a19b0
Add HEAD to GET overriding
const-t Dec 19, 2024
fb96939
Forward request that has empty `uri_path`
const-t Jan 15, 2025
5e59934
Prohibit empty URI host and userinfo component
const-t Jan 16, 2025
41b3f04
Don't mask error code
const-t Jan 22, 2025
137cc5c
Safe request cleanup
const-t Jan 22, 2025
aad5634
Update copyright year
const-t Jan 22, 2025
701a6b5
access_log: Write method as string
const-t Jan 23, 2025
b6372fc
Fix HEAD to GET overriding
const-t Jan 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 8 additions & 43 deletions fw/access_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
FIXED(" \"") \
UNTRUNCATABLE(vhost) \
FIXED("\" \"") \
UNTRUNCATABLE(method) \
TRUNCATABLE(method) \
FIXED(" ") \
TRUNCATABLE(uri) \
FIXED(" ") \
Expand Down Expand Up @@ -136,33 +136,6 @@ get_http_header_value(char http_version, TfwStr *line)
return result;
}


/* Helpers for const=>name conversions for http methods and versions */
static const struct {
# define MAX_HTTP_METHOD_NAME_LEN 10
char name[MAX_HTTP_METHOD_NAME_LEN];
u8 len;
} http_methods[] = {
#define STR_METHOD(name) [TFW_HTTP_METH_ ## name] = { #name, sizeof(#name) - 1 }
STR_METHOD(COPY),
STR_METHOD(DELETE),
STR_METHOD(GET),
STR_METHOD(HEAD),
STR_METHOD(LOCK),
STR_METHOD(MKCOL),
STR_METHOD(MOVE),
STR_METHOD(OPTIONS),
STR_METHOD(PATCH),
STR_METHOD(POST),
STR_METHOD(PROPFIND),
STR_METHOD(PROPPATCH),
STR_METHOD(PUT),
STR_METHOD(TRACE),
STR_METHOD(UNLOCK),
STR_METHOD(PURGE),
#undef STR_METHOD
};

static const struct {
# define MAX_HTTP_VERSION_LEN 9
char name[MAX_HTTP_VERSION_LEN];
Expand Down Expand Up @@ -405,7 +378,7 @@ do_access_log_req_dmesg(TfwHttpReq *req, int resp_status, unsigned long resp_con
{
char *buf = this_cpu_ptr(access_log_buf);
char *p = buf, *end = buf + ACCESS_LOG_BUF_SIZE;
BasicStr client_ip, vhost, method, version;
BasicStr client_ip, vhost, version;
/* These fields are only here to hold estimation of appropriate fields
* length in characters */
BasicStr status, content_length, ja5_tls, ja5_http;
Expand Down Expand Up @@ -436,18 +409,6 @@ do_access_log_req_dmesg(TfwHttpReq *req, int resp_status, unsigned long resp_con
#define ARG_vhost , (int)vhost.len, vhost.data
vhost = req->vhost && req->vhost->name.len ? req->vhost->name : missing;

/* method */
#define FMT_method "%.*s"
#define ARG_method , (int)method.len, method.data
if (req->method < sizeof(http_methods) / sizeof(*http_methods)
&& http_methods[req->method].len != 0)
{
method.data = (char *)http_methods[req->method].name;
method.len = http_methods[req->method].len;
} else {
method = missing;
}

/* http version */
#define FMT_version "%.*s"
#define ARG_version , (int)version.len, version.data
Expand Down Expand Up @@ -479,6 +440,12 @@ do_access_log_req_dmesg(TfwHttpReq *req, int resp_status, unsigned long resp_con
#define ADD_HDR(id, tfw_hdr_id) \
truncated_in[id] = get_http_header_value(req->version, \
req->h_tbl->tbl + tfw_hdr_id);

if (!TFW_MSG_H2(req))
truncated_in[idx_method] = req->h_tbl->tbl[TFW_HTTP_METHOD];
else
ADD_HDR(idx_method, TFW_HTTP_METHOD);

ADD_HDR(idx_referer, TFW_HTTP_HDR_REFERER);
ADD_HDR(idx_user_agent, TFW_HTTP_HDR_USER_AGENT);

Expand Down Expand Up @@ -538,8 +505,6 @@ do_access_log_req_dmesg(TfwHttpReq *req, int resp_status, unsigned long resp_con
#undef FMT_status
#undef ARG_version
#undef FMT_version
#undef ARG_method
#undef FMT_method
#undef ARG_vhost
#undef FMT_vhost
#undef ARG_client_ip
Expand Down
39 changes: 18 additions & 21 deletions fw/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* HTTP cache (RFC 7234).
*
* Copyright (C) 2014 NatSys Lab. ([email protected]).
* Copyright (C) 2015-2024 Tempesta Technologies, Inc.
* Copyright (C) 2015-2025 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -784,7 +784,7 @@ tfw_cache_h2_write(TDB *db, TdbVRec **trec, TfwHttpResp *resp, char **data,
TfwStr c = { 0 };
TdbVRec *tr = *trec;
TfwHttpTransIter *mit = &resp->mit;
TfwMsgIter *it = &mit->iter;
TfwMsgIter *it = &resp->iter;
int r = 0, copied = 0;

while (1) {
Expand Down Expand Up @@ -860,7 +860,7 @@ tfw_cache_set_status(TDB *db, TfwCacheEntry *ce, TfwHttpResp *resp,
TdbVRec **trec, char **p, unsigned long *acc_len)
{
int r;
TfwMsgIter *it = &resp->mit.iter;
TfwMsgIter *it = &resp->iter;
struct sk_buff **skb_head = &resp->msg.skb_head;
bool h2_mode = TFW_MSG_H2(resp->req);
TfwDecodeCacheIter dc_iter = {};
Expand Down Expand Up @@ -931,11 +931,8 @@ tfw_cache_skip_hdr(const TfwCStr *str, char *p, const TfwHdrMods *h_mods)
.len = str->name_len };

/* Fast path for special headers */
if (str->flags & TFW_CSTR_SPEC_IDX) {
desc = h_mods->spec_hdrs[str->idx];
/* Skip only resp_hdr_set headers */
return desc ? !desc->append : false;
}
if (str->flags & TFW_CSTR_SPEC_IDX)
return test_bit(str->idx, h_mods->spec_hdrs);

if (str->idx) {
unsigned short hpack_idx = str->idx;
Expand All @@ -946,13 +943,13 @@ tfw_cache_skip_hdr(const TfwCStr *str, char *p, const TfwHdrMods *h_mods)
return test_bit(hpack_idx, h_mods->s_tbl);
}

for (i = h_mods->spec_num; i < h_mods->sz; ++i) {
for (i = h_mods->scan_off; i < h_mods->set_num; ++i) {
char* mod_hdr_name;
size_t mod_hdr_len;

desc = &h_mods->hdrs[i];
mod_hdr_len = TFW_STR_CHUNK(desc->hdr, 0)->len;
if (desc->append || mod_hdr_len != hdr.len)
if (mod_hdr_len != hdr.len)
continue;

mod_hdr_name = TFW_STR_CHUNK(desc->hdr, 0)->data;
Expand Down Expand Up @@ -1053,7 +1050,7 @@ tfw_cache_send_304(TfwHttpReq *req, TfwCacheEntry *ce)
if (!(resp = tfw_http_msg_alloc_resp_light(req)))
goto err_create;

it = &resp->mit.iter;
it = &resp->iter;
skb_head = &resp->msg.skb_head;

if (!TFW_MSG_H2(req)) {
Expand Down Expand Up @@ -2798,11 +2795,12 @@ tfw_cache_add_body_page(TfwMsgIter *it, char *p, int sz, bool h2,
* to actually reserve any space for h2 frame header.
*/
static int
tfw_cache_build_resp_body(TDB *db, TdbVRec *trec, TfwMsgIter *it, char *p,
unsigned long body_sz, bool h2)
tfw_cache_build_resp_body(TDB *db, TdbVRec *trec, TfwHttpReq *req,
TfwMsgIter *it, char *p, unsigned long body_sz)
{
int r;
bool sh_frag = h2 ? false : true;
const bool h2 = TFW_MSG_H2(req);
const bool sh_frag = !h2 && TFW_CONN_TLS(req->conn);

if (WARN_ON_ONCE(!it->skb_head))
return -EINVAL;
Expand Down Expand Up @@ -2857,7 +2855,6 @@ tfw_cache_set_hdr_age(TfwHttpResp *resp, TfwCacheEntry *ce, long age)
int r;
size_t digs;
bool to_h2 = TFW_MSG_H2(resp->req);
TfwHttpTransIter *mit = &resp->mit;
struct sk_buff **skb_head = &resp->msg.skb_head;
char cstr_age[TFW_ULTOA_BUF_SIZ] = {0};
char *name = to_h2 ? "age" : "age" S_DLM;
Expand Down Expand Up @@ -2885,11 +2882,11 @@ tfw_cache_set_hdr_age(TfwHttpResp *resp, TfwCacheEntry *ce, long age)
if ((r = tfw_hpack_encode(resp, &h_age, false, false)))
goto err;
} else {
if ((r = tfw_http_msg_expand_data(&mit->iter, skb_head,
if ((r = tfw_http_msg_expand_data(&resp->iter, skb_head,
&h_age, NULL)))
goto err;

if ((r = tfw_http_msg_expand_data(&mit->iter, skb_head,
if ((r = tfw_http_msg_expand_data(&resp->iter, skb_head,
&g_crlf, NULL)))
goto err;
}
Expand Down Expand Up @@ -2977,7 +2974,7 @@ tfw_cache_build_resp(TfwHttpReq *req, TfwCacheEntry *ce, long age)
mit = &resp->mit;
skb_head = &resp->msg.skb_head;
WARN_ON_ONCE(mit->acc_len);
it = &mit->iter;
it = &resp->iter;

/*
* Set 'set-cookie' header if needed, for HTTP/2 or HTTP/1.1
Expand All @@ -3004,7 +3001,7 @@ tfw_cache_build_resp(TfwHttpReq *req, TfwCacheEntry *ce, long age)
*/
if (tfw_http_expand_hbh(resp, ce->resp_status)
|| tfw_http_expand_hdr_via(resp)
|| tfw_h1_set_loc_hdrs((TfwHttpMsg *)resp, true, true)
|| tfw_h1_add_loc_hdrs((TfwHttpMsg *)resp, h_mods, true)
|| (age > ce->lifetime
&& tfw_http_expand_stale_warn(resp))
|| (!test_bit(TFW_HTTP_B_HDR_DATE, resp->flags)
Expand Down Expand Up @@ -3052,8 +3049,8 @@ tfw_cache_build_resp(TfwHttpReq *req, TfwCacheEntry *ce, long age)
/* Fill skb with body from cache for HTTP/2 or HTTP/1.1 response. */
BUG_ON(p != TDB_PTR(db->hdr, ce->body));
if (ce->body_len && req->method != TFW_HTTP_METH_HEAD) {
if (tfw_cache_build_resp_body(db, trec, it, p, ce->body_len,
TFW_MSG_H2(req)))
if (tfw_cache_build_resp_body(db, trec, req, it, p,
ce->body_len))
goto free;
}
resp->content_length = ce->body_len;
Expand Down
30 changes: 15 additions & 15 deletions fw/hpack.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Tempesta FW
*
* Copyright (C) 2019-2024 Tempesta Technologies, Inc.
* Copyright (C) 2019-2025 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -1289,10 +1289,6 @@ tfw_hpack_hdr_set(TfwHPack *__restrict hp, TfwHttpReq *__restrict req,
* RFC 7541 6.2.1
* */
req->method = tfw_http_meth_str2id(s_hdr);
if (unlikely(req->method == _TFW_HTTP_METH_UNKNOWN)) {
WARN_ON_ONCE(1);
return -EINVAL;
}
}
parser->_hdr_tag = TFW_HTTP_HDR_H2_METHOD;
break;
Expand Down Expand Up @@ -1872,8 +1868,7 @@ tfw_hpack_cache_decode_expand(TfwHPack *__restrict hp,
unsigned int state;
int r = T_OK;
TfwStr exp_str = {};
TfwHttpTransIter *mit = &resp->mit;
TfwMsgIter *it = &mit->iter;
TfwMsgIter *it = &resp->iter;
const unsigned char *last = src + n;
unsigned char *prev = src;
struct sk_buff **skb_head = &resp->msg.skb_head;
Expand Down Expand Up @@ -3396,7 +3391,7 @@ tfw_hpack_write_idx(TfwHttpResp *__restrict resp, TfwHPackInt *__restrict idx,
bool use_pool)
{
TfwHttpTransIter *mit = &resp->mit;
TfwMsgIter *iter = &mit->iter;
TfwMsgIter *iter = &resp->iter;
struct sk_buff **skb_head = &resp->msg.skb_head;
const TfwStr s_idx = {
.data = idx->buf,
Expand All @@ -3408,7 +3403,8 @@ tfw_hpack_write_idx(TfwHttpResp *__restrict resp, TfwHPackInt *__restrict idx,
s_idx.data);

if (use_pool)
return tfw_http_msg_expand_from_pool(resp, &s_idx);
return tfw_h2_msg_expand_from_pool((TfwHttpMsg *)resp,
&s_idx, &resp->mit);

return tfw_http_msg_expand_data(iter, skb_head, &s_idx,
&mit->start_off);
Expand All @@ -3425,6 +3421,7 @@ tfw_hpack_hdr_add(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
int r;
TfwHPackInt vlen;
TfwStr s_name = {}, s_val = {}, s_vlen = {};
TfwHttpMsg *msg = (TfwHttpMsg *)resp;

if (!hdr)
return -EINVAL;
Expand All @@ -3447,14 +3444,16 @@ tfw_hpack_hdr_add(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
s_nlen.data = nlen.buf;
s_nlen.len = nlen.sz;

r = tfw_http_msg_expand_from_pool(resp, &s_nlen);
r = tfw_h2_msg_expand_from_pool(msg, &s_nlen, &resp->mit);
if (unlikely(r))
return r;

if (trans)
r = tfw_http_msg_expand_from_pool_lc(resp, &s_name);
r = tfw_h2_msg_expand_from_pool_lc(msg, &s_name,
&resp->mit);
else
r = tfw_http_msg_expand_from_pool(resp, &s_name);
r = tfw_h2_msg_expand_from_pool(msg, &s_name,
&resp->mit);
if (unlikely(r))
return r;
}
Expand All @@ -3463,12 +3462,12 @@ tfw_hpack_hdr_add(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
s_vlen.data = vlen.buf;
s_vlen.len = vlen.sz;

r = tfw_http_msg_expand_from_pool(resp, &s_vlen);
r = tfw_h2_msg_expand_from_pool(msg, &s_vlen, &resp->mit);

if (unlikely(r))
return r;
if (!TFW_STR_EMPTY(&s_val))
r = tfw_http_msg_expand_from_pool(resp, &s_val);
r = tfw_h2_msg_expand_from_pool(msg, &s_val, &resp->mit);

return r;
}
Expand All @@ -3484,7 +3483,7 @@ tfw_hpack_hdr_expand(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
int ret;
TfwStr *c, *end;
TfwHttpTransIter *mit = &resp->mit;
TfwMsgIter *iter = &mit->iter;
TfwMsgIter *iter = &resp->iter;
struct sk_buff **skb_head = &resp->msg.skb_head;
TfwStr s_val;

Expand Down Expand Up @@ -3630,6 +3629,7 @@ __tfw_hpack_encode(TfwHttpResp *__restrict resp, TfwStr *__restrict hdr,
r = tfw_hpack_hdr_add(resp, hdr, &idx, name_indexed, trans);
else
r = tfw_hpack_hdr_expand(resp, hdr, &idx, name_indexed);

return r;
}

Expand Down
Loading