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>
This commit is contained in:
parent
7d28e99a7c
commit
bccc2004df
411
sharkd_session.c
411
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user