From 982fc7184d46621948e53b485c7504c9d11f3350 Mon Sep 17 00:00:00 2001
From: Daniel Baumann <daniel.baumann@progress-linux.org>
Date: Fri, 17 May 2024 17:00:59 +0200
Subject: Merging upstream version 4.2.5.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
---
 sharkd_session.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 62 insertions(+), 6 deletions(-)

(limited to 'sharkd_session.c')

diff --git a/sharkd_session.c b/sharkd_session.c
index 8c378260..9e84cbc1 100644
--- a/sharkd_session.c
+++ b/sharkd_session.c
@@ -399,6 +399,7 @@ json_prep(char* buf, const jsmntok_t* tokens, int count)
         {"dumpconf",   "pref",       2, JSMN_STRING,       SHARKD_JSON_STRING,   SHARKD_OPTIONAL},
         {"follow",     "follow",     2, JSMN_STRING,       SHARKD_JSON_STRING,   SHARKD_MANDATORY},
         {"follow",     "filter",     2, JSMN_STRING,       SHARKD_JSON_STRING,   SHARKD_MANDATORY},
+        {"follow",     "sub_stream", 2, JSMN_PRIMITIVE,    SHARKD_JSON_UINTEGER, SHARKD_OPTIONAL},
         {"frame",      "frame",      2, JSMN_PRIMITIVE,    SHARKD_JSON_UINTEGER, SHARKD_MANDATORY},
         {"frame",      "proto",      2, JSMN_PRIMITIVE,    SHARKD_JSON_BOOLEAN,  SHARKD_OPTIONAL},
         {"frame",      "ref_frame",  2, JSMN_PRIMITIVE,    SHARKD_JSON_UINTEGER, SHARKD_OPTIONAL},
@@ -631,7 +632,7 @@ json_prep(char* buf, const jsmntok_t* tokens, int count)
                     {
                         sharkd_json_error(
                                 rpcid, -32600, NULL,
-                                "The data type for member %s is not a valid", attr_name
+                                "The data type for member %s is not valid", attr_name
                                 );
                         return FALSE;
                     }
@@ -3917,8 +3918,10 @@ sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count)
  * Process follow request
  *
  * Input:
- *   (m) follow  - follow protocol request (e.g. HTTP)
- *   (m) filter  - filter request (e.g. tcp.stream == 1)
+ *   (m) follow     - follow protocol request (e.g. HTTP)
+ *   (m) filter     - filter request (e.g. tcp.stream == 1)
+ *   (m) stream     - stream index number
+ *   (o) sub_stream - follow sub-stream index number (e.g. for HTTP/2 and QUIC streams)
  *
  * Output object with attributes:
  *
@@ -3939,6 +3942,7 @@ sharkd_session_process_follow(char *buf, const jsmntok_t *tokens, int count)
 {
     const char *tok_follow = json_find_attr(buf, tokens, count, "follow");
     const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
+    const char *tok_sub_stream = json_find_attr(buf, tokens, count, "sub_stream");
 
     register_follow_t *follower;
     GString *tap_error;
@@ -3957,8 +3961,15 @@ sharkd_session_process_follow(char *buf, const jsmntok_t *tokens, int count)
         return;
     }
 
+    guint64 substream_id = SUBSTREAM_UNUSED;
+    if (tok_sub_stream)
+    {
+        ws_strtou64(tok_sub_stream, NULL, &substream_id);
+    }
+
     /* follow_reset_stream ? */
     follow_info = g_new0(follow_info_t, 1);
+    follow_info->substream_id = substream_id;
     /* gui_data, filter_out_filter not set, but not used by dissector */
 
     tap_error = register_tap_listener(get_follow_tap_string(follower), follow_info, tok_filter, 0, NULL, get_follow_tap_handler(follower), NULL, NULL);
@@ -4143,7 +4154,8 @@ static bool
 sharkd_follower_visit_layers_cb(const void *key _U_, void *value, void *user_data)
 {
     register_follow_t *follower = (register_follow_t *) value;
-    packet_info *pi = (packet_info *) user_data;
+    epan_dissect_t *edt = (epan_dissect_t *) user_data;
+    packet_info *pi = &edt->pi;
 
     const int proto_id = get_follow_proto_id(follower);
 
@@ -4155,7 +4167,7 @@ sharkd_follower_visit_layers_cb(const void *key _U_, void *value, void *user_dat
         const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
         char *follow_filter;
 
-        follow_filter = get_follow_conv_func(follower)(NULL, pi, &ignore_stream, &ignore_sub_stream);
+        follow_filter = get_follow_conv_func(follower)(edt, pi, &ignore_stream, &ignore_sub_stream);
 
         json_dumper_begin_array(&dumper);
         json_dumper_value_string(&dumper, layer_proto);
@@ -4168,6 +4180,41 @@ sharkd_follower_visit_layers_cb(const void *key _U_, void *value, void *user_dat
     return FALSE;
 }
 
+static bool
+sharkd_followers_visit_layers_cb(const void *key _U_, void *value, void *user_data)
+{
+    register_follow_t *follower = (register_follow_t *) value;
+    epan_dissect_t *edt = (epan_dissect_t *) user_data;
+    packet_info *pi = &edt->pi;
+
+    const int proto_id = get_follow_proto_id(follower);
+
+    guint stream;
+    guint sub_stream = (guint) SUBSTREAM_UNUSED;
+
+    if (proto_is_frame_protocol(pi->layers, proto_get_protocol_filter_name(proto_id)))
+    {
+        const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
+        char *follow_filter;
+
+        follow_filter = get_follow_conv_func(follower)(edt, pi, (guint *) &stream, (guint *) &sub_stream);
+
+        sharkd_json_object_open(NULL);
+        sharkd_json_value_string("protocol", layer_proto);
+        sharkd_json_value_string("filter", follow_filter);
+        sharkd_json_value_anyf("stream", "%d", stream);
+        if (sub_stream != (guint) SUBSTREAM_UNUSED)
+        {
+            sharkd_json_value_anyf("sub_stream", "%d", sub_stream);
+        }
+        sharkd_json_object_close();
+
+        g_free(follow_filter);
+    }
+
+    return FALSE;
+}
+
 struct sharkd_frame_request_data
 {
     gboolean display_hidden;
@@ -4327,7 +4374,11 @@ sharkd_session_process_frame_cb(epan_dissect_t *edt, proto_tree *tree, struct ep
     }
 
     sharkd_json_array_open("fol");
-    follow_iterate_followers(sharkd_follower_visit_layers_cb, pi);
+    follow_iterate_followers(sharkd_follower_visit_layers_cb, edt);
+    sharkd_json_array_close();
+
+    sharkd_json_array_open("followers");
+    follow_iterate_followers(sharkd_followers_visit_layers_cb, edt);
     sharkd_json_array_close();
 
     sharkd_json_result_epilogue();
@@ -4709,6 +4760,11 @@ sharkd_session_process_intervals(char *buf, const jsmntok_t *tokens, int count)
  *   (o) fol   - array of follow filters:
  *                  [0] - protocol
  *                  [1] - filter string
+ *   (o) followers - array of followers with attributes:
+ *                      protocol - protocol string
+ *                      filter - filter string
+ *                      stream - stream index number
+ *                      sub_stream - sub-stream index number (optional, e.g. for HTTP/2 and QUIC streams)
  *   (o) i   - if frame is ignored
  *   (o) m   - if frame is marked
  *   (o) bg  - color filter - background color in hex
-- 
cgit v1.2.3