aboutsummaryrefslogtreecommitdiffstats
path: root/sharkd_session.c
diff options
context:
space:
mode:
authorJakub Zawadzki <darkjames-ws@darkjames.pl>2017-03-11 12:27:14 +0100
committerAlexis La Goutte <alexis.lagoutte@gmail.com>2017-03-11 20:35:19 +0000
commitbccc2004dfbd179ee05fa2e4d6d336a23df7b150 (patch)
tree5ea92f1d77aa57727802cc70614943f8f5bbbf54 /sharkd_session.c
parent7d28e99a7c73b9a51be3d2b96dd5f7f2bfb253f3 (diff)
sharkd: support for export objects, following stream.
Change-Id: I364cb200e537ae07cbe831d8be1f217c5a15ee09 Reviewed-on: https://code.wireshark.org/review/20492 Petri-Dish: Jakub Zawadzki <darkjames-ws@darkjames.pl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net> Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Diffstat (limited to 'sharkd_session.c')
-rw-r--r--sharkd_session.c411
1 files changed, 411 insertions, 0 deletions
diff --git a/sharkd_session.c b/sharkd_session.c
index ba06184e3e..3719f6337f 100644
--- a/sharkd_session.c
+++ b/sharkd_session.c
@@ -46,6 +46,8 @@
#include <epan/stats_tree_priv.h>
#include <epan/stat_tap_ui.h>
#include <epan/conversation_table.h>
+#include <epan/export_object.h>
+#include <epan/follow.h>
#include <epan/dissectors/packet-h225.h>
#include <epan/rtp_pt.h>
@@ -60,6 +62,7 @@
# include <wsutil/pint.h>
#endif
+#include <wsutil/glib-compat.h>
#include <wsutil/strtoi.h>
#include "sharkd.h"
@@ -243,6 +246,44 @@ sharkd_session_process_info_conv_cb(const void* key, void* value, void* userdata
return FALSE;
}
+static gboolean
+sharkd_export_object_visit_cb(const void *key _U_, void *value, void *user_data)
+{
+ register_eo_t *eo = (register_eo_t*)value;
+ int *pi = (int *) user_data;
+
+ const int proto_id = get_eo_proto_id(eo);
+ const char *filter = proto_get_protocol_filter_name(proto_id);
+ const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
+
+ printf("%s{", (*pi) ? "," : "");
+ printf("\"name\":\"Export Object/%s\"", label);
+ printf(",\"tap\":\"eo:%s\"", filter);
+ printf("}");
+
+ *pi = *pi + 1;
+ return FALSE;
+}
+
+static gboolean
+sharkd_follower_visit_cb(const void *key _U_, void *value, void *user_data)
+{
+ register_follow_t *follower = (register_follow_t*) value;
+ int *pi = (int *) user_data;
+
+ const int proto_id = get_follow_proto_id(follower);
+ const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
+ const char *filter = label; /* correct: get_follow_by_name() is registered by short name */
+
+ printf("%s{", (*pi) ? "," : "");
+ printf("\"name\":\"Follow/%s\"", label);
+ printf(",\"tap\":\"follow:%s\"", filter);
+ printf("}");
+
+ *pi = *pi + 1;
+ return FALSE;
+}
+
/**
* sharkd_session_process_info()
*
@@ -261,9 +302,17 @@ sharkd_session_process_info_conv_cb(const void* key, void* value, void* userdata
* 'name' - conversation name
* 'tap' - sharkd tap-name for conversation
*
+ * (m) eo - available export object list, array of object with attributes:
+ * 'name' - export object name
+ * 'tap' - sharkd tap-name for conversation
+ *
* (m) taps - available taps, array of object with attributes:
* 'name' - tap name
* 'tap' - sharkd tap-name
+
+ * (m) follow - available followers, array of object with attributes:
+ * 'name' - tap name
+ * 'tap' - sharkd tap-name
*
* (m) ftypes - conversation table for FT_ number to string
*/
@@ -329,6 +378,16 @@ sharkd_session_process_info(void)
}
printf("]");
+ printf(",\"eo\":[");
+ i = 0;
+ eo_iterate_tables(sharkd_export_object_visit_cb, &i);
+ printf("]");
+
+ printf(",\"follow\":[");
+ i = 0;
+ follow_iterate_followers(sharkd_follower_visit_cb, &i);
+ printf("]");
+
printf("}\n");
}
@@ -918,6 +977,97 @@ sharkd_session_process_tap_conv_cb(void *arg)
printf("],\"proto\":\"%s\",\"geoip\":%s},", proto, with_geoip ? "true" : "false");
}
+struct sharkd_export_object_list
+{
+ struct sharkd_export_object_list *next;
+
+ char *type;
+ const char *proto;
+ GSList *entries;
+};
+
+static struct sharkd_export_object_list *sharkd_eo_list;
+
+/**
+ * sharkd_session_process_tap_eo_cb()
+ *
+ * Output eo tap:
+ * (m) tap - tap name
+ * (m) type - tap output type
+ * (m) proto - protocol short name
+ * (m) objects - array of object with attributes:
+ * (m) pkt - packet number
+ * (o) hostname - hostname
+ * (o) type - content type
+ * (o) filename - filename
+ * (m) len - object length
+ */
+static void
+sharkd_session_process_tap_eo_cb(void *tapdata)
+{
+ export_object_list_t *tap_object = (export_object_list_t *) tapdata;
+ struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list*) tap_object->gui_data;
+ GSList *slist;
+ int i = 0;
+
+ printf("{\"tap\":\"%s\",\"type\":\"eo\"", object_list->type);
+ printf(",\"proto\":\"%s\"", object_list->proto);
+ printf(",\"objects\":[");
+
+ for (slist = object_list->entries; slist; slist = slist->next)
+ {
+ const export_object_entry_t *eo_entry = (export_object_entry_t *) slist->data;
+
+ printf("%s{", i ? "," : "");
+
+ printf("\"pkt\":%u", eo_entry->pkt_num);
+
+ if (eo_entry->hostname)
+ {
+ printf(",\"hostname\":");
+ json_puts_string(eo_entry->hostname);
+ }
+
+ if (eo_entry->content_type)
+ {
+ printf(",\"type\":");
+ json_puts_string(eo_entry->content_type);
+ }
+
+ if (eo_entry->filename)
+ {
+ printf(",\"filename\":");
+ json_puts_string(eo_entry->filename);
+ }
+
+ printf(",\"_download\":\"%s_%d\"", object_list->type, i);
+
+ printf(",\"len\":%" G_GUINT64_FORMAT, eo_entry->payload_len);
+
+ printf("}");
+
+ i++;
+ }
+
+ printf("]},");
+}
+
+static void
+sharkd_eo_object_list_add_entry(void *gui_data, export_object_entry_t *entry)
+{
+ struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
+
+ object_list->entries = g_slist_append(object_list->entries, entry);
+}
+
+static export_object_entry_t *
+sharkd_eo_object_list_get_entry(void *gui_data, int row)
+{
+ struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
+
+ return (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
+}
+
/**
* sharkd_session_process_tap_rtp_cb()
*
@@ -1019,6 +1169,7 @@ sharkd_session_process_tap_rtp_cb(void *arg)
* for type:conv see sharkd_session_process_tap_conv_cb()
* for type:host see sharkd_session_process_tap_conv_cb()
* for type:rtp-streams see sharkd_session_process_tap_rtp_cb()
+ * for type:eo see sharkd_session_process_tap_eo_cb()
*
* (m) err - error code
*/
@@ -1115,6 +1266,47 @@ sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count)
tap_data = &ct_data->hash;
}
+ else if (!strncmp(tok_tap, "eo:", 3))
+ {
+ register_eo_t *eo = get_eo_by_name(tok_tap + 3);
+ export_object_list_t *eo_object;
+ struct sharkd_export_object_list *object_list;
+
+ if (!eo)
+ {
+ fprintf(stderr, "sharkd_session_process_tap() eo=%s not found\n", tok_tap + 3);
+ continue;
+ }
+
+ for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
+ {
+ if (!strcmp(object_list->type, tok_tap))
+ {
+ g_slist_free_full(object_list->entries, (GDestroyNotify) eo_free_entry);
+ object_list->entries = NULL;
+ break;
+ }
+ }
+
+ if (!object_list)
+ {
+ object_list = g_new(struct sharkd_export_object_list, 1);
+ object_list->type = g_strdup(tok_tap);
+ object_list->proto = proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo)));
+ object_list->entries = NULL;
+ object_list->next = sharkd_eo_list;
+ sharkd_eo_list = object_list;
+ }
+
+ eo_object = g_new0(export_object_list_t, 1);
+ eo_object->add_entry = sharkd_eo_object_list_add_entry;
+ eo_object->get_entry = sharkd_eo_object_list_get_entry;
+ eo_object->gui_data = (void *) object_list;
+
+ tap_error = register_tap_listener(get_eo_tap_listener_name(eo), eo_object, NULL, 0, NULL, get_eo_packet_func(eo), sharkd_session_process_tap_eo_cb);
+
+ tap_data = eo_object;
+ }
else if (!strcmp(tok_tap, "rtp-streams"))
{
tap_error = register_tap_listener("rtp", &rtp_tapinfo, tap_filter, 0, rtpstream_reset_cb, rtpstream_packet, sharkd_session_process_tap_rtp_cb);
@@ -1156,6 +1348,130 @@ sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count)
}
}
+/**
+ * sharkd_session_process_follow()
+ *
+ * Process follow request
+ *
+ * Input:
+ * (m) follow - follow protocol request (e.g. HTTP)
+ * (m) filter - filter request (e.g. tcp.stream == 1)
+ *
+ * Output object with attributes:
+ *
+ * (m) err - error code
+ * (m) shost - server host
+ * (m) sport - server port
+ * (m) sbytes - server send bytes count
+ * (m) chost - client host
+ * (m) cport - client port
+ * (m) cbytes - client send bytes count
+ * (o) payloads - array of object with attributes:
+ * (o) s - set if server sent, else client
+ * (m) n - packet number
+ * (m) d - data base64 encoded
+ */
+static void
+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");
+
+ register_follow_t *follower;
+ GString *tap_error;
+
+ follow_info_t *follow_info;
+ const char *host;
+ char *port;
+
+ if (!tok_follow || !tok_filter)
+ return;
+
+ follower = get_follow_by_name(tok_follow);
+ if (!follower)
+ {
+ fprintf(stderr, "sharkd_session_process_follow() follower=%s not found\n", tok_follow);
+ return;
+ }
+
+ /* follow_reset_stream ? */
+ follow_info = g_new0(follow_info_t, 1);
+ /* 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);
+ if (tap_error)
+ {
+ fprintf(stderr, "sharkd_session_process_follow() name=%s error=%s", tok_follow, tap_error->str);
+ g_string_free(tap_error, TRUE);
+ g_free(follow_info);
+ return;
+ }
+
+ sharkd_retap();
+
+ printf("{");
+
+ printf("\"err\":0");
+
+ /* Server information: hostname, port, bytes sent */
+ host = address_to_name(&follow_info->server_ip);
+ printf(",\"shost\":");
+ json_puts_string(host);
+
+ port = get_follow_port_to_display(follower)(NULL, follow_info->server_port);
+ printf(",\"sport\":");
+ json_puts_string(port);
+ wmem_free(NULL, port);
+
+ printf(",\"sbytes\":%u", follow_info->bytes_written[0]);
+
+ /* Client information: hostname, port, bytes sent */
+ host = address_to_name(&follow_info->client_ip);
+ printf(",\"chost\":");
+ json_puts_string(host);
+
+ port = get_follow_port_to_display(follower)(NULL, follow_info->client_port);
+ printf(",\"cport\":");
+ json_puts_string(port);
+ wmem_free(NULL, port);
+
+ printf(",\"cbytes\":%u", follow_info->bytes_written[1]);
+
+ if (follow_info->payload)
+ {
+ follow_record_t *follow_record;
+ GList *cur;
+ const char *sepa = "";
+
+ printf(",\"payloads\":[");
+
+ for (cur = follow_info->payload; cur; cur = g_list_next(cur))
+ {
+ follow_record = (follow_record_t *) cur->data;
+
+ printf("%s{", sepa);
+
+ printf("\"n\":%u", follow_record->packet_num);
+
+ printf(",\"d\":");
+ json_print_base64(follow_record->data->data, follow_record->data->len);
+
+ if (follow_record->is_server)
+ printf(",\"s\":%d", 1);
+
+ printf("}");
+ sepa = ",";
+ }
+
+ printf("]");
+ }
+
+ printf("}\n");
+
+ remove_tap_listener(follow_info);
+ follow_info_free(follow_info);
+}
+
static void
sharkd_session_process_frame_cb_tree(proto_tree *tree, tvbuff_t **tvbs)
{
@@ -1257,6 +1573,33 @@ sharkd_session_process_frame_cb_tree(proto_tree *tree, tvbuff_t **tvbs)
printf("]");
}
+static gboolean
+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;
+
+ const int proto_id = get_follow_proto_id(follower);
+
+ guint32 ignore_stream;
+
+ 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)(pi, &ignore_stream);
+
+ printf(",[\"%s\",", layer_proto);
+ json_puts_string(follow_filter);
+ printf("]");
+
+ g_free(follow_filter);
+ }
+
+ return FALSE;
+}
+
static void
sharkd_session_process_frame_cb(packet_info *pi, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
{
@@ -1380,6 +1723,10 @@ sharkd_session_process_frame_cb(packet_info *pi, proto_tree *tree, struct epan_c
printf("]");
}
+ printf(",\"fol\":[0");
+ follow_iterate_followers(sharkd_follower_visit_layers_cb, pi);
+ printf("]");
+
printf("}\n");
}
@@ -1525,6 +1872,9 @@ sharkd_session_process_intervals(char *buf, const jsmntok_t *tokens, int count)
* (o) col - array of column data
* (o) bytes - base64 of frame bytes
* (o) ds - array of other data srcs
+ * (o) fol - array of follow filters:
+ * [0] - protocol
+ * [1] - filter string
*/
static void
sharkd_session_process_frame(char *buf, const jsmntok_t *tokens, int count)
@@ -1961,6 +2311,63 @@ sharkd_session_process_dumpconf(char *buf, const jsmntok_t *tokens, int count)
}
}
+/**
+ * sharkd_session_process_download()
+ *
+ * Process download request
+ *
+ * Input:
+ * (m) token - token to download
+ *
+ * Output object with attributes:
+ * (o) file - suggested name of file
+ * (o) mime - suggested content type
+ * (o) data - payload base64 encoded
+ */
+static void
+sharkd_session_process_download(char *buf, const jsmntok_t *tokens, int count)
+{
+ const char *tok_token = json_find_attr(buf, tokens, count, "token");
+
+ if (!tok_token)
+ return;
+
+ if (!strncmp(tok_token, "eo:", 3))
+ {
+ struct sharkd_export_object_list *object_list;
+ const export_object_entry_t *eo_entry = NULL;
+
+ for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
+ {
+ size_t eo_type_len = strlen(object_list->type);
+
+ if (!strncmp(tok_token, object_list->type, eo_type_len) && tok_token[eo_type_len] == '_')
+ {
+ int row;
+
+ sscanf(&tok_token[eo_type_len + 1], "%d", &row);
+
+ eo_entry = (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
+ break;
+ }
+ }
+
+ if (eo_entry)
+ {
+ const char *mime = (eo_entry->content_type) ? eo_entry->content_type : "application/octet-stream";
+ const char *filename = (eo_entry->filename) ? eo_entry->filename : tok_token;
+
+ printf("{\"file\":");
+ json_puts_string(filename);
+ printf(",\"mime\":");
+ json_puts_string(mime);
+ printf(",\"data\":");
+ json_print_base64(eo_entry->payload_data, (int) eo_entry->payload_len); /* XXX, export object will be truncated if >= 2^31 */
+ printf("}\n");
+ }
+ }
+}
+
static void
sharkd_session_process(char *buf, const jsmntok_t *tokens, int count)
{
@@ -2023,6 +2430,8 @@ sharkd_session_process(char *buf, const jsmntok_t *tokens, int count)
sharkd_session_process_frames(buf, tokens, count);
else if (!strcmp(tok_req, "tap"))
sharkd_session_process_tap(buf, tokens, count);
+ else if (!strcmp(tok_req, "follow"))
+ sharkd_session_process_follow(buf, tokens, count);
else if (!strcmp(tok_req, "intervals"))
sharkd_session_process_intervals(buf, tokens, count);
else if (!strcmp(tok_req, "frame"))
@@ -2031,6 +2440,8 @@ sharkd_session_process(char *buf, const jsmntok_t *tokens, int count)
sharkd_session_process_setconf(buf, tokens, count);
else if (!strcmp(tok_req, "dumpconf"))
sharkd_session_process_dumpconf(buf, tokens, count);
+ else if (!strcmp(tok_req, "download"))
+ sharkd_session_process_download(buf, tokens, count);
else if (!strcmp(tok_req, "bye"))
exit(0);
else