summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Zawadzki <darkjames-ws@darkjames.pl>2017-03-31 20:35:51 +0200
committerJakub Zawadzki <darkjames-ws@darkjames.pl>2017-04-08 07:29:44 +0000
commit99e0b39ba811796b48333540cf6f7edaa737c803 (patch)
treef28107e47dbf6a2556b586b910472ed79fd19374
parentb9b5703a41a52d9494c0179e42bbf5c62c7dcb05 (diff)
downloadwireshark-99e0b39ba811796b48333540cf6f7edaa737c803.tar.gz
sharkd: add tap for RTP stream analysis.
Change-Id: Idf88a891b69e4d89b2d0c62d505059ab073e266e Reviewed-on: https://code.wireshark.org/review/20816 Petri-Dish: Jakub Zawadzki <darkjames-ws@darkjames.pl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Jakub Zawadzki <darkjames-ws@darkjames.pl>
-rw-r--r--sharkd_session.c266
1 files changed, 266 insertions, 0 deletions
diff --git a/sharkd_session.c b/sharkd_session.c
index 64550d4c31..dea261991a 100644
--- a/sharkd_session.c
+++ b/sharkd_session.c
@@ -61,6 +61,9 @@
#include <ui/tap-rtp-common.h>
#include <epan/to_str.h>
+#include <epan/addr_resolv.h>
+#include <epan/dissectors/packet-rtp.h>
+
#ifdef HAVE_GEOIP
# include <GeoIP.h>
# include <epan/geoip_db.h>
@@ -215,6 +218,66 @@ sharkd_session_filter_data(const char *filter)
}
}
+struct sharkd_rtp_match
+{
+ guint32 addr_src, addr_dst;
+ address src_addr;
+ address dst_addr;
+ guint16 src_port;
+ guint16 dst_port;
+ guint32 ssrc;
+};
+
+static gboolean
+sharkd_rtp_match_init(struct sharkd_rtp_match *req, const char *init_str)
+{
+ gboolean ret = FALSE;
+ char **arr;
+
+ arr = g_strsplit(init_str, "_", 7); /* pass larger value, so we'll catch incorrect input :) */
+ if (g_strv_length(arr) != 5)
+ goto fail;
+
+ /* TODO, for now only IPv4 */
+ if (!get_host_ipaddr(arr[0], &req->addr_src))
+ goto fail;
+
+ if (!ws_strtou16(arr[1], NULL, &req->src_port))
+ goto fail;
+
+ if (!get_host_ipaddr(arr[2], &req->addr_dst))
+ goto fail;
+
+ if (!ws_strtou16(arr[3], NULL, &req->dst_port))
+ goto fail;
+
+ if (!ws_hexstrtou32(arr[4], NULL, &req->ssrc))
+ goto fail;
+
+ set_address(&req->src_addr, AT_IPv4, 4, &req->addr_src);
+ set_address(&req->dst_addr, AT_IPv4, 4, &req->addr_dst);
+ ret = TRUE;
+
+fail:
+ g_strfreev(arr);
+ return ret;
+}
+
+static gboolean
+sharkd_rtp_match_check(const struct sharkd_rtp_match *req, const packet_info *pinfo, const struct _rtp_info *rtp_info)
+{
+ if (rtp_info->info_sync_src == req->ssrc &&
+ pinfo->srcport == req->src_port &&
+ pinfo->destport == req->dst_port &&
+ addresses_equal(&pinfo->src, &req->src_addr) &&
+ addresses_equal(&pinfo->dst, &req->dst_addr))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static gboolean
sharkd_session_process_info_conv_cb(const void* key, void* value, void* userdata)
{
@@ -979,6 +1042,188 @@ sharkd_session_geoip_addr(address *addr, const char *suffix)
return with_geoip;
}
+struct sharkd_analyse_rtp_items
+{
+ guint32 frame_num;
+ guint32 sequence_num;
+
+ double delta;
+ double jitter;
+ double skew;
+ double bandwidth;
+ gboolean marker;
+
+ double arrive_offset;
+
+ /* from tap_rtp_stat_t */
+ guint32 flags;
+ guint16 pt;
+};
+
+struct sharkd_analyse_rtp
+{
+ const char *tap_name;
+ struct sharkd_rtp_match rtp;
+
+ GSList *packets;
+ double start_time;
+ tap_rtp_stat_t statinfo;
+};
+
+static void
+sharkd_session_process_tap_rtp_free_cb(void *tapdata)
+{
+ struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
+
+ g_slist_free_full(rtp_req->packets, g_free);
+ g_free(rtp_req);
+}
+
+static gboolean
+sharkd_session_packet_tap_rtp_analyse_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pointer)
+{
+ struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
+ const struct _rtp_info *rtpinfo = (const struct _rtp_info *) pointer;
+
+ if (sharkd_rtp_match_check(&rtp_req->rtp, pinfo, rtpinfo))
+ {
+ tap_rtp_stat_t *statinfo = &(rtp_req->statinfo);
+ struct sharkd_analyse_rtp_items *item;
+
+ rtp_packet_analyse(statinfo, pinfo, rtpinfo);
+
+ item = (struct sharkd_analyse_rtp_items *) g_malloc(sizeof(struct sharkd_analyse_rtp_items));
+
+ if (!rtp_req->packets)
+ rtp_req->start_time = nstime_to_sec(&pinfo->abs_ts);
+
+ item->frame_num = pinfo->num;
+ item->sequence_num = rtpinfo->info_seq_num;
+ item->delta = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->delta;
+ item->jitter = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->jitter;
+ item->skew = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->skew;
+ item->bandwidth = statinfo->bandwidth;
+ item->marker = rtpinfo->info_marker_set ? TRUE : FALSE;
+ item->arrive_offset= nstime_to_sec(&pinfo->abs_ts) - rtp_req->start_time;
+
+ item->flags = statinfo->flags;
+ item->pt = statinfo->pt;
+
+ /* XXX, O(n) optimize */
+ rtp_req->packets = g_slist_append(rtp_req->packets, item);
+ }
+
+ return TRUE;
+}
+
+/**
+ * sharkd_session_process_tap_rtp_analyse_cb()
+ *
+ * Output rtp analyse tap:
+ * (m) tap - tap name
+ * (m) type - tap output type
+ * (m) ssrc - RTP SSRC
+ * (m) max_delta - Max delta (ms)
+ * (m) max_delta_nr - Max delta packet #
+ * (m) max_jitter - Max jitter (ms)
+ * (m) mean_jitter - Mean jitter (ms)
+ * (m) max_skew - Max skew (ms)
+ * (m) total_nr - Total number of RTP packets
+ * (m) seq_err - Number of sequence errors
+ * (m) duration - Duration (ms)
+ * (m) items - array of object with attributes:
+ * (m) f - frame number
+ * (m) o - arrive offset
+ * (m) sn - sequence number
+ * (m) d - delta
+ * (m) j - jitter
+ * (m) sk - skew
+ * (m) bw - bandwidth
+ * (o) s - status string
+ * (o) t - status type
+ * (o) mark - rtp mark
+ */
+static void
+sharkd_session_process_tap_rtp_analyse_cb(void *tapdata)
+{
+ const int RTP_TYPE_CN = 1;
+ const int RTP_TYPE_ERROR = 2;
+ const int RTP_TYPE_WARN = 3;
+ const int RTP_TYPE_PT_EVENT = 4;
+
+ const struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
+ const tap_rtp_stat_t *statinfo = &rtp_req->statinfo;
+
+ const char *sepa = "";
+ GSList *l;
+
+ printf("{\"tap\":\"%s\",\"type\":\"rtp-analyse\"", rtp_req->tap_name);
+
+ printf(",\"ssrc\":%u", rtp_req->rtp.ssrc);
+
+ printf(",\"max_delta\":%f", statinfo->max_delta);
+ printf(",\"max_delta_nr\":%u", statinfo->max_nr);
+ printf(",\"max_jitter\":%f", statinfo->max_jitter);
+ printf(",\"mean_jitter\":%f", statinfo->mean_jitter);
+ printf(",\"max_skew\":%f", statinfo->max_skew);
+ printf(",\"total_nr\":%u", statinfo->total_nr);
+ printf(",\"seq_err\":%u", statinfo->sequence);
+ printf(",\"duration\":%f", statinfo->time - statinfo->start_time);
+
+ printf(",\"items\":[");
+ for (l = rtp_req->packets; l; l = l->next)
+ {
+ struct sharkd_analyse_rtp_items *item = (struct sharkd_analyse_rtp_items *) l->data;
+
+ printf("%s{", sepa);
+
+ printf("\"f\":%u", item->frame_num);
+ printf(",\"o\":%.9f", item->arrive_offset);
+ printf(",\"sn\":%u", item->sequence_num);
+ printf(",\"d\":%.2f", item->delta);
+ printf(",\"j\":%.2f", item->jitter);
+ printf(",\"sk\":%.2f", item->skew);
+ printf(",\"bw\":%.2f", item->bandwidth);
+
+ if (item->pt == PT_CN)
+ printf(",\"s\":\"%s\",\"t\":%d", "Comfort noise (PT=13, RFC 3389)", RTP_TYPE_CN);
+ else if (item->pt == PT_CN_OLD)
+ printf(",\"s\":\"%s\",\"t\":%d", "Comfort noise (PT=19, reserved)", RTP_TYPE_CN);
+ else if (item->flags & STAT_FLAG_WRONG_SEQ)
+ printf(",\"s\":\"%s\",\"t\":%d", "Wrong sequence number", RTP_TYPE_ERROR);
+ else if (item->flags & STAT_FLAG_DUP_PKT)
+ printf(",\"s\":\"%s\",\"t\":%d", "Suspected duplicate (MAC address) only delta time calculated", RTP_TYPE_WARN);
+ else if (item->flags & STAT_FLAG_REG_PT_CHANGE)
+ printf(",\"s\":\"Payload changed to PT=%u%s\",\"t\":%d",
+ item->pt,
+ (item->flags & STAT_FLAG_PT_T_EVENT) ? " telephone/event" : "",
+ RTP_TYPE_WARN);
+ else if (item->flags & STAT_FLAG_WRONG_TIMESTAMP)
+ printf(",\"s\":\"%s\",\"t\":%d", "Incorrect timestamp", RTP_TYPE_WARN);
+ else if ((item->flags & STAT_FLAG_PT_CHANGE)
+ && !(item->flags & STAT_FLAG_FIRST)
+ && !(item->flags & STAT_FLAG_PT_CN)
+ && (item->flags & STAT_FLAG_FOLLOW_PT_CN)
+ && !(item->flags & STAT_FLAG_MARKER))
+ {
+ printf(",\"s\":\"%s\",\"t\":%d", "Marker missing?", RTP_TYPE_WARN);
+ }
+ else if (item->flags & STAT_FLAG_PT_T_EVENT)
+ printf(",\"s\":\"PT=%u telephone/event\",\"t\":%d", item->pt, RTP_TYPE_PT_EVENT);
+ else if (item->flags & STAT_FLAG_MARKER)
+ printf(",\"t\":%d", RTP_TYPE_WARN);
+
+ if (item->marker)
+ printf(",\"mark\":1");
+
+ printf("}");
+ sepa = ",";
+ }
+ printf("]");
+
+ printf("},");
+}
+
/**
* sharkd_session_process_tap_conv_cb()
*
@@ -1556,6 +1801,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:rtp-analyse see sharkd_session_process_tap_rtp_analyse_cb()
* for type:eo see sharkd_session_process_tap_eo_cb()
* for type:expert see sharkd_session_process_tap_expert_cb()
* for type:rtd see sharkd_session_process_tap_rtd_cb()
@@ -1778,6 +2024,26 @@ sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count)
tap_data = &rtp_tapinfo;
tap_free = rtpstream_reset_cb;
}
+ else if (!strncmp(tok_tap, "rtp-analyse:", 12))
+ {
+ struct sharkd_analyse_rtp *rtp_req;
+
+ rtp_req = (struct sharkd_analyse_rtp *) g_malloc0(sizeof(*rtp_req));
+ if (!sharkd_rtp_match_init(&rtp_req->rtp, tok_tap + 12))
+ {
+ g_free(rtp_req);
+ continue;
+ }
+
+ rtp_req->tap_name = tok_tap;
+ rtp_req->statinfo.first_packet = TRUE;
+ rtp_req->statinfo.reg_pt = PT_UNDEFINED;
+
+ tap_error = register_tap_listener("rtp", rtp_req, tap_filter, 0, NULL, sharkd_session_packet_tap_rtp_analyse_cb, sharkd_session_process_tap_rtp_analyse_cb);
+
+ tap_data = rtp_req;
+ tap_free = sharkd_session_process_tap_rtp_free_cb;
+ }
else
{
fprintf(stderr, "sharkd_session_process_tap() %s not recognized\n", tok_tap);