aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extras/hs-test/http_test.go23
-rw-r--r--src/plugins/http_static/http_static.api38
-rw-r--r--src/plugins/http_static/http_static.c29
-rw-r--r--src/plugins/http_static/http_static.h3
-rw-r--r--src/plugins/http_static/http_static_test.c98
-rw-r--r--src/plugins/http_static/static_server.c27
6 files changed, 208 insertions, 10 deletions
diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go
index 4cbcdeb1b21..68934550b69 100644
--- a/extras/hs-test/http_test.go
+++ b/extras/hs-test/http_test.go
@@ -36,7 +36,7 @@ func init() {
HttpClientErrRespTest, HttpClientPostFormTest, HttpClientGet128kbResponseTest, HttpClientGetResponseBodyTest,
HttpClientGetNoResponseBodyTest, HttpClientPostFileTest, HttpClientPostFilePtrTest, HttpUnitTest,
HttpRequestLineTest, HttpClientGetTimeout, HttpStaticFileHandlerWrkTest, HttpStaticUrlHandlerWrkTest, HttpConnTimeoutTest,
- HttpClientGetRepeat, HttpClientPostRepeat, HttpIgnoreH2UpgradeTest, HttpInvalidAuthorityFormUriTest)
+ HttpClientGetRepeat, HttpClientPostRepeat, HttpIgnoreH2UpgradeTest, HttpInvalidAuthorityFormUriTest, HttpHeaderErrorConnectionDropTest)
RegisterNoTopoSoloTests(HttpStaticPromTest, HttpGetTpsTest, HttpGetTpsInterruptModeTest, PromConcurrentConnectionsTest,
PromMemLeakTest, HttpClientPostMemLeakTest, HttpInvalidClientRequestMemLeakTest, HttpPostTpsTest, HttpPostTpsInterruptModeTest,
PromConsecutiveConnectionsTest, HttpGetTpsTlsTest, HttpPostTpsTlsTest)
@@ -1240,7 +1240,7 @@ func HttpInvalidContentLengthTest(s *NoTopoSuite) {
func HttpContentLengthTest(s *NoTopoSuite) {
vpp := s.Containers.Vpp.VppInstance
serverAddress := s.VppAddr()
- s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
+ s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug max-body-size 12"))
ifName := s.VppIfName()
resp, err := TcpSendReceive(serverAddress+":80",
@@ -1259,6 +1259,25 @@ func HttpContentLengthTest(s *NoTopoSuite) {
validatePostInterfaceStats(s, resp)
}
+func HttpHeaderErrorConnectionDropTest(s *NoTopoSuite) {
+ vpp := s.Containers.Vpp.VppInstance
+ serverAddress := s.VppAddr()
+ s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug max-body-size 12"))
+ request := "POST /interface_stats.json HTTP/1.1\r\nContent-Length: 18234234\r\n\r\n" + s.VppIfName()
+ conn, err := net.DialTimeout("tcp", serverAddress+":80", time.Second*30)
+ s.AssertNil(err, fmt.Sprint(err))
+ err = conn.SetDeadline(time.Now().Add(time.Second * 10))
+ s.AssertNil(err, fmt.Sprint(err))
+ _, err = conn.Write([]byte(request))
+ s.AssertNil(err, fmt.Sprint(err))
+ reply := make([]byte, 1024)
+ _, err = conn.Read(reply)
+ s.AssertNil(err, fmt.Sprint(err))
+ s.AssertContains(string(reply), "HTTP/1.1 413 Content Too Large")
+ check := make([]byte, 1)
+ _, err = conn.Read(check)
+ s.AssertEqual(err, io.EOF)
+}
func HttpMethodNotImplementedTest(s *NoTopoSuite) {
vpp := s.Containers.Vpp.VppInstance
serverAddress := s.VppAddr()
diff --git a/src/plugins/http_static/http_static.api b/src/plugins/http_static/http_static.api
index 60c0369848d..bd0cebc45d2 100644
--- a/src/plugins/http_static/http_static.api
+++ b/src/plugins/http_static/http_static.api
@@ -3,7 +3,7 @@
This file defines static http server control-plane API messages
*/
-option version = "2.3.0";
+option version = "2.4.0";
/** \brief Configure and enable the static http server
@param client_index - opaque cookie to identify the sender
@@ -74,3 +74,39 @@ autoreply define http_static_enable_v3 {
/* The bind URI */
string uri[256];
};
+
+/** \brief Configure and enable the static http server
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param fifo_size - size (in bytes) of the session FIFOs
+ @param cache_size_limit - size (in bytes) of the in-memory file data cache
+ @param max_age - how long a response is considered fresh (in seconds)
+ @param max_body_size - maximum size of a request body (in bytes)
+ @param keepalive_timeout - timeout during which client connection will stay open (in seconds)
+ @param prealloc_fifos - number of preallocated fifos (usually 0)
+ @param private_segment_size - fifo segment size (usually 0)
+ @param www_root - html root path
+ @param uri - bind URI, defaults to "tcp://0.0.0.0/80"
+*/
+
+autoreply define http_static_enable_v4 {
+ /* Client identifier, set from api_main.my_client_index */
+ u32 client_index;
+
+ /* Arbitrary context, so client can match reply to request */
+ u32 context;
+ /* Typical options */
+ u32 fifo_size;
+ u32 cache_size_limit;
+ u32 max_age [default=600];
+ u32 keepalive_timeout [default=60];
+ u64 max_body_size [default=8000];
+ /* Unusual options */
+ u32 prealloc_fifos;
+ u32 private_segment_size;
+
+ /* Root of the html path */
+ string www_root[256];
+ /* The bind URI */
+ string uri[256];
+};
diff --git a/src/plugins/http_static/http_static.c b/src/plugins/http_static/http_static.c
index 464fd27e90d..7a12f37b8d3 100644
--- a/src/plugins/http_static/http_static.c
+++ b/src/plugins/http_static/http_static.c
@@ -67,7 +67,7 @@ hss_register_url_handler (hss_url_handler_fn fp, const char *url,
static int
hss_enable_api (u32 fifo_size, u32 cache_limit, u32 prealloc_fifos,
u32 private_segment_size, u8 *www_root, u8 *uri, u32 max_age,
- u32 keepalive_timeout)
+ u32 keepalive_timeout, u64 max_body_size)
{
hss_main_t *hsm = &hss_main;
int rv;
@@ -79,6 +79,7 @@ hss_enable_api (u32 fifo_size, u32 cache_limit, u32 prealloc_fifos,
hsm->www_root = format (0, "%s%c", www_root, 0);
hsm->uri = format (0, "%s%c", uri, 0);
hsm->max_age = max_age;
+ hsm->max_body_size = max_body_size;
hsm->keepalive_timeout = keepalive_timeout;
if (vec_len (hsm->www_root) < 2)
@@ -119,7 +120,8 @@ vl_api_http_static_enable_v2_t_handler (vl_api_http_static_enable_v2_t *mp)
rv = hss_enable_api (ntohl (mp->fifo_size), ntohl (mp->cache_size_limit),
ntohl (mp->prealloc_fifos),
ntohl (mp->private_segment_size), mp->www_root, mp->uri,
- ntohl (mp->max_age), HSS_DEFAULT_KEEPALIVE_TIMEOUT);
+ ntohl (mp->max_age), HSS_DEFAULT_KEEPALIVE_TIMEOUT,
+ HSS_DEFAULT_MAX_BODY_SIZE);
REPLY_MACRO (VL_API_HTTP_STATIC_ENABLE_V2_REPLY);
}
@@ -138,11 +140,32 @@ vl_api_http_static_enable_v3_t_handler (vl_api_http_static_enable_v3_t *mp)
rv = hss_enable_api (ntohl (mp->fifo_size), ntohl (mp->cache_size_limit),
ntohl (mp->prealloc_fifos),
ntohl (mp->private_segment_size), mp->www_root, mp->uri,
- ntohl (mp->max_age), ntohl (mp->keepalive_timeout));
+ ntohl (mp->max_age), ntohl (mp->keepalive_timeout),
+ HSS_DEFAULT_MAX_BODY_SIZE);
REPLY_MACRO (VL_API_HTTP_STATIC_ENABLE_V3_REPLY);
}
+/* API message handler */
+static void
+vl_api_http_static_enable_v4_t_handler (vl_api_http_static_enable_v4_t *mp)
+{
+ vl_api_http_static_enable_v4_reply_t *rmp;
+ hss_main_t *hsm = &hss_main;
+ int rv;
+
+ mp->uri[ARRAY_LEN (mp->uri) - 1] = 0;
+ mp->www_root[ARRAY_LEN (mp->www_root) - 1] = 0;
+
+ rv = hss_enable_api (ntohl (mp->fifo_size), ntohl (mp->cache_size_limit),
+ ntohl (mp->prealloc_fifos),
+ ntohl (mp->private_segment_size), mp->www_root, mp->uri,
+ ntohl (mp->max_age), ntohl (mp->keepalive_timeout),
+ ntohl (mp->max_body_size));
+
+ REPLY_MACRO (VL_API_HTTP_STATIC_ENABLE_V4_REPLY);
+}
+
#include <http_static/http_static.api.c>
static clib_error_t *
hss_api_init (vlib_main_t *vm)
diff --git a/src/plugins/http_static/http_static.h b/src/plugins/http_static/http_static.h
index 88b0002c971..e158a32dbc9 100644
--- a/src/plugins/http_static/http_static.h
+++ b/src/plugins/http_static/http_static.h
@@ -24,6 +24,7 @@
#include <http_static/http_cache.h>
#define HSS_DEFAULT_MAX_AGE 600
+#define HSS_DEFAULT_MAX_BODY_SIZE 8192
#define HSS_DEFAULT_KEEPALIVE_TIMEOUT 60
/** @file http_static.h
@@ -161,6 +162,8 @@ typedef struct
u64 cache_size;
/** How long a response is considered fresh (in seconds) */
u32 max_age;
+ /** Maximum size of a request body (in bytes) **/
+ u64 max_body_size;
/** Formatted max_age: "max-age=xyz" */
u8 *max_age_formatted;
/** Timeout during which client connection will stay open */
diff --git a/src/plugins/http_static/http_static_test.c b/src/plugins/http_static/http_static_test.c
index edb016f9e05..56487893220 100644
--- a/src/plugins/http_static/http_static_test.c
+++ b/src/plugins/http_static/http_static_test.c
@@ -214,6 +214,104 @@ api_http_static_enable_v3 (vat_main_t *vam)
mp->private_segment_size = ntohl (private_segment_size);
mp->max_age = ntohl (max_age);
mp->keepalive_timeout = ntohl (keepalive_timeout);
+ /* send it... */
+ S (mp);
+
+ /* Wait for a reply... */
+ W (ret);
+ return ret;
+}
+
+static int
+api_http_static_enable_v4 (vat_main_t *vam)
+{
+ unformat_input_t *line_input = vam->input;
+ vl_api_http_static_enable_v4_t *mp;
+ u64 tmp;
+ u8 *www_root = 0;
+ u8 *uri = 0;
+ u32 prealloc_fifos = 0;
+ u32 private_segment_size = 0;
+ u32 fifo_size = 8 << 10;
+ u32 cache_size_limit = 1 << 20;
+ u32 max_age = HSS_DEFAULT_MAX_AGE;
+ u32 keepalive_timeout = HSS_DEFAULT_KEEPALIVE_TIMEOUT;
+ u64 max_body_size = HSS_DEFAULT_MAX_BODY_SIZE;
+ int ret;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "www-root %s", &www_root))
+ ;
+ else if (unformat (line_input, "prealloc-fifos %d", &prealloc_fifos))
+ ;
+ else if (unformat (line_input, "private-segment-size %U",
+ unformat_memory_size, &tmp))
+ {
+ if (tmp >= 0x100000000ULL)
+ {
+ errmsg ("private segment size %llu, too large", tmp);
+ return -99;
+ }
+ private_segment_size = (u32) tmp;
+ }
+ else if (unformat (line_input, "fifo-size %U", unformat_memory_size,
+ &tmp))
+ {
+ if (tmp >= 0x100000000ULL)
+ {
+ errmsg ("fifo-size %llu, too large", tmp);
+ return -99;
+ }
+ fifo_size = (u32) tmp;
+ }
+ else if (unformat (line_input, "cache-size %U", unformat_memory_size,
+ &tmp))
+ {
+ if (tmp < (128ULL << 10))
+ {
+ errmsg ("cache-size must be at least 128kb");
+ return -99;
+ }
+ cache_size_limit = (u32) tmp;
+ }
+ else if (unformat (line_input, "max-age %d", &max_age))
+ ;
+ else if (unformat (line_input, "keepalive-timeout %d",
+ &keepalive_timeout))
+ ;
+ else if (unformat (line_input, "uri %s", &uri))
+ ;
+ else if (unformat (line_input, "max-body-size %llu", &max_body_size))
+ ;
+ else
+ {
+ errmsg ("unknown input `%U'", format_unformat_error, line_input);
+ return -99;
+ }
+ }
+
+ if (www_root == 0)
+ {
+ errmsg ("Must specify www-root");
+ return -99;
+ }
+
+ if (uri == 0)
+ uri = format (0, "tcp://0.0.0.0/80%c", 0);
+
+ /* Construct the API message */
+ M (HTTP_STATIC_ENABLE_V4, mp);
+ strncpy_s ((char *) mp->www_root, 256, (const char *) www_root, 256);
+ strncpy_s ((char *) mp->uri, 256, (const char *) uri, 256);
+ mp->fifo_size = ntohl (fifo_size);
+ mp->cache_size_limit = ntohl (cache_size_limit);
+ mp->prealloc_fifos = ntohl (prealloc_fifos);
+ mp->private_segment_size = ntohl (private_segment_size);
+ mp->max_age = ntohl (max_age);
+ mp->keepalive_timeout = ntohl (keepalive_timeout);
+ mp->max_body_size = ntohl (max_body_size);
/* send it... */
S (mp);
diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c
index 7c8c65bb9bd..074416873e3 100644
--- a/src/plugins/http_static/static_server.c
+++ b/src/plugins/http_static/static_server.c
@@ -500,6 +500,7 @@ handle_request (hss_session_t *hs, http_req_method_t rt, u8 *target_path,
static int
hss_ts_rx_callback (session_t *ts)
{
+ hss_main_t *hsm = &hss_main;
hss_session_t *hs;
u8 *target_path = 0, *target_query = 0, *data = 0;
http_msg_t msg;
@@ -522,7 +523,7 @@ hss_ts_rx_callback (session_t *ts)
http_add_header (&hs->resp_headers, HTTP_HEADER_ALLOW,
http_token_lit ("GET, POST"));
start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED);
- goto done;
+ goto err_done;
}
/* Read target path */
@@ -535,7 +536,7 @@ hss_ts_rx_callback (session_t *ts)
if (http_validate_abs_path_syntax (target_path, 0))
{
start_send_data (hs, HTTP_STATUS_BAD_REQUEST);
- goto done;
+ goto err_done;
}
/* Target path must be a proper C-string in addition to a vector */
vec_add1 (target_path, 0);
@@ -551,13 +552,24 @@ hss_ts_rx_callback (session_t *ts)
if (http_validate_query_syntax (target_query, 0))
{
start_send_data (hs, HTTP_STATUS_BAD_REQUEST);
- goto done;
+ goto err_done;
}
}
/* Read request body for POST requests */
if (msg.data.body_len && msg.method_type == HTTP_REQ_POST)
{
+ if (msg.data.body_len > hsm->max_body_size)
+ {
+ start_send_data (hs, HTTP_STATUS_CONTENT_TOO_LARGE);
+ goto err_done;
+ }
+ if (svm_fifo_max_dequeue (ts->rx_fifo) - msg.data.body_offset <
+ msg.data.body_len)
+ {
+ start_send_data (hs, HTTP_STATUS_INTERNAL_ERROR);
+ goto err_done;
+ }
vec_validate (data, msg.data.body_len - 1);
rv = svm_fifo_peek (ts->rx_fifo, msg.data.body_offset, msg.data.body_len,
data);
@@ -566,7 +578,10 @@ hss_ts_rx_callback (session_t *ts)
/* Find and send data */
handle_request (hs, msg.method_type, target_path, target_query, data);
+ goto done;
+err_done:
+ hss_session_disconnect_transport (hs);
done:
vec_free (target_path);
vec_free (target_query);
@@ -879,6 +894,7 @@ hss_create_command_fn (vlib_main_t *vm, unformat_input_t *input,
hsm->fifo_size = 0;
hsm->cache_size = 10 << 20;
hsm->max_age = HSS_DEFAULT_MAX_AGE;
+ hsm->max_body_size = HSS_DEFAULT_MAX_BODY_SIZE;
hsm->keepalive_timeout = HSS_DEFAULT_KEEPALIVE_TIMEOUT;
/* Get a line of input. */
@@ -916,6 +932,9 @@ hss_create_command_fn (vlib_main_t *vm, unformat_input_t *input,
hsm->enable_url_handlers = 1;
else if (unformat (line_input, "max-age %d", &hsm->max_age))
;
+ else if (unformat (line_input, "max-body-size %U", unformat_memory_size,
+ &hsm->max_body_size))
+ ;
else
{
error = clib_error_return (0, "unknown input `%U'",
@@ -979,7 +998,7 @@ VLIB_CLI_COMMAND (hss_create_command, static) = {
"http static server www-root <path> [prealloc-fifos <nn>]\n"
"[private-segment-size <nnMG>] [fifo-size <nbytes>] [max-age <nseconds>]\n"
"[uri <uri>] [ptr-thresh <nn>] [url-handlers] [debug [nn]]\n"
- "[keepalive-timeout <nn>]\n",
+ "[keepalive-timeout <nn>] [max-body-size <nn>]\n",
.function = hss_create_command_fn,
};