aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2016-01-04 13:14:08 -0800
committerGuy Harris <guy@alum.mit.edu>2016-01-04 21:14:42 +0000
commitcdf9943717c9bb1cba7af381507b295b384e800b (patch)
tree183f70fcbc06d492130997c9fe559b532d83b44a
parent849d87af1cb9f3e19222e452fd76483244375a03 (diff)
Don't walk the entire protocol tree to extract the value of one field.
Instead, prime the epan_dissect_t's tree to look for rtp.ssrc, and extract that value with proto_get_finfo_ptr_array(). Also, have the filter used to check whether the packet is a candidate for RTP analysis to check for RTPv2 (and add a check for IPv4 or IPv6 back to the Qt version), and get rid of an unnecessary extra level of indirection for that string. In the Qt version, if findStreams() set the error string, don't overwrite it with a "No streams found." indication, and fix error handling for the "filter didn't compile" case. Change-Id: I09d0ea37ccd4806d99e3b6394f2a8a376e974705 Reviewed-on: https://code.wireshark.org/review/13045 Reviewed-by: Guy Harris <guy@alum.mit.edu>
-rw-r--r--debian/libwireshark0.symbols1
-rw-r--r--epan/epan.c8
-rw-r--r--epan/epan.h7
-rw-r--r--epan/proto.h2
-rw-r--r--ui/gtk/rtp_analysis.c102
-rw-r--r--ui/qt/rtp_analysis_dialog.cpp112
6 files changed, 61 insertions, 171 deletions
diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols
index fe9952d017..2dfd297131 100644
--- a/debian/libwireshark0.symbols
+++ b/debian/libwireshark0.symbols
@@ -476,6 +476,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
epan_dissect_new@Base 1.9.1
epan_dissect_packet_contains_field@Base 1.12.0~rc1
epan_dissect_prime_dfilter@Base 1.9.1
+ epan_dissect_prime_hfid@Base 2.1.0
epan_dissect_reset@Base 1.12.0~rc1
epan_dissect_run@Base 1.9.1
epan_dissect_run_with_taps@Base 1.9.1
diff --git a/epan/epan.c b/epan/epan.c
index 98815b5d6f..d33544e681 100644
--- a/epan/epan.c
+++ b/epan/epan.c
@@ -446,7 +446,13 @@ epan_dissect_free(epan_dissect_t* edt)
void
epan_dissect_prime_dfilter(epan_dissect_t *edt, const dfilter_t* dfcode)
{
- dfilter_prime_proto_tree(dfcode, edt->tree);
+ dfilter_prime_proto_tree(dfcode, edt->tree);
+}
+
+void
+epan_dissect_prime_hfid(epan_dissect_t *edt, int hfid)
+{
+ proto_tree_prime_hfid(edt->tree, hfid);
}
/* ----------------------- */
diff --git a/epan/epan.h b/epan/epan.h
index 41bf18e437..1c743e80f3 100644
--- a/epan/epan.h
+++ b/epan/epan.h
@@ -206,11 +206,16 @@ void
epan_dissect_file_run_with_taps(epan_dissect_t *edt, struct wtap_pkthdr *phdr,
tvbuff_t *tvb, frame_data *fd, struct epan_column_info *cinfo);
-/** Prime a proto_tree using the fields/protocols used in a dfilter. */
+/** Prime an epan_dissect_t's proto_tree using the fields/protocols used in a dfilter. */
WS_DLL_PUBLIC
void
epan_dissect_prime_dfilter(epan_dissect_t *edt, const struct epan_dfilter *dfcode);
+/** Prime an epan_dissect_t's proto_tree with a field/protocol specified by its hfid */
+WS_DLL_PUBLIC
+void
+epan_dissect_prime_hfid(epan_dissect_t *edt, int hfid);
+
/** fill the dissect run output into the packet list columns */
WS_DLL_PUBLIC
void
diff --git a/epan/proto.h b/epan/proto.h
index 8277cde828..51e4dc0bac 100644
--- a/epan/proto.h
+++ b/epan/proto.h
@@ -2088,7 +2088,7 @@ WS_DLL_PUBLIC header_field_info* proto_registrar_get_byname(const char *field_na
/** Get the header_field id based upon a field name.
@param field_name the field name to search for
@return the field id for the registered item */
-extern int proto_registrar_get_id_byname(const char *field_name);
+WS_DLL_PUBLIC int proto_registrar_get_id_byname(const char *field_name);
/** Get enum ftenum FT_ of registered header_field number n.
@param n item # n (0-indexed)
diff --git a/ui/gtk/rtp_analysis.c b/ui/gtk/rtp_analysis.c
index 846635e206..2815e73d88 100644
--- a/ui/gtk/rtp_analysis.c
+++ b/ui/gtk/rtp_analysis.c
@@ -3719,75 +3719,6 @@ create_rtp_dialog(user_data_t* user_data)
/****************************************************************************/
-static gboolean
-process_node(proto_node *ptree_node, header_field_info *hfinformation,
- const gchar* proto_field, guint32* p_result)
-{
- field_info *finfo;
- proto_node *proto_sibling_node;
- header_field_info *hfssrc;
- ipv4_addr_and_mask *ipv4;
-
- finfo = PNODE_FINFO(ptree_node);
-
- /* Caller passed top of the protocol tree. Expected child node */
- g_assert(finfo);
-
- if (hfinformation == (finfo->hfinfo)) {
- hfssrc = proto_registrar_get_byname(proto_field);
- if (hfssrc == NULL)
- return FALSE;
- for (ptree_node = ptree_node->first_child;
- ptree_node != NULL;
- ptree_node = ptree_node->next) {
- finfo = PNODE_FINFO(ptree_node);
- if (hfssrc == finfo->hfinfo) {
- if (hfinformation->type == FT_IPv4) {
- ipv4 = (ipv4_addr_and_mask *)fvalue_get(&finfo->value);
- *p_result = ipv4_get_net_order_addr(ipv4);
- }
- else {
- *p_result = fvalue_get_uinteger(&finfo->value);
- }
- return TRUE;
- }
- }
- if (!ptree_node)
- return FALSE;
- }
-
- proto_sibling_node = ptree_node->next;
-
- if (proto_sibling_node) {
- return process_node(proto_sibling_node, hfinformation, proto_field, p_result);
- }
- else
- return FALSE;
-}
-
-/****************************************************************************/
-static gboolean
-get_int_value_from_proto_tree(proto_tree *protocol_tree,
- const gchar *proto_name,
- const gchar *proto_field,
- guint32 *p_result)
-{
- proto_node *ptree_node;
- header_field_info *hfinformation;
-
- hfinformation = proto_registrar_get_byname(proto_name);
- if (hfinformation == NULL)
- return FALSE;
-
- ptree_node = ((proto_node *)protocol_tree)->first_child;
- if (!ptree_node)
- return FALSE;
-
- return process_node(ptree_node, hfinformation, proto_field, p_result);
-}
-
-
-/****************************************************************************/
void
rtp_analysis(address *src_fwd,
guint32 port_src_fwd,
@@ -3921,9 +3852,9 @@ rtp_analysis_cb(GtkAction *action _U_, gpointer user_data _U_)
address dst_rev;
guint32 port_dst_rev;
guint32 ssrc_rev = 0;
- unsigned int version_fwd;
+ GPtrArray *gp;
- const gchar *filter_text = "rtp && rtp.version && rtp.ssrc && (ip || ipv6)";
+ const gchar filter_text[] = "rtp && rtp.version == 2 && rtp.ssrc && (ip || ipv6)";
dfilter_t *sfcode;
gchar *err_msg;
capture_file *cf;
@@ -3932,8 +3863,16 @@ rtp_analysis_cb(GtkAction *action _U_, gpointer user_data _U_)
GList *filtered_list = NULL;
guint nfound;
epan_dissect_t edt;
+ int hfid_rtp_ssrc;
rtp_stream_info_t *strinfo;
+ /* Try to get the hfid for "rtp.ssrc". */
+ hfid_rtp_ssrc = proto_registrar_get_id_byname("rtp.ssrc");
+ if (hfid_rtp_ssrc == -1) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "There is no \"rtp.ssrc\" field in this version of Wireshark.");
+ return;
+ }
+
/* Try to compile the filter. */
if (!dfilter_compile(filter_text, &sfcode, &err_msg)) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
@@ -3953,13 +3892,17 @@ rtp_analysis_cb(GtkAction *action _U_, gpointer user_data _U_)
return; /* error reading the record */
epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
epan_dissect_prime_dfilter(&edt, sfcode);
+ epan_dissect_prime_hfid(&edt, hfid_rtp_ssrc);
epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
- /* if it is not an rtp packet, show the rtpstream dialog */
+ /*
+ * Packet must be an RTPv2 packet with an SSRC; we use the filter to
+ * check.
+ */
if (!dfilter_apply_edt(sfcode, &edt)) {
epan_dissect_cleanup(&edt);
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Please select an RTP packet.");
+ "Please select an RTPv2 packet with an SSID.");
return;
}
@@ -3975,19 +3918,16 @@ rtp_analysis_cb(GtkAction *action _U_, gpointer user_data _U_)
port_src_rev = edt.pi.destport;
port_dst_rev = edt.pi.srcport;
- /* check if it is RTP Version 2 */
- if (!get_int_value_from_proto_tree(edt.tree, "rtp", "rtp.version", &version_fwd) || version_fwd != 2) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Only RTP version 2 is supported.");
- return;
- }
-
/* now we need the SSRC value of the current frame */
- if (!get_int_value_from_proto_tree(edt.tree, "rtp", "rtp.ssrc", &ssrc_fwd)) {
+ gp = proto_get_finfo_ptr_array(edt.tree, hfid_rtp_ssrc);
+ if (gp == NULL || gp->len == 0) {
+ /* XXX - should not happen, as the filter inculdes rtp.ssrc */
+ epan_dissect_cleanup(&edt);
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"SSRC value not found.");
return;
}
+ ssrc_fwd = fvalue_get_uinteger(&((field_info *)gp->pdata[0])->value);
/* Scan for rtpstream */
rtpstream_scan(rtpstream_dlg_get_tapinfo(), &cfile, NULL);
diff --git a/ui/qt/rtp_analysis_dialog.cpp b/ui/qt/rtp_analysis_dialog.cpp
index ae819d48ad..66ac236e94 100644
--- a/ui/qt/rtp_analysis_dialog.cpp
+++ b/ui/qt/rtp_analysis_dialog.cpp
@@ -372,7 +372,7 @@ RtpAnalysisDialog::RtpAnalysisDialog(QWidget &parent, CaptureFile &cf, struct _r
findStreams();
}
- if (num_streams_ < 1) {
+ if (err_str_.isEmpty() && num_streams_ < 1) {
err_str_ = tr("No streams found.");
}
@@ -1366,75 +1366,6 @@ void RtpAnalysisDialog::saveCsv(RtpAnalysisDialog::StreamDirection direction)
}
}
-// Adapted from rtp_analysis.c:process_node
-guint32 RtpAnalysisDialog::processNode(proto_node *ptree_node, header_field_info *hfinformation, const gchar *proto_field, bool *ok)
-{
- field_info *finfo;
- proto_node *proto_sibling_node;
- header_field_info *hfssrc;
- ipv4_addr_and_mask *ipv4;
-
- finfo = PNODE_FINFO(ptree_node);
-
- /* Caller passed top of the protocol tree. Expected child node */
- g_assert(finfo);
-
- if (hfinformation == (finfo->hfinfo)) {
- hfssrc = proto_registrar_get_byname(proto_field);
- if (hfssrc == NULL) {
- return 0;
- }
- for (ptree_node = ptree_node->first_child;
- ptree_node != NULL;
- ptree_node = ptree_node->next) {
- finfo = PNODE_FINFO(ptree_node);
- if (hfssrc == finfo->hfinfo) {
- guint32 result;
- if (hfinformation->type == FT_IPv4) {
- ipv4 = (ipv4_addr_and_mask *)fvalue_get(&finfo->value);
- result = ipv4_get_net_order_addr(ipv4);
- } else {
- result = fvalue_get_uinteger(&finfo->value);
- }
- if (ok) *ok = true;
- return result;
- }
- }
- if (!ptree_node) {
- return 0;
- }
- }
-
- proto_sibling_node = ptree_node->next;
-
- if (proto_sibling_node) {
- return processNode(proto_sibling_node, hfinformation, proto_field, ok);
- } else {
- return 0;
- }
-}
-
-// Adapted from rtp_analysis.c:get_int_value_from_proto_tree
-guint32 RtpAnalysisDialog::getIntFromProtoTree(proto_tree *protocol_tree, const gchar *proto_name, const gchar *proto_field, bool *ok)
-{
- proto_node *ptree_node;
- header_field_info *hfinformation;
-
- if (ok) *ok = false;
-
- hfinformation = proto_registrar_get_byname(proto_name);
- if (hfinformation == NULL) {
- return 0;
- }
-
- ptree_node = ((proto_node *)protocol_tree)->first_child;
- if (!ptree_node) {
- return 0;
- }
-
- return processNode(ptree_node, hfinformation, proto_field, ok);
-}
-
bool RtpAnalysisDialog::eventFilter(QObject *, QEvent *event)
{
if (event->type() != QEvent::KeyPress) return false;
@@ -1464,14 +1395,24 @@ void RtpAnalysisDialog::graphClicked(QMouseEvent *event)
void RtpAnalysisDialog::findStreams()
{
- const gchar *filter_text = "rtp && rtp.version && rtp.ssrc";
+ const gchar filter_text[] = "rtp && rtp.version == 2 && rtp.ssrc && (ip || ipv6)";
dfilter_t *sfcode;
gchar *err_msg;
+ /* Try to get the hfid for "rtp.ssrc". */
+ int hfid_rtp_ssrc = proto_registrar_get_id_byname("rtp.ssrc");
+ if (hfid_rtp_ssrc == -1) {
+ err_str_ = tr("There is no \"rtp.ssrc\" field in this version of Wireshark.");
+ updateWidgets();
+ return;
+ }
+
+ /* Try to compile the filter. */
if (!dfilter_compile(filter_text, &sfcode, &err_msg)) {
- QMessageBox::warning(this, tr("No RTP packets found"), QString("%1").arg(err_msg));
+ err_str_ = QString(err_msg);
g_free(err_msg);
- close();
+ updateWidgets();
+ return;
}
if (!cap_file_.capFile() || !cap_file_.capFile()->current_frame) close();
@@ -1484,14 +1425,18 @@ void RtpAnalysisDialog::findStreams()
epan_dissect_init(&edt, cap_file_.capFile()->epan, TRUE, FALSE);
epan_dissect_prime_dfilter(&edt, sfcode);
+ epan_dissect_prime_hfid(&edt, hfid_rtp_ssrc);
epan_dissect_run(&edt, cap_file_.capFile()->cd_t, &cap_file_.capFile()->phdr,
frame_tvbuff_new_buffer(fdata, &cap_file_.capFile()->buf), fdata, NULL);
- // This shouldn't happen (the menu item should be disabled) but check anyway
+ /*
+ * Packet must be an RTPv2 packet with an SSRC; we use the filter to
+ * check.
+ */
if (!dfilter_apply_edt(sfcode, &edt)) {
epan_dissect_cleanup(&edt);
dfilter_free(sfcode);
- err_str_ = tr("Please select an RTP packet");
+ err_str_ = tr("Please select an RTPv2 packet with an SSRC value");
updateWidgets();
return;
}
@@ -1510,23 +1455,16 @@ void RtpAnalysisDialog::findStreams()
port_src_rev_ = edt.pi.destport;
port_dst_rev_ = edt.pi.srcport;
- /* Check if it is RTP Version 2 */
- unsigned int version_fwd;
- bool ok;
- version_fwd = getIntFromProtoTree(edt.tree, "rtp", "rtp.version", &ok);
- if (!ok || version_fwd != 2) {
- err_str_ = tr("RTP version %1 found. Only version 2 is supported.").arg(version_fwd);
- updateWidgets();
- return;
- }
-
/* now we need the SSRC value of the current frame */
- ssrc_fwd_ = getIntFromProtoTree(edt.tree, "rtp", "rtp.ssrc", &ok);
- if (!ok) {
+ GPtrArray *gp = proto_get_finfo_ptr_array(edt.tree, hfid_rtp_ssrc);
+ if (gp == NULL || gp->len == 0) {
+ /* XXX - should not happen, as the filter includes rtp.ssrc */
+ epan_dissect_cleanup(&edt);
err_str_ = tr("SSRC value not found.");
updateWidgets();
return;
}
+ ssrc_fwd_ = fvalue_get_uinteger(&((field_info *)gp->pdata[0])->value);
/* Register the tap listener */
memset(&tapinfo_, 0, sizeof(rtpstream_tapinfo_t));