]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1982 in SNORT/snort3 from ~KATHARVE/snort3:h2i_dynamic_size to...
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Fri, 7 Feb 2020 18:45:00 +0000 (18:45 +0000)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Fri, 7 Feb 2020 18:45:00 +0000 (18:45 +0000)
Squashed commit of the following:

commit a1bbb525ea89620dfcfc6d3985ba6ccb7fe86ba2
Author: Katura Harvey <katharve@cisco.com>
Date:   Thu Jan 23 16:48:27 2020 -0500

    http2_inspect: support HPACK dynamic table size updates

15 files changed:
src/service_inspectors/http2_inspect/http2_enum.h
src/service_inspectors/http2_inspect/http2_flow_data.cc
src/service_inspectors/http2_inspect/http2_flow_data.h
src/service_inspectors/http2_inspect/http2_hpack.cc
src/service_inspectors/http2_inspect/http2_hpack.h
src/service_inspectors/http2_inspect/http2_hpack_dynamic_table.cc
src/service_inspectors/http2_inspect/http2_hpack_dynamic_table.h
src/service_inspectors/http2_inspect/http2_hpack_table.cc
src/service_inspectors/http2_inspect/http2_hpack_table.h
src/service_inspectors/http2_inspect/http2_inspect.cc
src/service_inspectors/http2_inspect/http2_module.cc
src/service_inspectors/http2_inspect/http2_settings_frame.cc
src/service_inspectors/http2_inspect/http2_settings_frame.h
src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc
src/service_inspectors/http2_inspect/http2_tables.cc

index 507fecd908eac6fa268ea035e9d9086d8e21349b..be19f496ebc8326a88afb30817d056e2c28be52f 100644 (file)
@@ -38,13 +38,13 @@ enum FrameType : uint8_t { FT_DATA=0, FT_HEADERS=1, FT_PRIORITY=2, FT_RST_STREAM
 
 // Message buffers available to clients
 // This enum must remain synchronized with Http2Api::classic_buffer_names[]
-enum HTTP2_BUFFER { HTTP2_BUFFER_FRAME_HEADER = 1, HTTP2_BUFFER_FRAME_DATA, HTTP2_BUFFER_DECODED_HEADER,
-    HTTP2_BUFFER_MAX };
+enum HTTP2_BUFFER { HTTP2_BUFFER_FRAME_HEADER = 1, HTTP2_BUFFER_FRAME_DATA,
+    HTTP2_BUFFER_DECODED_HEADER, HTTP2_BUFFER__MAX };
 
 // Peg counts
 // This enum must remain synchronized with Http2Module::peg_names[] in http2_tables.cc
-enum PEG_COUNT { PEG_CONCURRENT_SESSIONS = 0, PEG_MAX_CONCURRENT_SESSIONS, PEG_FLOW,
-    PEG_COUNT_MAX };
+enum PEG_COUNT { PEG_FLOW = 0, PEG_CONCURRENT_SESSIONS, PEG_MAX_CONCURRENT_SESSIONS,
+    PEG_MAX_ENTRIES, PEG_COUNT__MAX };
 
 enum EventSid
 {
@@ -62,6 +62,7 @@ enum EventSid
     EVENT_SETTINGS_FRAME_ERROR = 11,
     EVENT_SETTINGS_FRAME_UNKN_PARAM = 12,
     EVENT_FRAME_SEQUENCE = 13,
+    EVENT_DYNAMIC_TABLE_OVERFLOW = 14,
     EVENT__MAX_VALUE
 };
 
@@ -90,6 +91,10 @@ enum Infraction
     INF_INVALID_SETTINGS_FRAME = 18,
     INF_SETTINGS_FRAME_UNKN_PARAM = 19,
     INF_FRAME_SEQUENCE = 20,
+    INF_INVALID_TABLE_SIZE_UPDATE = 21,
+    INF_DYNAMIC_TABLE_OVERFLOW = 22,
+    INF_TABLE_SIZE_UPDATE_WITHIN_HEADER = 23,
+    INF_TOO_MANY_TABLE_SIZE_UPDATES = 24,
     INF__MAX_VALUE
 };
 
index 6ee5571ce2076e12f167ec1dfa8029f72ba79584..5075fe530634c99426c4de60735583235ec41e64 100644 (file)
@@ -45,7 +45,8 @@ uint64_t Http2FlowData::instance_count = 0;
 Http2FlowData::Http2FlowData(Flow* flow_) :
     FlowData(inspector_id),
     flow(flow_),
-    hi((HttpInspect*)(flow->assistant_gadget))
+    hi((HttpInspect*)(flow->assistant_gadget)),
+    hpack_decoder{Http2HpackDecoder(this, SRC_CLIENT), Http2HpackDecoder(this, SRC_SERVER)}
 {
     if (hi != nullptr)
     {
index 41937d699d31f6ae6e9b3c1ab6ac9822e686c53d..93e6cd7f34425b9fa597c397f0804eddf25be62f 100644 (file)
@@ -91,6 +91,10 @@ public:
     };
     class Http2Stream* get_current_stream(const HttpCommon::SourceId source_id);
 
+    Http2HpackDecoder* get_hpack_decoder(const HttpCommon::SourceId source_id)
+        { return &hpack_decoder[source_id]; }
+    Http2ConnectionSettings* get_connection_settings(const HttpCommon::SourceId source_id)
+        { return &connection_settings[source_id]; }
 protected:
     snort::Flow* flow;
     HttpInspect* const hi;
index 4e4b6746348e44d4a881c239d88db41ed44a5817..ac47b781828ad7bea910e0a0e5150c6482e0f333 100644 (file)
@@ -122,6 +122,8 @@ bool Http2HpackDecoder::decode_literal_header_line(const uint8_t* encoded_header
     uint32_t partial_bytes_written;
     Field name, value;
 
+    table_size_update_allowed = false;
+
     // Indexed field name
     if (encoded_header_buffer[0] & name_index_mask)
     {
@@ -192,8 +194,16 @@ bool Http2HpackDecoder::decode_literal_header_line(const uint8_t* encoded_header
     }
 
     if (with_indexing)
-        decode_table.add_index(name, value);
-
+    {
+        // Adding the entry to the dynamic table fails if the number of entries in the dynamic
+        // table exceeds the Snort hard-coded limit of 512
+        if (!decode_table.add_index(name, value))
+        {
+            infractions += INF_DYNAMIC_TABLE_OVERFLOW;
+            events->create_event(EVENT_DYNAMIC_TABLE_OVERFLOW);
+            return false;
+        }
+    }
     return true;
 }
 
@@ -206,6 +216,8 @@ bool Http2HpackDecoder::decode_indexed_header(const uint8_t* encoded_header_buff
     bytes_written = 0;
     bytes_consumed = 0;
 
+    table_size_update_allowed = false;
+
     if (!decode_int.translate(encoded_header_buffer, encoded_header_length, bytes_consumed,
             index, events, infractions))
         return false;
@@ -258,7 +270,6 @@ bool Http2HpackDecoder::decode_indexed_header(const uint8_t* encoded_header_buff
     return true;
 }
 
-// FIXIT-M Will be updated to actually update dynamic table size. For now just skips over
 bool Http2HpackDecoder::handle_dynamic_size_update(const uint8_t* encoded_header_buffer,
     const uint32_t encoded_header_length, const Http2HpackIntDecode &decode_int,
     uint32_t &bytes_consumed, uint32_t &bytes_written)
@@ -273,15 +284,28 @@ bool Http2HpackDecoder::handle_dynamic_size_update(const uint8_t* encoded_header
     {
         return false;
     }
-#ifdef REG_TEST
-    //FIXIT-M remove when dynamic size updates are handled
-    if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2))
+    bytes_consumed += encoded_bytes_consumed;
+
+    if (!table_size_update_allowed)
+    {
+        *infractions += INF_TABLE_SIZE_UPDATE_WITHIN_HEADER;
+        events->create_event(EVENT_MISFORMATTED_HTTP2);
+        return true;
+    }
+    if (num_table_size_updates >= 2)
     {
-            fprintf(HttpTestManager::get_output_file(),
-                "Skipping HPACK dynamic size update: %lu\n", decoded_int);
+        *infractions += INF_TOO_MANY_TABLE_SIZE_UPDATES;
+        events->create_event(EVENT_MISFORMATTED_HTTP2);
+        return true;
     }
-#endif
-    bytes_consumed += encoded_bytes_consumed;
+
+    if (!decode_table.hpack_table_size_update(decoded_int))
+    {
+        *infractions += INF_INVALID_TABLE_SIZE_UPDATE;
+        events->create_event(EVENT_MISFORMATTED_HTTP2);
+    }
+
+    num_table_size_updates++;
 
     return true;
 }
@@ -318,7 +342,6 @@ bool Http2HpackDecoder::decode_header_line(const uint8_t* encoded_header_buffer,
             LITERAL_NO_INDEX_NAME_INDEX_MASK, decode_int4, false, bytes_consumed,
             decoded_header_buffer, decoded_header_length, bytes_written);
     else
-        // FIXIT-M dynamic table size update not yet supported, just skip
         return handle_dynamic_size_update(encoded_header_buffer,
             encoded_header_length, decode_int5, bytes_consumed, bytes_written);
 }
@@ -343,6 +366,10 @@ bool Http2HpackDecoder::decode_headers(const uint8_t* encoded_headers,
     infractions = stream_infractions;
     pseudo_headers_fragment_size = 0;
 
+    // A maximum of two table size updates are allowed, and must be at the start of the header block
+    table_size_update_allowed = true;
+    num_table_size_updates = 0;
+
     while (success and total_bytes_consumed < encoded_headers_length)
     {
         success = decode_header_line(encoded_headers + total_bytes_consumed,
index 9ec5d599db8dd2f21f1dc25044b3f2bbd49b066f..5fa92e3d956bedc39e785c99317fe84fe77fdf1a 100644 (file)
@@ -35,7 +35,8 @@ class Http2StartLine;
 class Http2HpackDecoder
 {
 public:
-    Http2HpackDecoder() { }
+    Http2HpackDecoder(Http2FlowData* flow_data, HttpCommon::SourceId src_id) :
+        decode_table(flow_data, src_id) { }
     bool decode_headers(const uint8_t* encoded_headers, const uint32_t encoded_headers_length,
         uint8_t* decoded_headers, Http2StartLine* start_line,
         Http2EventGen* stream_events, Http2Infractions* stream_infractions, bool no_message_body);
@@ -68,6 +69,7 @@ public:
     bool finalize_start_line();
     const Field* get_start_line();
     const Field* get_decoded_headers(const uint8_t* const decoded_headers);
+    HpackIndexTable* get_decode_table() { return &decode_table; }
 
 private:
     Http2StartLine* start_line = nullptr;
@@ -84,6 +86,8 @@ private:
     static Http2HpackStringDecode decode_string;
 
     HpackIndexTable decode_table;
+    bool table_size_update_allowed = true;
+    uint8_t num_table_size_updates = 0;
 };
 
 #endif
index 8e524438b2bfdcd4ccf3e13e09d9795f213e73e4..3bb7518009f7854c0ff39ebcd6bcb794435e8373 100644 (file)
 #endif
 
 #include "http2_hpack_dynamic_table.h"
+#include "http2_module.h"
 
 #include <string.h>
 
 #include "http2_hpack_table.h"
 
+using namespace Http2Enums;
+
 HpackDynamicTable::~HpackDynamicTable()
 {
-    assert(num_entries <= array_capacity);
-    const uint32_t end_index = (start + num_entries) % array_capacity;
-    for (uint32_t i = 0; i < array_capacity; i++)
-    {
-        if ((start <= end_index and (i >= start and i < end_index)) or
-            (start > end_index and (i >= start or i < end_index)))
-        {
-            delete circular_array[i];
-            circular_array[i] = nullptr;
-        }
-    }
+    for (unsigned i = 0; i < ARRAY_CAPACITY; i++)
+        delete circular_array[i];
     delete[] circular_array;
 }
 
-void HpackDynamicTable::add_entry(Field name, Field value)
+bool HpackDynamicTable::add_entry(const Field& name, const Field& value)
 {
+    // The add only fails if the underlying circular array is out of space
+    if (num_entries >= ARRAY_CAPACITY)
+        return false;
+
     const uint32_t new_entry_size = name.length() + value.length() + RFC_ENTRY_OVERHEAD;
 
     // As per the RFC, attempting to add an entry that is larger than the max size of the table is
@@ -52,34 +50,36 @@ void HpackDynamicTable::add_entry(Field name, Field value)
     if (new_entry_size > max_size)
     {
         prune_to_size(0);
-        return;
+        return true;
     }
 
+    // Create new entry. This is done before pruning because the entry referenced by the new name
+    // may be pruned.
+    HpackTableEntry *new_entry = new HpackTableEntry(name, value);
+
     // If add entry would exceed max table size, evict old entries
     prune_to_size(max_size - new_entry_size);
 
     // Add new entry to the front of the table (newest entry = lowest index)
-    HpackTableEntry *new_entry = new HpackTableEntry(name, value);
-
-    start = (start + array_capacity - 1) % array_capacity;
-
-    // FIXIT-P May want to initially allocate small circular array and expand as needed. For now
-    // array big enough to support hardcoded max table size of 4096 bytes
-    assert(num_entries < array_capacity);
+    start = (start + ARRAY_CAPACITY - 1) % ARRAY_CAPACITY;
     circular_array[start] = new_entry;
 
     num_entries++;
+    if (num_entries > Http2Module::get_peg_counts(PEG_MAX_ENTRIES))
+        Http2Module::increment_peg_counts(PEG_MAX_ENTRIES);
+
     rfc_table_size += new_entry_size;
+    return true;
 }
 
 const HpackTableEntry* HpackDynamicTable::get_entry(uint32_t virtual_index) const
 {
     const uint32_t dyn_index = virtual_index - HpackIndexTable::STATIC_MAX_INDEX - 1;
 
-    if (num_entries == 0 or dyn_index > num_entries - 1)
+    if (dyn_index + 1 > num_entries)
         return nullptr;
 
-    const uint32_t arr_index = (start + dyn_index) % array_capacity;
+    const uint32_t arr_index = (start + dyn_index) % ARRAY_CAPACITY;
     return circular_array[arr_index];
 }
 
@@ -88,18 +88,25 @@ const HpackTableEntry* HpackDynamicTable::get_entry(uint32_t virtual_index) cons
  * until the new entry fits. If the dynamic size update is smaller than the current table size,
  * entries are pruned until the table is no larger than the max size. Entries are pruned least
  * recently added first.
- * Note: dynamic size updates not yet implemented
  */
 void HpackDynamicTable::prune_to_size(uint32_t new_max_size)
 {
     while (rfc_table_size > new_max_size)
     {
-        const uint32_t last_index = (start + num_entries - 1 + array_capacity) % array_capacity;
-        HpackTableEntry *last_entry = circular_array[last_index];
+        const uint32_t last_index = (start + num_entries - 1 + ARRAY_CAPACITY) % ARRAY_CAPACITY;
         num_entries--;
-        rfc_table_size -= last_entry->name.length() + last_entry->value.length() +
-            RFC_ENTRY_OVERHEAD;
-        delete last_entry;
+        rfc_table_size -= circular_array[last_index]->name.length() +
+            circular_array[last_index]->value.length() + RFC_ENTRY_OVERHEAD;
+        delete circular_array[last_index];
         circular_array[last_index] = nullptr;
     }
 }
+
+void HpackDynamicTable::update_size(uint32_t new_size)
+{
+    if (new_size < rfc_table_size)
+    {
+        prune_to_size(new_size);
+    }
+    max_size = new_size;
+}
index 0fa40a3bfbd65ce197755649e35872045618d585..7a1f03bc4eff239e7c4e743be330177bef78af71 100644 (file)
@@ -30,25 +30,28 @@ struct HpackTableEntry;
 class HpackDynamicTable
 {
 public:
-    // FIXIT-M allocate array based on actual max_size from settings
-    HpackDynamicTable() : circular_array(new HpackTableEntry*[DEFAULT_NUM_ENTRIES]()) { }
+    // FIXIT-P This array can be optimized to start smaller and grow on demand 
+    HpackDynamicTable() : circular_array(new HpackTableEntry*[ARRAY_CAPACITY]()) { }
     ~HpackDynamicTable();
     const HpackTableEntry* get_entry(uint32_t index) const;
-    void add_entry(Field name, Field value);
-    void prune_to_size(uint32_t new_max_size);
-    // FIXIT-M implement handle_dynamic_size_update function
+    bool add_entry(const Field& name, const Field& value);
+    void update_size(uint32_t new_size);
+    uint32_t get_max_size() { return max_size; }
+
 private:
+    void expand_array();
+
     const static uint32_t RFC_ENTRY_OVERHEAD = 32;
 
-    // FIXIT-H set/update these parameters dynamically. For now hardcoded
     const static uint32_t DEFAULT_MAX_SIZE = 4096;
-    const static uint32_t DEFAULT_NUM_ENTRIES = DEFAULT_MAX_SIZE / RFC_ENTRY_OVERHEAD;
-    uint32_t array_capacity = DEFAULT_NUM_ENTRIES;
+    const static uint32_t ARRAY_CAPACITY = 512;
     uint32_t max_size = DEFAULT_MAX_SIZE;
 
     uint32_t start = 0;
     uint32_t num_entries = 0;
     uint32_t rfc_table_size = 0;
     HpackTableEntry** circular_array;
+
+    void prune_to_size(uint32_t new_max_size);
 };
 #endif
index 347a99c2e48c609d9f7dbdb47d205a34e4489cba..e5b03d0d05e0e9c477c3d55341a699bf4c655388 100644 (file)
 //--------------------------------------------------------------------------
 // http2_hpack_table.cc author Katura Harvey <katharve@cisco.com>
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "http2_enum.h"
+#include "http2_flow_data.h"
 #include "http2_hpack_table.h"
 
 #include <string.h>
 #define MAKE_TABLE_ENTRY(name, value) \
     HpackTableEntry(strlen(name), (const uint8_t*)name, strlen(value), (const uint8_t*)value)
 
+using namespace Http2Enums;
+
 HpackTableEntry::HpackTableEntry(const Field& copy_name, const Field& copy_value)
 {
     uint8_t* new_name = new uint8_t[copy_name.length()];
     uint8_t* new_value = new uint8_t[copy_value.length()];
-    memcpy(new_value, copy_value.start(), copy_value.length());
     memcpy(new_name, copy_name.start(), copy_name.length());
+    memcpy(new_value, copy_value.start(), copy_value.length());
 
     name.set(copy_name.length(), new_name, true);
     value.set(copy_value.length(), new_value, true);
@@ -108,3 +116,34 @@ const HpackTableEntry* HpackIndexTable::lookup(uint64_t index) const
     else
         return dynamic_table.get_entry(index);
 }
+
+bool HpackIndexTable::add_index(const Field& name, const Field& value)
+{
+    return dynamic_table.add_entry(name, value);
+}
+
+void HpackIndexTable::settings_table_size_update(uint32_t new_size)
+{
+    if (!encoder_set_max_size)
+        dynamic_table.update_size(new_size);
+    else if (new_size < dynamic_table.get_max_size())
+    {
+        encoder_set_max_size = false;
+        dynamic_table.update_size(new_size);
+    }
+}
+
+// A dynamic table size update sent in an HPACK encoder cannot be larger than last
+// HEADER_TABLE_SIZE settings frame parameter sent by the decoder
+bool HpackIndexTable::hpack_table_size_update(uint32_t new_size)
+{
+    encoder_set_max_size = true;
+    if (new_size <= session_data->get_connection_settings((HttpCommon::SourceId)(1 - source_id))->
+        get_param(HEADER_TABLE_SIZE))
+    {
+       dynamic_table.update_size(new_size);
+       return true;
+    }
+    else
+        return false;
+}
index 2ac181fcb9b81054f6c7b8b747c4f98571439fac..202f785cc8d1b55d6675f926df66da44946c0f55 100644 (file)
@@ -25,6 +25,8 @@
 #include "http2_enum.h"
 #include "http2_hpack_dynamic_table.h"
 
+class Http2FlowData;
+
 struct HpackTableEntry
 {
     HpackTableEntry(uint32_t name_len, const uint8_t* _name, uint32_t value_len,
@@ -38,8 +40,12 @@ struct HpackTableEntry
 class HpackIndexTable
 {
 public:
+    HpackIndexTable(Http2FlowData* flow_data, HttpCommon::SourceId src_id) :
+        session_data(flow_data), source_id(src_id) { }
     const HpackTableEntry* lookup(uint64_t index) const;
-    void add_index(Field name, Field value) { dynamic_table.add_entry(name, value); }
+    bool add_index(const Field& name, const Field& value);
+    bool hpack_table_size_update(const uint32_t size);
+    void settings_table_size_update(const uint32_t size);
 
     const static uint8_t STATIC_MAX_INDEX = 61;
     const static uint8_t PSEUDO_HEADER_MAX_STATIC_INDEX = 14;
@@ -47,5 +53,8 @@ public:
 private:
     const static HpackTableEntry static_table[STATIC_MAX_INDEX + 1];
     HpackDynamicTable dynamic_table;
+    Http2FlowData* session_data;
+    HttpCommon::SourceId source_id;
+    bool encoder_set_max_size = false;
 };
 #endif
index 2b385284f257aedd59c84d994fb2b43bc3b89a3b..836d7936510e54512e0e44d1f1f9802720cfce69 100644 (file)
@@ -133,7 +133,9 @@ void Http2Inspect::eval(Packet* p)
 
     // The current frame now owns these buffers, clear them from the flow data
     session_data->frame_header[source_id] = nullptr;
+    session_data->frame_header_size[source_id] = 0;
     session_data->frame_data[source_id] = nullptr;
+    session_data->frame_data_size[source_id] = 0;
 
     session_data->frame_in_detection = true;
 
index e83c938475fee91765326e7190f7778644b18a58..304ae196623968a3cbc8acc036026a77973d9a4b 100644 (file)
@@ -56,7 +56,7 @@ THREAD_LOCAL ProfileStats Http2Module::http2_profile;
 ProfileStats* Http2Module::get_profile() const
 { return &http2_profile; }
 
-THREAD_LOCAL PegCount Http2Module::peg_counts[PEG_COUNT_MAX] = { 0 };
+THREAD_LOCAL PegCount Http2Module::peg_counts[PEG_COUNT__MAX] = { 0 };
 
 bool Http2Module::begin(const char*, int, SnortConfig*)
 {
index 3dc0cfdcf22a8aa94a9d6de55bf6148de3e2443f..980a35c3b60d21d80e734ddd1625b4ba66b3fbd4 100644 (file)
@@ -82,6 +82,7 @@ void Http2SettingsFrame::parse_settings_frame()
             continue;
         }
 
+        handle_update(parameter_id, parameter_value);
         session_data->connection_settings[source_id].set_param(parameter_id, parameter_value);
     }
 }
@@ -100,6 +101,21 @@ bool Http2SettingsFrame::sanity_check()
     return !(bad_frame);
 }
 
+void Http2SettingsFrame::handle_update(uint16_t id, uint32_t value)
+{
+    switch (id)
+    {
+        case HEADER_TABLE_SIZE:
+            // Sending a table size parameter informs the receiver the maximum hpack dynamic
+            // table size they may use.
+            session_data->get_hpack_decoder((HttpCommon::SourceId) (1 - source_id))->
+                get_decode_table()->settings_table_size_update(value);
+            break;
+        default:
+            break;
+    }
+}
+
 #ifdef REG_TEST
 void Http2SettingsFrame::print_frame(FILE* output)
 {
index 74c0d3314188b2b5f57fafb077d19bc7bf40a8d5..00e194d69aaa676b6b408ff58b8459d0b56b0643 100644 (file)
@@ -43,6 +43,7 @@ private:
 
     void parse_settings_frame();
     bool sanity_check();
+    void handle_update(uint16_t id, uint32_t value);
 
     bool bad_frame = false;
     static const uint8_t SfAck = 0x01;
index 527e17a1c067d51fbef99f9cce583ad939cd8786..6eb937cc421b61f99a3f10e745035cbec0eaf089 100644 (file)
@@ -176,8 +176,8 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t
                 if (stream)
                     http_flow = (HttpFlowData*)stream->get_hi_flow_data();
 
-                if (!stream || !http_flow ||
-                    (http_flow->get_type_expected(source_id) != HttpEnums::SEC_BODY_CHUNK))
+                if (!stream || !http_flow || (frame_length > 0 and
+                    (http_flow->get_type_expected(source_id) != HttpEnums::SEC_BODY_CHUNK)))
                 {
                      *session_data->infractions[source_id] += INF_FRAME_SEQUENCE;
                      session_data->events[source_id]->create_event(EVENT_FRAME_SEQUENCE);
index 780672ed207d2ee6bf26e540e0a9b1425e31cb4b..29652cda1cc148e4faa2e077d53bf2eac34fff82 100644 (file)
@@ -44,14 +44,16 @@ const RuleMap Http2Module::http2_events[] =
     { EVENT_SETTINGS_FRAME_ERROR, "error in HTTP/2 settings frame" },
     { EVENT_SETTINGS_FRAME_UNKN_PARAM, "unknown parameter in HTTP/2 settings frame" },
     { EVENT_FRAME_SEQUENCE, "invalid HTTP/2 frame sequence" },
+    { EVENT_DYNAMIC_TABLE_OVERFLOW, "HTTP/2 dynamic table size limit exceeded" },
     { 0, nullptr }
 };
 
-const PegInfo Http2Module::peg_names[PEG_COUNT_MAX+1] =
+const PegInfo Http2Module::peg_names[PEG_COUNT__MAX+1] =
 {
     { CountType::SUM, "flows", "HTTP connections inspected" },
     { CountType::NOW, "concurrent_sessions", "total concurrent HTTP/2 sessions" },
     { CountType::MAX, "max_concurrent_sessions", "maximum concurrent HTTP/2 sessions" },
+    { CountType::MAX, "max_table_entries", "maximum entries in an HTTP/2 dynamic table" },
     { CountType::END, nullptr, nullptr }
 };