Wireshark-dev: [Wireshark-dev] TCP dissector design
From: "John Dill" <John.Dill@xxxxxxxxxxxxxxxxx>
Date: Thu, 17 Apr 2014 14:48:51 -0400
Title: TCP dissector design

I have a closed network system where there are several TCP conversations
that transmit the same kind of data, but use different application layer
messages structures.  It seems to be based on the age of the code,
where TCP conversations from older code use a different application
message structure (with different headers) than newer ones.

They would like to be able to see all the data fields under the same
protocol, whether the message came from a UDP packet or TCP packet.
However, I'm a bit confused as to how to structure the dissector to
be able to handle this properly.

For the UDP, I have a top level dissector that uses an heuristic to
receive all UDP packets and discover which of these UDP messages are
the protocol's application messages.  I represent the protocol with
the acronym as "XYZ".

\code snippet

static void xyz_dissect_app_msg_fmt1(tvbuff_t *tvb, packet_info *pinfo, gint offset, proto_tree *tree);
static void xyz_dissect_app_msg_fmt2(tvbuff_t *tvb, packet_info *pinfo, gint offset, proto_tree *tree);

/* Forward declare the XYZ message sub-dissectors to handle each Message ID. */
static void dissect_xyz_message1(tvbuff_t *tvb, gint offset, proto_tree *tree);
...
static void dissect_xyz_messageN(tvbuff_t *tvb, gint offset, proto_tree *tree);
[There is a switch table in each app_msg_fmt dissector that calls
the appropriate message subdissector based on an id.]

/* Forward declare the hand-off registration. */
void proto_register_xyz(void);
void proto_reg_handoff_xyz(void);

/* This is the main XYZ dissector that gets called for every UDP packet
   because it is registered as a heuristic filter under the UDP protocol. */
static gboolean
dissect_xyz_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  ...

    if (tree)
    {
      if (msg_fmt == APPLICATION_MSG_FMT1) {
        xyz_dissect_app_msg_fmt1(tvb, pinfo, offset, xyz_tree);
      }
      else if (msg_fmt == APPLICATION_MSG_FMT2) {
        xyz_dissect_app_msg_fmt2(tvb, pinfo, offset, xyz_tree);
      }
    }

  ...
}

static gboolean
dissect_xyz_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
  return dissect_xyz_udp(tvb, pinfo, tree);
}

void proto_register_xyz(void)
{
  static hf_register_info hf[] = ...
  static gint *ett[] = ...

  /* proto_register_protocol(name, short_name, abbreviation) */
  proto_xyz = proto_register_protocol("XYZ Protocol",
                                      "XYZ",
                                      "xyz");

  /* The macro 'array_length' calculates the number of elements of a
     fixed-size array at the compile phase. */
  proto_register_field_array(proto_xyz, hf, array_length(hf));
  proto_register_subtree_array(ett, array_length(ett));

  /* Register configuration options for the XYZ protocol dissector. */
  {
    module_t *xyz_module;
    xyz_module = prefs_register_protocol(proto_xyz, proto_reg_handoff_xyz);

    ...
  }

  register_dissector("xyz", dissect_xyz_udp, proto_xyz);
}

void
proto_reg_handoff_xyz(void)
{
  heur_dissector_add("udp", dissect_xyz_heur, proto_xyz);
}
\endcode

The TCP dissectors can be split up into three families (as far as I
know), where port family A uses the older application message
structure and port family B uses the new application message
structure, and one port C uses its own separate custom application
message format.

Ideally, they would like to see all the messages under one protocol
family 'XYZ', regardless of whether it came from a TCP or UDP packet.
All the TCP conversations require fragments to be assembled.  Can
someone offer some advice on how to structure the dissector registration
so that I can handle the TCP messages in this scenario.  Is there a
dissector already developed that kind of matches this scenario that
I can glean some ideas from?

Thanks,
John Dill