Wireshark-dev: Re: [Wireshark-dev] dissecting TCP packets with multiple PDUs

From: John Dill <John.Dill@xxxxxxxxxxxxxxxxx>
Date: Fri, 5 Aug 2016 17:39:42 +0000
>Message: 1
>Date: Fri, 5 Aug 2016 14:47:59 +0100
>From: Graham Bloice <graham.bloice@xxxxxxxxxxxxx>
>To: Developer support list for Wireshark <wireshark-dev@xxxxxxxxxxxxx>
>Subject: Re: [Wireshark-dev] dissecting TCP packets with multiple PDUs
>
>>On 5 August 2016 at 14:08, John Dill <John.Dill@xxxxxxxxxxxxxxxxx> wrote:
>>
>> I have a TCP protocol that sends multiple PDUs.  So far, my dissector
>> seems to handle the cases where one PDU is split across multiple frames,
>> and when multiple PDUs are dissected in one frame.  Unfortunately, I'm
>> having issues where the TCP dissection stops if I have multiple PDUs that
>> are split inside a frame, e.g.
>>
>>
>>
>> packet 37104 TCP segment (536)
>>
>> packet 37167 TCP segment (498) - creates reassembled TCP size of (1034)
>> which is correct
>>
>> However, packet 37167 has the start of another PDU containing 38 bytes.  I
>> can't seem to get the dissector to recognize the start of it.
>>
>> ?I printed out the captured length, but it always seems to be 1034.  I'm
>> not sure how to recognize that the current frame has leftover bytes to
>> start a new dissection.
>>
>> Is there an example plugin that someone can suggest that I can investigate
>> to see how this scenario is handled?
>>
>> Thanks,
>>
>> John D.
>
>
>Is your dissector returning the number of bytes it dissected?

Yes, I am returning tvb_length(tvb), and the length matches the expected size of the Reassembled TCP packet.  It appears everything makes sense from that perspective.

Upon closer inspection, I found that one of the frames in a sequence of PDUs appears to have been dropped, so the PDU length read in the earlier frame didn't match the data.  I believe that caused the TCP dissector to not parse properly.

I'm looking at another capture, and it appears to have the same issue where one of the last frames of a sequence of PDUs is not captured.  I thought I had a problem with my dissector code, but now it looks more like a protocol software bug.

On a different note...

One problem I have is that I'm creating multiple subtrees for a protocol when two PDUs are found in the same frame.  What's the best way to avoid this?

\code
gint
dissect_mk32_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
  proto_tree *mk32_tree = NULL;
  proto_item *ti;                 /* ti := tree item */
  gint       offset = 0;

  /*
   * This is a high level dissector targeting a re-assembled TCP
   * packet containing MK32 messages.  The main responsibilities
   * of the dissector is to control the meta data displayed in the
   * "Packet List" pane, and to display the packet contents in the
   * "Packet Details" pane.  Typically, the dissection details of
   * higher level protocol messages (MK32) and their contents are
   * handled in message specific sub-dissectors.
   */

  /* Change the Protocol column to MK32 in addition to TCP. */
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP/MK32");

  /* Change the Info column to indicate what? */

  /* Process the remaining data only if actively viewed in the
     "Packet Details" pane (when 'tree != NULL'). */
  if (tree)
  {
    ti = proto_tree_add_item(tree, proto_mk32, tvb, offset, -1, ENC_BIG_ENDIAN);
    mk32_tree = proto_item_add_subtree(ti, ett_mk32);

    mk32_dissect_messages(tvb, pinfo, offset, mk32_tree);
  }
  return tvb_length(tvb);
}
\endcode

If the frame has multiple PDUs, I create multiple mk32_tree subtrees instead of just one.  Is there any recommended heuristic or method I should use to determine whether my PDU is in the same frame as another so that I don't make duplicate protocol subtrees, e.g. "if (tree && <current_frame_has_not_already_processed_another_PDU_already>)"

I thought about static variables, or maybe using the 'data' member.  Any suggestions?

Thanks,
John D.