diff options
author | Jeff Morriss <jeff.morriss.ws@gmail.com> | 2015-05-11 15:45:04 -0400 |
---|---|---|
committer | Jeff Morriss <jeff.morriss.ws@gmail.com> | 2015-05-12 14:04:09 +0000 |
commit | ab74ebd958969072c8004fe5e197542f26bc5a58 (patch) | |
tree | 57864313b3576663a327ad0e0666ea4f451ce336 | |
parent | 8b7f2c9e977b275f7fdd5f509b4ad734a04de9d4 (diff) | |
download | wireshark-ab74ebd958969072c8004fe5e197542f26bc5a58.tar.gz wireshark-ab74ebd958969072c8004fe5e197542f26bc5a58.tar.bz2 wireshark-ab74ebd958969072c8004fe5e197542f26bc5a58.zip |
Fix Diameter reassembly when the captured tvb length is less than 5 bytes.
Since Diameter does heuristic checks before calling tcp_dissect_pdus() we
have to "manually" ask for more data if the tvb is too short for our
heuristics.
Bug: 11183
Change-Id: I14c36042306b532b53df80cc3971866b76094084
Reviewed-on: https://code.wireshark.org/review/8405
Reviewed-by: Evan Huus <eapache@gmail.com>
Petri-Dish: Jeff Morriss <jeff.morriss.ws@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Jeff Morriss <jeff.morriss.ws@gmail.com>
(cherry picked from commit d1f78230c9dcc631659f3e5f0008bf01115c2d69)
Conflicts:
epan/dissectors/packet-diameter.c
Reviewed-on: https://code.wireshark.org/review/8428
-rw-r--r-- | epan/dissectors/packet-diameter.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/epan/dissectors/packet-diameter.c b/epan/dissectors/packet-diameter.c index d15de8122d..f6f427a298 100644 --- a/epan/dissectors/packet-diameter.c +++ b/epan/dissectors/packet-diameter.c @@ -1238,19 +1238,22 @@ get_diameter_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset) return tvb_get_ntoh24(tvb, offset + 1); } -static gboolean +#define NOT_DIAMETER 0 +#define IS_DIAMETER 1 +#define NOT_ENOUGH_DATA 2 +static gint check_diameter(tvbuff_t *tvb) { guint32 diam_len; guint8 flags; /* Ensure we don't throw an exception trying to do these heuristics */ - if (tvb_length(tvb) < 5) - return FALSE; + if (tvb_captured_length(tvb) < 5) + return NOT_ENOUGH_DATA; /* Check if the Diameter version is 1 */ if (tvb_get_guint8(tvb, 0) != 1) - return FALSE; + return NOT_DIAMETER; /* Check if the message size is reasonable. * Diameter messages can technically be of any size; this limit @@ -1258,7 +1261,7 @@ check_diameter(tvbuff_t *tvb) */ diam_len = tvb_get_ntoh24(tvb, 1); if (diam_len > 65534) - return FALSE; + return NOT_DIAMETER; /* Diameter minimum message length: * @@ -1275,19 +1278,19 @@ check_diameter(tvbuff_t *tvb) * --> 36 bytes */ if (diam_len < 36) - return FALSE; + return NOT_DIAMETER; flags = tvb_get_guint8(tvb, 4); /* Check if any of the Reserved flag bits are set */ if (flags & 0x0f) - return FALSE; + return NOT_DIAMETER; /* Check if both the R- and E-bits are set */ if ((flags & DIAM_FLAGS_R) && (flags & DIAM_FLAGS_E)) - return FALSE; + return NOT_DIAMETER; - return TRUE; + return IS_DIAMETER; } /*****************************************************************/ @@ -1297,7 +1300,7 @@ check_diameter(tvbuff_t *tvb) static int dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { - if (!check_diameter(tvb)) + if (check_diameter(tvb) != IS_DIAMETER) return 0; return dissect_diameter_common(tvb, pinfo, tree, data); } @@ -1305,11 +1308,22 @@ dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data static int dissect_diameter_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { - /* Check if we have the start of a PDU or if this is segment */ - if (!check_diameter(tvb)) { + gint is_diam = check_diameter(tvb); + + if (is_diam == NOT_DIAMETER) { + /* We've probably been given a frame that's not the start of + * a PDU. + */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DIAMETER"); col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); call_dissector(data_handle, tvb, pinfo, tree); + } else if (is_diam == NOT_ENOUGH_DATA) { + /* Since we're doing our heuristic checks before + * tcp_dissect_pdus() (since we we can't do heuristics once + * we're in there) we sometimes have to ask for more data... + */ + pinfo->desegment_offset = 0; + pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; } else { tcp_dissect_pdus(tvb, pinfo, tree, gbl_diameter_desegment, 4, get_diameter_pdu_len, dissect_diameter_common, data); |