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>
This commit is contained in:
parent
b708c4a48c
commit
d1f78230c9
|
@ -1312,7 +1312,10 @@ get_diameter_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
|
|||
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;
|
||||
|
@ -1320,11 +1323,11 @@ check_diameter(tvbuff_t *tvb)
|
|||
|
||||
/* Ensure we don't throw an exception trying to do these heuristics */
|
||||
if (tvb_captured_length(tvb) < 5)
|
||||
return FALSE;
|
||||
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
|
||||
|
@ -1332,7 +1335,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:
|
||||
*
|
||||
|
@ -1349,19 +1352,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;
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
|
@ -1371,7 +1374,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);
|
||||
}
|
||||
|
@ -1379,11 +1382,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);
|
||||
|
|
Loading…
Reference in New Issue