1 // WSDG Chapter Dissection
11 Each dissector decodes its part of the protocol, and then hands off
12 decoding to subsequent dissectors for an encapsulated protocol.
14 Every dissection starts with the Frame dissector which dissects the packet
15 details of the capture file itself (e.g. timestamps). From there it passes the
16 data on to the lowest-level data dissector, e.g. the Ethernet dissector for
17 the Ethernet header. The payload is then passed on to the next dissector (e.g.
18 IP) and so on. At each stage, details of the packet will be decoded and
21 Dissection can be implemented in two possible ways. One is to have a dissector
22 module compiled into the main program, which means it’s always available.
23 Another way is to make a plugin (a shared library or DLL) that registers itself
26 There is little difference in having your dissector as either a plugin or
27 built-in. On the Windows platform you have limited function access through the
28 ABI exposed by functions declared as WS_DLL_PUBLIC.
30 The big plus is that your rebuild cycle for a plugin is much shorter than for a
31 built-in one. So starting with a plugin makes initial development simpler, while
32 the finished code may make more sense as a built-in dissector.
35 .Read README.dissector
37 The file _doc/README.dissector_ contains detailed information about implementing
38 a dissector. In many cases it is more up to date than this document.
43 === Adding a basic dissector
45 Let’s step through adding a basic dissector. We'll start with the made up "foo"
46 protocol. It consists of the following basic items.
48 * A packet type - 8 bits, possible values: 1 - initialisation, 2 - terminate, 3 - data.
50 * A set of flags stored in 8 bits, 0x01 - start packet, 0x02 - end packet, 0x04 - priority packet.
52 * A sequence number - 16 bits.
58 ==== Setting up the dissector
60 The first decision you need to make is if this dissector will be a
61 built-in dissector, included in the main program, or a plugin.
63 Plugins are the easiest to write initially, so let’s start with that.
64 With a little care, the plugin can be made to run as a built-in
65 easily too so we haven't lost anything.
67 .Dissector Initialisation.
72 #include <epan/packet.h>
76 static int proto_foo = -1;
80 proto_register_foo(void)
82 proto_foo = proto_register_protocol (
83 "FOO Protocol", /* name */
84 "FOO", /* short name */
91 Let’s go through this a bit at a time. First we have some boilerplate
92 include files. These will be pretty constant to start with.
94 Next we have an int that is initialised to `-1` that records our protocol.
95 This will get updated when we register this dissector with the main program.
96 It’s good practice to make all variables and functions that aren't exported
97 static to keep name space pollution down. Normally this isn't a problem unless your
98 dissector gets so big it has to span multiple files.
100 Then a `#define` for the UDP port that carries _foo_ traffic.
102 Now that we have the basics in place to interact with the main program, we'll
103 start with two protocol dissector setup functions.
105 First we'll call `proto_register_protocol()` which registers the protocol. We
106 can give it three names that will be used for display in various places. The
107 full and short name are used in e.g. the "Preferences" and "Enabled protocols"
108 dialogs as well as the generated field name list in the documentation. The
109 abbreviation is used as the display filter name.
111 Next we need a handoff routine.
117 proto_reg_handoff_foo(void)
119 static dissector_handle_t foo_handle;
121 foo_handle = create_dissector_handle(dissect_foo, proto_foo);
122 dissector_add_uint("udp.port", FOO_PORT, foo_handle);
127 What’s happening here? We are initialising the dissector. First we create a
128 dissector handle; It is associated with the foo protocol and with a routine to
129 be called to do the actual dissecting. Then we associate the handle with a UDP
130 port number so that the main program will know to call us when it gets UDP
131 traffic on that port.
133 The standard Wireshark dissector convention is to put `proto_register_foo()` and
134 `proto_reg_handoff_foo()` as the last two functions in the dissector source.
136 Now at last we get to write some dissecting code. For the moment we'll
137 leave it as a basic placeholder.
143 dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data _U_)
145 col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
146 /* Clear out stuff in the info column */
147 col_clear(pinfo->cinfo,COL_INFO);
149 return tvb_captured_length(tvb);
154 This function is called to dissect the packets presented to it. The packet data
155 is held in a special buffer referenced here as tvb. We shall become fairly
156 familiar with this as we get deeper into the details of the protocol. The packet
157 info structure contains general data about the protocol, and we can update
158 information here. The tree parameter is where the detail dissection takes place.
160 For now we'll do the minimum we can get away with. In the first line we set the
161 text of this to our protocol, so everyone can see it’s being recognised. The
162 only other thing we do is to clear out any data in the INFO column if it’s being
165 At this point we should have a basic dissector ready to compile and install.
166 It doesn't do much at present, other than identify the protocol and label it.
168 In order to compile this dissector and create a plugin a couple of support files
169 are required, besides the dissector source in _packet-foo.c_:
171 * _CMakeLists.txt_ - Contains the CMake file and version info for this plugin.
173 * _packet-foo.c_ - Your dissector source.
175 * _plugin.rc.in_ - Contains the DLL resource template for Windows. (optional)
177 You can find a good example for these files in the gryphon plugin directory.
178 _CMakeLists.txt_ has to be modified with the correct plugin name and version
179 info, along with the relevant files to compile.
180 In the main top-level source directory, copy CMakeListsCustom.txt.example to
181 CMakeListsCustom.txt and add the path of your plugin to the list in
182 CUSTOM_PLUGIN_SRC_DIR.
184 Compile the dissector to a DLL or shared library and either run Wireshark from
185 the build directory as detailed in <<ChSrcRunFirstTime>> or copy the plugin
186 binary into the plugin directory of your Wireshark installation and run that.
190 ==== Dissecting the details of the protocol
192 Now that we have our basic dissector up and running, let’s do something with it.
193 The simplest thing to do to start with is to just label the payload.
194 This will allow us to set up some of the parts we will need.
196 The first thing we will do is to build a subtree to decode our results into.
197 This helps to keep things looking nice in the detailed display.
199 .Plugin Packet Dissection.
203 dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
206 col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
207 /* Clear out stuff in the info column */
208 col_clear(pinfo->cinfo,COL_INFO);
210 proto_item *ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
212 return tvb_captured_length(tvb);
217 What we're doing here is adding a subtree to the dissection.
218 This subtree will hold all the details of this protocol and so not clutter
219 up the display when not required.
221 We are also marking the area of data that is being consumed by this
222 protocol. In our case it’s all that has been passed to us, as we're assuming
223 this protocol does not encapsulate another.
224 Therefore, we add the new tree node with `proto_tree_add_item()`,
225 adding it to the passed in tree, label it with the protocol, use the passed in
226 tvb buffer as the data, and consume from 0 to the end (-1) of this data.
227 ENC_NA ("not applicable") is specified as the "encoding" parameter.
229 After this change, there should be a label in the detailed display for the protocol,
230 and selecting this will highlight the remaining contents of the packet.
232 Now let’s go to the next step and add some protocol dissection. For this step
233 we'll need to construct a couple of tables that help with dissection. This needs
234 some additions to the `proto_register_foo()` function shown previously.
236 Two statically allocated arrays are added at the beginning of
237 `proto_register_foo()`. The arrays are then registered after the call to
238 `proto_register_protocol()`.
240 .Registering data structures.
244 proto_register_foo(void)
246 static hf_register_info hf[] = {
248 { "FOO PDU Type", "foo.type",
255 /* Setup protocol subtree array */
256 static gint *ett[] = {
260 proto_foo = proto_register_protocol (
261 "FOO Protocol", /* name */
262 "FOO", /* short name */
266 proto_register_field_array(proto_foo, hf, array_length(hf));
267 proto_register_subtree_array(ett, array_length(ett));
272 The variables `hf_foo_pdu_type` and `ett_foo` also need to be declared somewhere near the top of the file.
274 .Dissector data structure globals.
277 static int hf_foo_pdu_type = -1;
279 static gint ett_foo = -1;
283 Now we can enhance the protocol display with some detail.
285 .Dissector starting to dissect the packets.
288 proto_item *ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
289 proto_tree *foo_tree = proto_item_add_subtree(ti, ett_foo);
290 proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, 0, 1, ENC_BIG_ENDIAN);
294 Now the dissection is starting to look more interesting. We have picked apart
295 our first bit of the protocol. One byte of data at the start of the packet
296 that defines the packet type for foo protocol.
298 The `proto_item_add_subtree()` call has added a child node
299 to the protocol tree which is where we will do our detail dissection.
300 The expansion of this node is controlled by the `ett_foo`
301 variable. This remembers if the node should be expanded or not as you move
302 between packets. All subsequent dissection will be added to this tree,
303 as you can see from the next call.
304 A call to `proto_tree_add_item()` in the foo_tree,
305 this time using the `hf_foo_pdu_type` to control the formatting
306 of the item. The pdu type is one byte of data, starting at 0. We assume it is
307 in network order (also called big endian), so that is why we use `ENC_BIG_ENDIAN`.
308 For a 1-byte quantity, there is no order issue, but it is good practice to
309 make this the same as any multibyte fields that may be present, and as we will
310 see in the next section, this particular protocol uses network order.
312 If we look in detail at the `hf_foo_pdu_type` declaration in
313 the static array we can see the details of the definition.
315 * _hf_foo_pdu_type_ - The index for this node.
317 * _FOO PDU Type_ - The label for this item.
319 * _foo.type_ - This is the filter string. It enables us to type constructs such
320 as `foo.type=1` into the filter box.
322 * _FT_UINT8_ - This specifies this item is an 8bit unsigned integer.
323 This tallies with our call above where we tell it to only look at one byte.
325 * _BASE_DEC_ - For an integer type, this tells it to be printed as a decimal
326 number. It could be hexadecimal (BASE_HEX) or octal (BASE_OCT) if that made more sense.
328 We'll ignore the rest of the structure for now.
330 If you install this plugin and try it out, you'll see something that begins to look
333 Now let’s finish off dissecting the simple protocol. We need to add a few
334 more variables to the hfarray, and a couple more procedure calls.
336 .Wrapping up the packet dissection.
340 static int hf_foo_flags = -1;
341 static int hf_foo_sequenceno = -1;
342 static int hf_foo_initialip = -1;
346 dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
351 proto_item *ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
352 proto_tree *foo_tree = proto_item_add_subtree(ti, ett_foo);
353 proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
355 proto_tree_add_item(foo_tree, hf_foo_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
357 proto_tree_add_item(foo_tree, hf_foo_sequenceno, tvb, offset, 2, ENC_BIG_ENDIAN);
359 proto_tree_add_item(foo_tree, hf_foo_initialip, tvb, offset, 4, ENC_BIG_ENDIAN);
363 return tvb_captured_length(tvb);
367 proto_register_foo(void) {
371 { "FOO PDU Flags", "foo.flags",
376 { &hf_foo_sequenceno,
377 { "FOO PDU Sequence Number", "foo.seqn",
383 { "FOO PDU Initial IP", "foo.initialip",
395 This dissects all the bits of this simple hypothetical protocol. We've
396 introduced a new variable offsetinto the mix to help keep track of where we are
397 in the packet dissection. With these extra bits in place, the whole protocol is
400 ==== Improving the dissection information
402 We can certainly improve the display of the protocol with a bit of extra data.
403 The first step is to add some text labels. Let’s start by labeling the packet
404 types. There is some useful support for this sort of thing by adding a couple of
405 extra things. First we add a simple table of type to name.
408 .Naming the packet types.
411 static const value_string packettypenames[] = {
420 This is a handy data structure that can be used to look up a name for a value.
421 There are routines to directly access this lookup table, but we don't need to
422 do that, as the support code already has that added in. We just have to give
423 these details to the appropriate part of the data, using the `VALS` macro.
425 .Adding Names to the protocol.
429 { "FOO PDU Type", "foo.type",
431 VALS(packettypenames), 0x0,
437 This helps in deciphering the packets, and we can do a similar thing for the
438 flags structure. For this we need to add some more data to the table though.
440 .Adding Flags to the protocol.
443 #define FOO_START_FLAG 0x01
444 #define FOO_END_FLAG 0x02
445 #define FOO_PRIORITY_FLAG 0x04
447 static int hf_foo_startflag = -1;
448 static int hf_foo_endflag = -1;
449 static int hf_foo_priorityflag = -1;
452 dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
456 static const int* bits[] = {
462 proto_tree_add_bitmask(foo_tree, tvb, offset, hf_foo_flags, ett_foo, bits, ENC_BIG_ENDIAN);
466 return tvb_captured_length(tvb);
470 proto_register_foo(void) {
474 { "FOO PDU Start Flags", "foo.flags.start",
476 NULL, FOO_START_FLAG,
480 { "FOO PDU End Flags", "foo.flags.end",
485 { &hf_foo_priorityflag,
486 { "FOO PDU Priority Flags", "foo.flags.priority",
488 NULL, FOO_PRIORITY_FLAG,
498 Some things to note here. For the flags, as each bit is a different flag, we use
499 the type `FT_BOOLEAN`, as the flag is either on or off. Second, we include the flag
500 mask in the 7th field of the data, which allows the system to mask the relevant bit.
501 We've also changed the 5th field to 8, to indicate that we are looking at an 8 bit
502 quantity when the flags are extracted. Then finally we add the extra constructs
503 to the dissection routine.
505 This is starting to look fairly full featured now, but there are a couple of
506 other things we can do to make things look even more pretty. At the moment our
507 dissection shows the packets as "Foo Protocol" which whilst correct is a little
508 uninformative. We can enhance this by adding a little more detail. First, let’s
509 get hold of the actual value of the protocol type. We can use the handy function
510 `tvb_get_guint8()` to do this. With this value in hand, there are a couple of
511 things we can do. First we can set the INFO column of the non-detailed view to
512 show what sort of PDU it is - which is extremely helpful when looking at
513 protocol traces. Second, we can also display this information in the dissection
516 .Enhancing the display.
520 dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
523 guint8 packet_type = tvb_get_guint8(tvb, 0);
525 col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
526 /* Clear out stuff in the info column */
527 col_clear(pinfo->cinfo,COL_INFO);
528 col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s",
529 val_to_str(packet_type, packettypenames, "Unknown (0x%02x)"));
531 proto_item *ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
532 proto_item_append_text(ti, ", Type %s",
533 val_to_str(packet_type, packettypenames, "Unknown (0x%02x)"));
534 proto_tree *foo_tree = proto_item_add_subtree(ti, ett_foo);
535 proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
538 return tvb_captured_length(tvb);
543 So here, after grabbing the value of the first 8 bits, we use it with one of the
544 built-in utility routines `val_to_str()`, to lookup the value. If the value
545 isn't found we provide a fallback which just prints the value in hex. We use
546 this twice, once in the INFO field of the columns -- if it’s displayed, and
547 similarly we append this data to the base of our dissecting tree.
549 [[ChDissectTransformed]]
551 === How to handle transformed data
553 Some protocols do clever things with data. They might possibly
554 encrypt the data, or compress data, or part of it. If you know
555 how these steps are taken it is possible to reverse them within the
558 As encryption can be tricky, let’s consider the case of compression.
559 These techniques can also work for other transformations of data,
560 where some step is required before the data can be examined.
562 What basically needs to happen here, is to identify the data that needs
563 conversion, take that data and transform it into a new stream, and then call a
564 dissector on it. Often this needs to be done "on-the-fly" based on clues in the
565 packet. Sometimes this needs to be used in conjunction with other techniques,
566 such as packet reassembly. The following shows a technique to achieve this
569 .Decompressing data packets for dissection.
572 guint8 flags = tvb_get_guint8(tvb, offset);
574 if (flags & FLAG_COMPRESSED) { /* the remainder of the packet is compressed */
575 guint16 orig_size = tvb_get_ntohs(tvb, offset);
576 guchar *decompressed_buffer = (guchar*)wmem_alloc(pinfo->pool, orig_size);
578 decompress_packet(tvb_get_ptr(tvb, offset, -1),
579 tvb_captured_length_remaining(tvb, offset),
580 decompressed_buffer, orig_size);
581 /* Now re-setup the tvb buffer to have the new data */
582 next_tvb = tvb_new_child_real_data(tvb, decompressed_buffer, orig_size, orig_size);
583 add_new_data_source(pinfo, next_tvb, "Decompressed Data");
585 next_tvb = tvb_new_subset_remaining(tvb, offset);
588 /* process next_tvb from here on */
592 The first steps here are to recognise the compression. In this case a flag byte
593 alerts us to the fact the remainder of the packet is compressed. Next we
594 retrieve the original size of the packet, which in this case is conveniently
595 within the protocol. If it’s not, it may be part of the compression routine to
596 work it out for you, in which case the logic would be different.
598 So armed with the size, a buffer is allocated to receive the uncompressed data
599 using `wmem_alloc()` in pinfo->pool memory, and the packet is decompressed into
600 it. The `tvb_get_ptr()` function is useful to get a pointer to the raw data of
601 the packet from the offset onwards. In this case the decompression routine also
602 needs to know the length, which is given by the
603 `tvb_captured_length_remaining()` function.
605 Next we build a new tvb buffer from this data, using the
606 `tvb_new_child_real_data()` call. This data is a child of our original data, so
607 calling this function also acknowledges that. No need to call
608 `tvb_set_free_cb()` as the pinfo->pool was used (the memory block will be
609 automatically freed when the pinfo pool lifetime expires). Finally we add this
610 tvb as a new data source, so that the detailed display can show the
611 decompressed bytes as well as the original.
613 After this has been set up the remainder of the dissector can dissect the buffer
614 next_tvb, as it’s a new buffer the offset needs to be 0 as we start again from
615 the beginning of this buffer. To make the rest of the dissector work regardless
616 of whether compression was involved or not, in the case that compression was not
617 signaled, we use `tvb_new_subset_remaining()` to deliver us a new buffer based
618 on the old one but starting at the current offset, and extending to the end.
619 This makes dissecting the packet from this point on exactly the same regardless
622 [[ChDissectReassemble]]
624 === How to reassemble split packets
626 Some protocols have times when they have to split a large packet across
627 multiple other packets. In this case the dissection can't be carried out correctly
628 until you have all the data. The first packet doesn't have enough data,
629 and the subsequent packets don't have the expect format.
630 To dissect these packets you need to wait until all the parts have
631 arrived and then start the dissection.
633 The following sections will guide you through two common cases. For a
634 description of all possible functions, structures and parameters, see
637 [[ChDissectReassembleUdp]]
639 ==== How to reassemble split UDP packets
641 As an example, let’s examine a protocol that is layered on top of UDP that
642 splits up its own data stream. If a packet is bigger than some given size, it
643 will be split into chunks, and somehow signaled within its protocol.
645 To deal with such streams, we need several things to trigger from. We need to
646 know that this packet is part of a multi-packet sequence. We need to know how
647 many packets are in the sequence. We also need to know when we have all the
650 For this example we'll assume there is a simple in-protocol signaling mechanism
651 to give details. A flag byte that signals the presence of a multi-packet
652 sequence and also the last packet, followed by an ID of the sequence and a
653 packet sequence number.
656 msg_pkt ::= SEQUENCE {
660 last_fragment BOOLEAN,
663 msg_id INTEGER(0..65535),
664 frag_id INTEGER(0..65535),
669 .Reassembling fragments - Part 1
672 #include <epan/reassemble.h>
674 save_fragmented = pinfo->fragmented;
675 flags = tvb_get_guint8(tvb, offset); offset++;
676 if (flags & FL_FRAGMENT) { /* fragmented */
677 tvbuff_t* new_tvb = NULL;
678 fragment_data *frag_msg = NULL;
679 guint16 msg_seqid = tvb_get_ntohs(tvb, offset); offset += 2;
680 guint16 msg_num = tvb_get_ntohs(tvb, offset); offset += 2;
682 pinfo->fragmented = TRUE;
683 frag_msg = fragment_add_seq_check(msg_reassembly_table,
685 msg_seqid, NULL, /* ID for fragments belonging together */
686 msg_num, /* fragment sequence number */
687 tvb_captured_length_remaining(tvb, offset), /* fragment length - to the end */
688 flags & FL_FRAG_LAST); /* More fragments? */
692 We start by saving the fragmented state of this packet, so we can restore it
693 later. Next comes some protocol specific stuff, to dig the fragment data out of
694 the stream if it’s present. Having decided it is present, we let the function
695 `fragment_add_seq_check()` do its work. We need to provide this with a certain
696 amount of parameters:
698 * The `msg_reassembly_table` table is for bookkeeping and is described later.
700 * The tvb buffer we are dissecting.
702 * The offset where the partial packet starts.
704 * The provided packet info.
706 * The sequence number of the fragment stream. There may be several streams of
707 fragments in flight, and this is used to key the relevant one to be used for
710 * Optional additional data for identifying the fragment. Can be set to `NULL`
711 (as is done in the example) for most dissectors.
713 * msg_num is the packet number within the sequence.
715 * The length here is specified as the rest of the tvb as we want the rest of the packet data.
717 * Finally a parameter that signals if this is the last fragment or not. This
718 might be a flag as in this case, or there may be a counter in the protocol.
720 .Reassembling fragments part 2
723 new_tvb = process_reassembled_data(tvb, offset, pinfo,
724 "Reassembled Message", frag_msg, &msg_frag_items,
727 if (frag_msg) { /* Reassembled */
728 col_append_str(pinfo->cinfo, COL_INFO,
729 " (Message Reassembled)");
730 } else { /* Not last packet of reassembled Short Message */
731 col_append_fstr(pinfo->cinfo, COL_INFO,
732 " (Message fragment %u)", msg_num);
735 if (new_tvb) { /* take it all */
737 } else { /* make a new subset */
738 next_tvb = tvb_new_subset_remaining(tvb, offset);
741 else { /* Not fragmented */
742 next_tvb = tvb_new_subset_remaining(tvb, offset);
746 pinfo->fragmented = save_fragmented;
750 Having passed the fragment data to the reassembly handler, we can now check if
751 we have the whole message. If there is enough information, this routine will
752 return the newly reassembled data buffer.
754 After that, we add a couple of informative messages to the display to show that
755 this is part of a sequence. Then a bit of manipulation of the buffers and the
756 dissection can proceed. Normally you will probably not bother dissecting further
757 unless the fragments have been reassembled as there won't be much to find.
758 Sometimes the first packet in the sequence can be partially decoded though if
761 Now the mysterious data we passed into the `fragment_add_seq_check()`.
763 .Reassembling fragments - Initialisation
766 static reassembly_table reassembly_table;
769 proto_register_msg(void)
771 reassembly_table_register(&msg_reassemble_table,
772 &addresses_ports_reassembly_table_functions);
777 First a `reassembly_table` structure is declared and initialised in the protocol
778 initialisation routine. The second parameter specifies the functions that should
779 be used for identifying fragments. We will use
780 `addresses_ports_reassembly_table_functions` in order to identify fragments by
781 the given sequence number (`msg_seqid`), the source and destination addresses
782 and ports from the packet.
784 Following that, a `fragment_items` structure is allocated and filled in with a
785 series of ett items, hf data items, and a string tag. The ett and hf values
786 should be included in the relevant tables like all the other variables your
787 protocol may use. The hf variables need to be placed in the structure something
788 like the following. Of course the names may need to be adjusted.
790 .Reassembling fragments - Data
794 static int hf_msg_fragments = -1;
795 static int hf_msg_fragment = -1;
796 static int hf_msg_fragment_overlap = -1;
797 static int hf_msg_fragment_overlap_conflicts = -1;
798 static int hf_msg_fragment_multiple_tails = -1;
799 static int hf_msg_fragment_too_long_fragment = -1;
800 static int hf_msg_fragment_error = -1;
801 static int hf_msg_fragment_count = -1;
802 static int hf_msg_reassembled_in = -1;
803 static int hf_msg_reassembled_length = -1;
805 static gint ett_msg_fragment = -1;
806 static gint ett_msg_fragments = -1;
808 static const fragment_items msg_frag_items = {
809 /* Fragment subtrees */
812 /* Fragment fields */
815 &hf_msg_fragment_overlap,
816 &hf_msg_fragment_overlap_conflicts,
817 &hf_msg_fragment_multiple_tails,
818 &hf_msg_fragment_too_long_fragment,
819 &hf_msg_fragment_error,
820 &hf_msg_fragment_count,
821 /* Reassembled in field */
822 &hf_msg_reassembled_in,
823 /* Reassembled length field */
824 &hf_msg_reassembled_length,
829 static hf_register_info hf[] =
833 {"Message fragments", "msg.fragments",
834 FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
836 {"Message fragment", "msg.fragment",
837 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
838 {&hf_msg_fragment_overlap,
839 {"Message fragment overlap", "msg.fragment.overlap",
840 FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
841 {&hf_msg_fragment_overlap_conflicts,
842 {"Message fragment overlapping with conflicting data",
843 "msg.fragment.overlap.conflicts",
844 FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
845 {&hf_msg_fragment_multiple_tails,
846 {"Message has multiple tail fragments",
847 "msg.fragment.multiple_tails",
848 FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
849 {&hf_msg_fragment_too_long_fragment,
850 {"Message fragment too long", "msg.fragment.too_long_fragment",
851 FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
852 {&hf_msg_fragment_error,
853 {"Message defragmentation error", "msg.fragment.error",
854 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
855 {&hf_msg_fragment_count,
856 {"Message fragment count", "msg.fragment.count",
857 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
858 {&hf_msg_reassembled_in,
859 {"Reassembled in", "msg.reassembled.in",
860 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
861 {&hf_msg_reassembled_length,
862 {"Reassembled length", "msg.reassembled.length",
863 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
874 These hf variables are used internally within the reassembly routines to make
875 useful links, and to add data to the dissection. It produces links from one
876 packet to another, such as a partial packet having a link to the fully
877 reassembled packet. Likewise there are back pointers to the individual packets
878 from the reassembled one. The other variables are used for flagging up errors.
882 ==== How to reassemble split TCP Packets
884 A dissector gets a `tvbuff_t` pointer which holds the payload
885 of a TCP packet. This payload contains the header and data
886 of your application layer protocol.
888 When dissecting an application layer protocol you cannot assume
889 that each TCP packet contains exactly one application layer message.
890 One application layer message can be split into several TCP packets.
892 You also cannot assume that a TCP packet contains only one application layer message
893 and that the message header is at the start of your TCP payload.
894 More than one messages can be transmitted in one TCP packet,
895 so that a message can start at an arbitrary position.
897 This sounds complicated, but there is a simple solution.
898 `tcp_dissect_pdus()` does all this tcp packet reassembling for you.
899 This function is implemented in _epan/dissectors/packet-tcp.h_.
901 .Reassembling TCP fragments
906 #include <epan/packet.h>
907 #include <epan/prefs.h>
908 #include "packet-tcp.h"
912 #define FRAME_HEADER_LEN 8
914 /* This method dissects fully reassembled messages */
916 dissect_foo_message(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_)
918 /* TODO: implement your dissecting code */
919 return tvb_captured_length(tvb);
922 /* determine PDU length of protocol foo */
924 get_foo_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
926 /* TODO: change this to your needs */
927 return (guint)tvb_get_ntohl(tvb, offset+4); /* e.g. length is at offset 4 */
930 /* The main dissecting routine */
932 dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
934 tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN,
935 get_foo_message_len, dissect_foo_message, data);
936 return tvb_captured_length(tvb);
943 As you can see this is really simple. Just call `tcp_dissect_pdus()` in your
944 main dissection routine and move you message parsing code into another function.
945 This function gets called whenever a message has been reassembled.
947 The parameters tvb, pinfo, tree and data are just handed over to
948 `tcp_dissect_pdus()`. The 4th parameter is a flag to indicate if the data should
949 be reassembled or not. This could be set according to a dissector preference as
950 well. Parameter 5 indicates how much data has at least to be available to be
951 able to determine the length of the foo message. Parameter 6 is a function
952 pointer to a method that returns this length. It gets called when at least the
953 number of bytes given in the previous parameter is available. Parameter 7 is a
954 function pointer to your real message dissector. Parameter 8 is the data
955 passed in from parent dissector.
957 Protocols which need more data before the message length can be determined can
958 return zero. Other values smaller than the fixed length will result in an
963 === How to tap protocols
965 Adding a Tap interface to a protocol allows it to do some useful things.
966 In particular you can produce protocol statistics from the tap interface.
968 A tap is basically a way of allowing other items to see what’s happening as
969 a protocol is dissected. A tap is registered with the main program, and
970 then called on each dissection. Some arbitrary protocol specific data
971 is provided with the routine that can be used.
973 To create a tap, you first need to register a tap. A tap is registered with an
974 integer handle, and registered with the routine `register_tap()`. This takes a
975 string name with which to find it again.
980 #include <epan/packet.h>
981 #include <epan/tap.h>
983 static int foo_tap = -1;
991 void proto_register_foo(void)
994 foo_tap = register_tap("foo");
998 Whilst you can program a tap without protocol specific data, it is generally not
999 very useful. Therefore it’s a good idea to declare a structure that can be
1000 passed through the tap. This needs to be a static structure as it will be used
1001 after the dissection routine has returned. It’s generally best to pick out some
1002 generic parts of the protocol you are dissecting into the tap data. A packet
1003 type, a priority or a status code maybe. The structure really needs to be
1004 included in a header file so that it can be included by other components that
1005 want to listen in to the tap.
1007 Once you have these defined, it’s simply a case of populating the protocol
1008 specific structure and then calling `tap_queue_packet`, probably as the last part
1011 .Calling a protocol tap
1015 dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1018 fooinfo = wmem_alloc(wmem_packet_scope(), sizeof(struct FooTap));
1019 fooinfo->packet_type = tvb_get_guint8(tvb, 0);
1020 fooinfo->priority = tvb_get_ntohs(tvb, 8);
1022 tap_queue_packet(foo_tap, pinfo, fooinfo);
1024 return tvb_captured_length(tvb);
1029 This now enables those interested parties to listen in on the details
1030 of this protocol conversation.
1034 === How to produce protocol stats
1036 Given that you have a tap interface for the protocol, you can use this
1037 to produce some interesting statistics (well presumably interesting!) from
1040 This can be done in a separate plugin, or in the same plugin that is
1041 doing the dissection. The latter scheme is better, as the tap and stats
1042 module typically rely on sharing protocol specific data, which might get out
1043 of step between two different plugins.
1045 Here is a mechanism to produce statistics from the above TAP interface.
1047 .Initialising a stats interface
1050 /* register all http trees */
1051 static void register_foo_stat_trees(void) {
1052 stats_tree_register_plugin("foo", "foo", "Foo/Packet Types", 0,
1053 foo_stats_tree_packet, foo_stats_tree_init, NULL);
1056 WS_DLL_PUBLIC_DEF void plugin_register_tap_listener(void)
1058 register_foo_stat_trees();
1063 Working from the bottom up, first the plugin interface entry point is defined,
1064 `plugin_register_tap_listener()`. This simply calls the initialisation function
1065 `register_foo_stat_trees()`.
1067 This in turn calls the `stats_tree_register_plugin()` function, which takes three
1068 strings, an integer, and three callback functions.
1070 . This is the tap name that is registered.
1072 . An abbreviation of the stats name.
1074 . The name of the stats module. A “/” character can be used to make sub menus.
1076 . Flags for per-packet callback
1078 . The function that will called to generate the stats.
1080 . A function that can be called to initialise the stats data.
1082 . A function that will be called to clean up the stats data.
1084 In this case we only need the first two functions, as there is nothing specific to clean up.
1086 .Initialising a stats session
1089 static const guint8* st_str_packets = "Total Packets";
1090 static const guint8* st_str_packet_types = "FOO Packet Types";
1091 static int st_node_packets = -1;
1092 static int st_node_packet_types = -1;
1094 static void foo_stats_tree_init(stats_tree* st)
1096 st_node_packets = stats_tree_create_node(st, st_str_packets, 0, TRUE);
1097 st_node_packet_types = stats_tree_create_pivot(st, st_str_packet_types, st_node_packets);
1102 In this case we create a new tree node, to handle the total packets,
1103 and as a child of that we create a pivot table to handle the stats about
1104 different packet types.
1107 .Generating the stats
1110 static int foo_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt, const void* p)
1112 struct FooTap *pi = (struct FooTap *)p;
1113 tick_stat_node(st, st_str_packets, 0, FALSE);
1114 stats_tree_tick_pivot(st, st_node_packet_types,
1115 val_to_str(pi->packet_type, msgtypevalues, "Unknown packet type (%d)"));
1121 In this case the processing of the stats is quite simple. First we call the
1122 `tick_stat_node` for the `st_str_packets` packet node, to count packets. Then a
1123 call to `stats_tree_tick_pivot()` on the `st_node_packet_types` subtree allows
1124 us to record statistics by packet type.
1126 [[ChDissectConversation]]
1128 === How to use conversations
1130 Some info about how to use conversations in a dissector can be found in the file
1131 _doc/README.dissector_, chapter 2.2.
1133 [[ChDissectIdl2wrs]]
1135 === __idl2wrs__: Creating dissectors from CORBA IDL files
1137 Many of Wireshark’s dissectors are automatically generated. This section shows
1138 how to generate one from a CORBA IDL file.
1142 As you have probably guessed from the name, `idl2wrs` takes a user specified IDL
1143 file and attempts to build a dissector that can decode the IDL traffic over
1144 GIOP. The resulting file is “C” code, that should compile okay as a Wireshark
1147 `idl2wrs` parses the data struct given to it by the `omniidl` compiler,
1148 and using the GIOP API available in packet-giop.[ch], generates get_CDR_xxx
1149 calls to decode the CORBA traffic on the wire.
1151 It consists of 4 main files.
1156 _$$wireshark_be.py$$_::
1157 The main compiler backend
1159 _$$wireshark_gen.py$$_::
1160 A helper class, that generates the C code.
1163 A simple shell script wrapper that the end user should use to generate the
1164 dissector from the IDL file(s).
1168 It is important to understand what CORBA traffic looks like over GIOP/IIOP, and
1169 to help build a tool that can assist in troubleshooting CORBA interworking. This
1170 was especially the case after seeing a lot of discussions about how particular
1171 IDL types are represented inside an octet stream.
1173 I have also had comments/feedback that this tool would be good for say a CORBA
1174 class when teaching students what CORBA traffic looks like “on the wire”.
1176 It is also COOL to work on a great Open Source project such as the case with
1177 “Wireshark” ({wireshark-main-url}).
1180 ==== How to use idl2wrs
1182 To use the idl2wrs to generate Wireshark dissectors, you need the following:
1184 * Python must be installed. See link:https://python.org/[]
1186 * `omniidl` from the omniORB package must be available. See link:http://omniorb.sourceforge.net/[]
1188 * Of course you need Wireshark installed to compile the code and tweak it if
1189 required. idl2wrs is part of the standard Wireshark distribution
1191 To use idl2wrs to generate an Wireshark dissector from an idl file use the following procedure:
1193 * To write the C code to stdout.
1197 $ idl2wrs <your_file.idl>
1207 * To write to a file, just redirect the output.
1211 $ idl2wrs echo.idl > packet-test-idl.c
1214 You may wish to comment out the register_giop_user_module() code and that will
1215 leave you with heuristic dissection.
1217 If you don't want to use the shell script wrapper, then try steps 3 or 4 instead.
1220 * To write the C code to stdout.
1224 $ omniidl -p ./ -b wireshark_be <your file.idl>
1230 $ omniidl -p ./ -b wireshark_be echo.idl
1234 * To write to a file, just redirect the output.
1238 $ omniidl -p ./ -b wireshark_be echo.idl > packet-test-idl.c
1241 You may wish to comment out the register_giop_user_module() code and that will
1242 leave you with heuristic dissection.
1245 * Copy the resulting C code to subdirectory epan/dissectors/ inside your
1246 Wireshark source directory.
1250 $ cp packet-test-idl.c /dir/where/wireshark/lives/epan/dissectors/
1253 The new dissector has to be added to CMakeLists.txt in the same directory. Look
1254 for the declaration DISSECTOR_SRC and add the new dissector there. For
1259 ${CMAKE_CURRENT_SOURCE_DIR}/packet-2dparityfec.c
1260 ${CMAKE_CURRENT_SOURCE_DIR}/packet-3com-njack.c
1268 ${CMAKE_CURRENT_SOURCE_DIR}/packet-test-idl.c \
1269 ${CMAKE_CURRENT_SOURCE_DIR}/packet-2dparityfec.c \
1270 ${CMAKE_CURRENT_SOURCE_DIR}/packet-3com-njack.c \
1275 For the next steps, go up to the top of your Wireshark source directory.
1277 * Create a build dir
1281 $ mkdir build && cd build
1305 * Exception code not generated (yet), but can be added manually.
1307 * Enums not converted to symbolic values (yet), but can be added manually.
1309 * Add command line options etc
1311 * More I am sure :-)
1315 See the TODO list inside _packet-giop.c_
1319 The `-p ./` option passed to omniidl indicates that the wireshark_be.py and
1320 wireshark_gen.py are residing in the current directory. This may need tweaking
1321 if you place these files somewhere else.
1323 If it complains about being unable to find some modules (e.g. tempfile.py), you
1324 may want to check if PYTHONPATH is set correctly.
1327 // End of WSDG Chapter Dissection