From 6b2c1293a67aef19d029db9b2816544da6193522 Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Wed, 11 Jun 2025 07:27:54 -0400 Subject: [PATCH] http_static: use authority in redirects Use authority in redirects instead of IP address of the listener. Type: improvement Change-Id: Id6dedcb59f4d3e9775ce74be483395ee782ac5d5 Signed-off-by: Matus Fabian --- extras/hs-test/http_test.go | 97 ++++++++++++++++++++------------- extras/hs-test/infra/hst_suite.go | 2 + src/plugins/http_static/http_static.h | 22 +++++++- src/plugins/http_static/static_server.c | 55 +++++++++---------- 4 files changed, 108 insertions(+), 68 deletions(-) diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go index 19f54d17000..12811cbd380 100644 --- a/extras/hs-test/http_test.go +++ b/extras/hs-test/http_test.go @@ -37,7 +37,8 @@ func init() { HttpClientGetTlsNoRespBodyTest, HttpClientPostFileTest, HttpClientPostFilePtrTest, HttpUnitTest, HttpRequestLineTest, HttpClientGetTimeout, HttpStaticFileHandlerWrkTest, HttpStaticUrlHandlerWrkTest, HttpConnTimeoutTest, HttpClientGetRepeatTest, HttpClientPostRepeatTest, HttpIgnoreH2UpgradeTest, HttpInvalidAuthorityFormUriTest, HttpHeaderErrorConnectionDropTest, - HttpClientInvalidHeaderNameTest, HttpStaticHttp1OnlyTest, HttpTimerSessionDisable, HttpClientBodySizeTest) + HttpClientInvalidHeaderNameTest, HttpStaticHttp1OnlyTest, HttpTimerSessionDisable, HttpClientBodySizeTest, + HttpStaticRedirectTest) RegisterNoTopoSoloTests(HttpStaticPromTest, HttpGetTpsTest, HttpGetTpsInterruptModeTest, PromConcurrentConnectionsTest, PromMemLeakTest, HttpClientPostMemLeakTest, HttpInvalidClientRequestMemLeakTest, HttpPostTpsTest, HttpPostTpsInterruptModeTest, PromConsecutiveConnectionsTest, HttpGetTpsTlsTest, HttpPostTpsTlsTest, HttpClientGetRepeatMTTest, HttpClientPtrGetRepeatMTTest) @@ -1111,7 +1112,7 @@ func HttpStaticPathSanitizationTest(s *NoTopoSuite) { defer resp.Body.Close() s.Log(DumpHttpResp(resp, true)) s.AssertHttpStatus(resp, 301) - s.AssertHttpHeaderWithValue(resp, "Location", "http://"+s.VppAddr()+"/index.html") + s.AssertHttpHeaderWithValue(resp, "Location", "http://"+serverAddress+"/index.html") } func HttpStaticMovedTest(s *NoTopoSuite) { @@ -1119,11 +1120,11 @@ func HttpStaticMovedTest(s *NoTopoSuite) { vpp.Container.Exec(false, "mkdir -p "+wwwRootPath+"/tmp.aaa") err := vpp.Container.CreateFile(wwwRootPath+"/tmp.aaa/index.html", "

Hello

") s.AssertNil(err, fmt.Sprint(err)) - serverAddress := s.VppAddr() - s.Log(vpp.Vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/" + s.Ports.Http + " debug")) + serverAddress := s.VppAddr() + ":" + s.Ports.Http + s.Log(vpp.Vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + " debug")) client := NewHttpClient(defaultHttpTimeout, false) - req, err := http.NewRequest("GET", "http://"+serverAddress+":"+s.Ports.Http+"/tmp.aaa", nil) + req, err := http.NewRequest("GET", "http://"+serverAddress+"/tmp.aaa", nil) s.AssertNil(err, fmt.Sprint(err)) resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) @@ -1136,6 +1137,32 @@ func HttpStaticMovedTest(s *NoTopoSuite) { s.AssertHttpContentLength(resp, int64(0)) } +func HttpStaticRedirectTest(s *NoTopoSuite) { + vpp := s.Containers.Vpp.VppInstance + vpp.Container.Exec(false, "mkdir -p "+wwwRootPath) + err := vpp.Container.CreateFile(wwwRootPath+"/index.html", "

Hello

") + s.AssertNil(err, fmt.Sprint(err)) + serverAddress := s.VppAddr() + ":" + s.Ports.Http + s.Log(vpp.Vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + " debug")) + + req := "GET / HTTP/1.1\r\nHost: example.com\r\nUser-Agent: test\r\n\r\n" + + conn, err := net.DialTimeout("tcp", serverAddress, time.Second*30) + s.AssertNil(err, fmt.Sprint(err)) + defer conn.Close() + err = conn.SetDeadline(time.Now().Add(time.Second * 5)) + s.AssertNil(err, fmt.Sprint(err)) + n, err := conn.Write([]byte(req)) + s.AssertNil(err, fmt.Sprint(err)) + s.AssertEqual(n, len([]rune(req))) + reply := make([]byte, 1024) + _, err = conn.Read(reply) + s.AssertNil(err, fmt.Sprint(err)) + s.Log(string(reply)) + expectedLocation := fmt.Sprintf("Location: http://example.com/index.html") + s.AssertContains(string(reply), expectedLocation) +} + func HttpStaticNotFoundTest(s *NoTopoSuite) { vpp := s.Containers.Vpp.VppInstance vpp.Container.Exec(false, "mkdir -p "+wwwRootPath) @@ -1432,57 +1459,57 @@ func HttpInvalidTargetSyntaxTest(s *NoTopoSuite) { serverAddress := s.VppAddr() + ":" + s.Ports.Http s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + " url-handlers debug")) - resp, err := TcpSendReceive(serverAddress, "GET /interface|stats.json HTTP/1.1\r\n\r\n") + resp, err := TcpSendReceive(serverAddress, "GET /interface|stats.json HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "'|' not allowed in target path") - resp, err = TcpSendReceive(serverAddress, "GET /interface#stats.json HTTP/1.1\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /interface#stats.json HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "'#' not allowed in target path") - resp, err = TcpSendReceive(serverAddress, "GET /interface%stats.json HTTP/1.1\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /interface%stats.json HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "after '%' there must be two hex-digit characters in target path") - resp, err = TcpSendReceive(serverAddress, "GET /interface%1stats.json HTTP/1.1\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /interface%1stats.json HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "after '%' there must be two hex-digit characters in target path") - resp, err = TcpSendReceive(serverAddress, "GET /interface%Bstats.json HTTP/1.1\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /interface%Bstats.json HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "after '%' there must be two hex-digit characters in target path") - resp, err = TcpSendReceive(serverAddress, "GET /interface%stats.json%B HTTP/1.1\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /interface%stats.json%B HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "after '%' there must be two hex-digit characters in target path") - resp, err = TcpSendReceive(serverAddress, "GET /version.json?verbose>true HTTP/1.1\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /version.json?verbose>true HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "'>' not allowed in target query") - resp, err = TcpSendReceive(serverAddress, "GET /version.json?verbose%true HTTP/1.1\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /version.json?verbose%true HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "after '%' there must be two hex-digit characters in target query") - resp, err = TcpSendReceive(serverAddress, "GET /version.json?verbose=%1 HTTP/1.1\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /version.json?verbose=%1 HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "after '%' there must be two hex-digit characters in target query") - resp, err = TcpSendReceive(serverAddress, "GET * HTTP/1.1\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET * HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "asterisk-form is only used for a server-wide OPTIONS request") - resp, err = TcpSendReceive(serverAddress, "GET www.example.com:80 HTTP/1.1\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET www.example.com:80 HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "authority-form is only used for CONNECT requests") - resp, err = TcpSendReceive(serverAddress, "CONNECT https://www.example.com/tunnel HTTP/1.1\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "CONNECT https://www.example.com/tunnel HTTP/1.1\r\nHost: example.com\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "CONNECT requests must use authority-form only") } @@ -1508,22 +1535,22 @@ 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 max-body-size 12")) + serverAddress := s.VppAddr() + ":" + s.Ports.Http + s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + " url-handlers debug max-body-size 12")) ifName := s.VppIfName() - resp, err := TcpSendReceive(serverAddress+":80", - "POST /interface_stats.json HTTP/1.1\r\nContent-Length:4\r\n\r\n"+ifName) + resp, err := TcpSendReceive(serverAddress, + "POST /interface_stats.json HTTP/1.1\r\nHost: example.com\r\nContent-Length:4\r\n\r\n"+ifName) s.AssertNil(err, fmt.Sprint(err)) validatePostInterfaceStats(s, resp) - resp, err = TcpSendReceive(serverAddress+":80", - "POST /interface_stats.json HTTP/1.1\r\nContent-Length: 4 \r\n\r\n"+ifName) + resp, err = TcpSendReceive(serverAddress, + "POST /interface_stats.json HTTP/1.1\r\nHost: example.com\r\nContent-Length: 4 \r\n\r\n"+ifName) s.AssertNil(err, fmt.Sprint(err)) validatePostInterfaceStats(s, resp) - resp, err = TcpSendReceive(serverAddress+":80", - "POST /interface_stats.json HTTP/1.1\r\nContent-Length:\t\t4\r\n\r\n"+ifName) + resp, err = TcpSendReceive(serverAddress, + "POST /interface_stats.json HTTP/1.1\r\nHost: example.com\r\nContent-Length:\t\t4\r\n\r\n"+ifName) s.AssertNil(err, fmt.Sprint(err)) validatePostInterfaceStats(s, resp) } @@ -1532,7 +1559,7 @@ func HttpHeaderErrorConnectionDropTest(s *NoTopoSuite) { vpp := s.Containers.Vpp.VppInstance serverAddress := s.VppAddr() + ":" + s.Ports.Http s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + " 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() + request := "POST /interface_stats.json HTTP/1.1\r\nHost: example.com\r\nContent-Length: 18234234\r\n\r\n" + s.VppIfName() conn, err := net.DialTimeout("tcp", serverAddress, time.Second*30) s.AssertNil(err, fmt.Sprint(err)) err = conn.SetDeadline(time.Now().Add(time.Second * 10)) @@ -1602,10 +1629,6 @@ func HttpAbsoluteFormUriTest(s *NoTopoSuite) { resp, err := TcpSendReceive(serverAddress, "GET http://"+serverAddress+"/show/version HTTP/1.1\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 200 OK") - - resp, err = TcpSendReceive(serverAddress, "GET http://"+serverAddress+":80/show/version HTTP/1.1\r\n\r\n") - s.AssertNil(err, fmt.Sprint(err)) - s.AssertContains(resp, "HTTP/1.1 200 OK") } func HttpInvalidAuthorityFormUriTest(s *NoTopoSuite) { @@ -1708,31 +1731,31 @@ func HttpInvalidHeadersTest(s *NoTopoSuite) { s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "Header section must end with CRLF CRLF") - resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser@Agent:test\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+"\r\nUser@Agent:test\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "'@' not allowed in field name") - resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser-Agent\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+"\r\nUser-Agent\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "incomplete field line not allowed") - resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\n: test\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+"\r\n: test\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "empty field name not allowed") - resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\rUser-Agent:test\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+"\rUser-Agent:test\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "invalid field line end not allowed") - resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\nUser-Agent:test\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+"\nUser-Agent:test\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "invalid field line end not allowed") - resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser-Agent:\r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+"\r\nUser-Agent:\r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "empty field value not allowed") - resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser-Agent: \r\n\r\n") + resp, err = TcpSendReceive(serverAddress, "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+"\r\nUser-Agent: \r\n\r\n") s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "empty field value not allowed") } diff --git a/extras/hs-test/infra/hst_suite.go b/extras/hs-test/infra/hst_suite.go index e9d0dacce07..bfc6b7a8424 100644 --- a/extras/hs-test/infra/hst_suite.go +++ b/extras/hs-test/infra/hst_suite.go @@ -70,6 +70,8 @@ var reservedPorts = []string{ "53", "67", "68", + "80", + "443", "500", "2152", "3784", diff --git a/src/plugins/http_static/http_static.h b/src/plugins/http_static/http_static.h index 2c65df0c9d0..46c9e758844 100644 --- a/src/plugins/http_static/http_static.h +++ b/src/plugins/http_static/http_static.h @@ -47,6 +47,7 @@ typedef struct hss_session_ u32 listener_index; u8 *target_path; u8 *target_query; + u8 *authority; http_req_method_t rt; /** Fully-resolved file path */ u8 *path; @@ -128,6 +129,24 @@ typedef hss_url_handler_rc_t (*hss_url_handler_fn) (hss_url_handler_args_t *); typedef void (*hss_register_url_fn) (hss_url_handler_fn, char *, int); typedef void (*hss_session_send_fn) (hss_url_handler_args_t *args); +#define foreach_hss_listener_flags \ + _ (HTTP1_ONLY) \ + _ (NEED_CRYPTO) + +typedef enum hss_listener_flags_bit_ +{ +#define _(sym) HSS_LISTENER_F_BIT_##sym, + foreach_hss_listener_flags +#undef _ +} hss_listener_flags_bit_t; + +typedef enum hss_listener_flags_ +{ +#define _(sym) HSS_LISTENER_F_##sym = 1 << HSS_LISTENER_F_BIT_##sym, + foreach_hss_listener_flags +#undef _ +} __clib_packed hss_listener_flags_t; + typedef struct hss_listener_ { /** Path to file hash table */ @@ -156,8 +175,7 @@ typedef struct hss_listener_ u32 l_index; /** Listener session handle */ session_handle_t session_handle; - /** Enable only HTTP/1.1 in TLS ALPN list */ - u8 http1_only; + u8 flags; } hss_listener_t; /** \brief Main data structure diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c index f1cfbeec1d7..4015916bcfe 100644 --- a/src/plugins/http_static/static_server.c +++ b/src/plugins/http_static/static_server.c @@ -435,12 +435,7 @@ static u32 try_index_file (hss_listener_t *l, hss_session_t *hs, u8 *path) { hss_main_t *hsm = &hss_main; - u8 *port_str = 0, *redirect; - transport_endpoint_t endpt; - transport_proto_t proto; - int print_port = 0; - u16 local_port; - session_t *ts; + u8 *redirect; u32 plen; /* Remove the trailing space */ @@ -464,29 +459,13 @@ try_index_file (hss_listener_t *l, hss_session_t *hs, u8 *path) */ vec_delete (path, vec_len (l->www_root) - 1, 0); - ts = session_get (hs->vpp_session_index, hs->thread_index); - session_get_endpoint (ts, &endpt, 1 /* is_local */); - - local_port = clib_net_to_host_u16 (endpt.port); - proto = session_type_transport_proto (ts->session_type); - - if ((proto == TRANSPORT_PROTO_TCP && local_port != 80) || - (proto == TRANSPORT_PROTO_TLS && local_port != 443)) - { - print_port = 1; - port_str = format (0, ":%u", (u32) local_port); - } - - redirect = - format (0, "http%s://%U%s%s", proto == TRANSPORT_PROTO_TLS ? "s" : "", - format_ip46_address, &endpt.ip, endpt.is_ip4, - print_port ? port_str : (u8 *) "", path); + redirect = format (0, "http%s://%s%s", + l->flags & HSS_LISTENER_F_NEED_CRYPTO ? "s" : "", + hs->authority, path); if (hsm->debug_level > 0) clib_warning ("redirect: %s", redirect); - vec_free (port_str); - if (hss_add_header (hs, HTTP_HEADER_LOCATION, (const char *) redirect, vec_len (redirect))) return HTTP_STATUS_INTERNAL_ERROR; @@ -691,6 +670,7 @@ hss_ts_rx_callback (session_t *ts) hs->data_len = 0; vec_free (hs->target_path); vec_free (hs->target_query); + vec_free (hs->authority); http_init_headers_ctx (&hs->resp_headers, hs->headers_buf, vec_len (hs->headers_buf)); @@ -710,6 +690,21 @@ hss_ts_rx_callback (session_t *ts) hs->rt = msg.method_type; + /* Read authority */ + if (msg.data.target_authority_len) + { + vec_validate (hs->authority, msg.data.target_authority_len - 1); + rv = svm_fifo_peek (ts->rx_fifo, msg.data.target_authority_offset, + msg.data.target_authority_len, hs->authority); + ASSERT (rv == msg.data.target_authority_len); + } + else + { + /* Mandatory Host header was missing in HTTP/1.1 request */ + start_send_data (hs, HTTP_STATUS_BAD_REQUEST); + vec_add1 (hs->authority, 0); + goto err_done; + } /* Read target path */ if (msg.data.target_path_len) { @@ -891,6 +886,7 @@ hss_ts_cleanup (session_t *s, session_cleanup_ntf_t ntf) hs->free_data = 0; vec_free (hs->headers_buf); vec_free (hs->path); + vec_free (hs->authority); vec_free (hs->target_path); vec_free (hs->target_query); @@ -988,11 +984,12 @@ hss_listen (hss_listener_t *l, session_handle_t *lh) if (need_crypto) { + l->flags |= HSS_LISTENER_F_NEED_CRYPTO; ext_cfg = session_endpoint_add_ext_cfg ( &a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_CRYPTO, sizeof (transport_endpt_crypto_cfg_t)); ext_cfg->crypto.ckpair_index = hsm->ckpair_index; - if (l->http1_only) + if (l->flags & HSS_LISTENER_F_HTTP1_ONLY) ext_cfg->crypto.alpn_protos[0] = TLS_ALPN_PROTO_HTTP_1_1; } @@ -1135,7 +1132,7 @@ hss_create_command_fn (vlib_main_t *vm, unformat_input_t *input, l->max_body_size = HSS_DEFAULT_MAX_BODY_SIZE; l->rx_buff_thresh = HSS_DEFAULT_RX_BUFFER_THRESH; l->keepalive_timeout = HSS_DEFAULT_KEEPALIVE_TIMEOUT; - l->http1_only = 0; + l->flags = 0; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -1182,7 +1179,7 @@ hss_create_command_fn (vlib_main_t *vm, unformat_input_t *input, &l->use_ptr_thresh)) ; else if (unformat (line_input, "http1-only")) - l->http1_only = 1; + l->flags |= HSS_LISTENER_F_HTTP1_ONLY; else { error = clib_error_return (0, "unknown input `%U'", @@ -1278,7 +1275,7 @@ hss_add_del_listener_command_fn (vlib_main_t *vm, unformat_input_t *input, l->max_body_size = HSS_DEFAULT_MAX_BODY_SIZE; l->rx_buff_thresh = HSS_DEFAULT_RX_BUFFER_THRESH; l->keepalive_timeout = HSS_DEFAULT_KEEPALIVE_TIMEOUT; - l->http1_only = 0; + l->flags = 0; while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { -- 2.16.6