From Alton MacDonald:

A TLV can be larger that the MIH payload. In this case the packet should be fragmented and controlled with the help of two fields in the MIH header. The attached patch checks these fields and dissects the TLVs if the MIH payload is not fragmented.

Additionally, if a TLV is detected larger than the payload size it is marked as a fragmented TLV and not dissected. This would be the case if the previously mentioned fields were not set correctly as their use under this scenario is not explicitly defined in the 802.21 standard.

https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5881

svn path=/trunk/; revision=47014
This commit is contained in:
Anders Broman 2013-01-10 07:36:32 +00:00
parent 68160dac5c
commit 2d44d2e05c
1 changed files with 44 additions and 29 deletions

View File

@ -1986,7 +1986,9 @@ static void dissect_mih(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
guint8 type = 0;
proto_tree *mid_tree = NULL;
proto_tree *tlv_tree = NULL;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "MIH");
guint8 fragment = 0;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "MIH");
col_clear(pinfo->cinfo,COL_INFO);
if (tree)
{
@ -2005,7 +2007,8 @@ static void dissect_mih(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree_add_item(ver_flags_tree, hf_mih_ack_resp, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(ver_flags_tree, hf_mih_uir, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(ver_flags_tree, hf_mih_more_frag, tvb, offset, 1, ENC_BIG_ENDIAN);
fragment = tvb_get_guint8(tvb, offset);
fragment = fragment << 7;
}
offset += 1;
@ -2013,6 +2016,7 @@ static void dissect_mih(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/*flags and version tree is done.....*/
proto_tree_add_item(mih_tree, hf_mih_frag_no, tvb, offset, 1, ENC_BIG_ENDIAN);
fragment = fragment + (tvb_get_guint8(tvb, offset)>>1);
/*for MIH message ID*/
item = proto_tree_add_item(mih_tree, hf_mih_mid, tvb, offset + 1, 2, ENC_BIG_ENDIAN);
@ -2082,7 +2086,7 @@ static void dissect_mih(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/*now the type length values list is present get them and decode it...
loop for showing all the tlvs....*/
while(payload_length > 0)
while(payload_length > 0 && fragment==0)
{
/* Adding a third case here since the 802.21 standard defines 3 cases */
/*extract length*/
@ -2141,37 +2145,48 @@ static void dissect_mih(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
len_of_len = 1;
/*for type...*/
item = proto_tree_add_text(mih_tree, tvb, offset, 1 + len_of_len + (guint32)len, "MIH TLV : %s", val_to_str(tvb_get_guint8(tvb, offset), typevaluenames, "UNKNOWN"));
tlv_tree = proto_item_add_subtree(item, ett_tlv);
if(tlv_tree)
/*TODO: TLVs greater than the payload_length are fragmented, and currently not parsed*/
if(len <= (guint64)payload_length)
{
proto_tree_add_item(tlv_tree, hf_mih_type, tvb, offset, 1, ENC_BIG_ENDIAN);
type = tvb_get_guint8(tvb, offset);
/*for length...*/
if(len_of_len == 1)
/*for type...*/
item = proto_tree_add_text(mih_tree, tvb, offset, 1 + len_of_len + (guint32)len, "MIH TLV : %s", val_to_str(tvb_get_guint8(tvb, offset), typevaluenames, "UNKNOWN"));
tlv_tree = proto_item_add_subtree(item, ett_tlv);
if(tlv_tree)
{
proto_tree_add_item(tlv_tree, hf_mih_type_length, tvb, offset+1, len_of_len, ENC_BIG_ENDIAN);
}
else if(len_of_len>1 && len_of_len<=5)
{
proto_tree_add_item(tlv_tree, hf_mih_type_length_ext, tvb, offset+2, len_of_len-1, ENC_BIG_ENDIAN);
}
proto_tree_add_item(tlv_tree, hf_mih_type, tvb, offset, 1, ENC_BIG_ENDIAN);
type = tvb_get_guint8(tvb, offset);
/*for length...*/
if(len_of_len == 1)
{
proto_tree_add_item(tlv_tree, hf_mih_type_length, tvb, offset+1, len_of_len, ENC_BIG_ENDIAN);
}
else if(len_of_len>1 && len_of_len<=5)
{
proto_tree_add_item(tlv_tree, hf_mih_type_length_ext, tvb, offset+2, len_of_len-1, ENC_BIG_ENDIAN);
}
}
offset += 1 + len_of_len;
/*For Value fields*/
/*TODO: this assumes the maximum value length is 2^32. Dissecting bigger data fields would require breaking the data into chunks*/
if(len<(2^32)){
dissect_mih_tlv(tvb, offset, tlv_tree, type, (guint32)len);
offset += (guint32)len;
payload_length -= (1 + len_of_len + (guint16)len);
}else{
return;
}
}
else
{
proto_tree_add_text(mih_tree, tvb, offset, -1, "FRAGMENTED TLV");
payload_length = 0;
}
offset += 1 + len_of_len;
/*For Value fields*/
/*TODO: this assumes the maximum value length is 2^32. Dissecting bigger data fields would require breaking the data into chunks*/
if(len<(2^32)){
dissect_mih_tlv(tvb, offset, tlv_tree, type, (guint32)len);
offset += (guint32)len;
payload_length -= (1 + len_of_len + (guint16)len);
}else{
return;
}
}
if(fragment!=0)
proto_tree_add_text(mih_tree, tvb, offset, -1, "FRAGMENTED TLV");
}
/*dissector initialistaion*/