1// WSDG Chapter Dissection
2
3[[ChapterDissection]]
4
5== Packet Dissection
6
7[[ChDissectWorks]]
8
9=== How packet dissection works
10
11Each dissector decodes its part of the protocol and then hands off
12decoding to subsequent dissectors for an encapsulated protocol.
13
14Every dissection starts with the Frame dissector which dissects the
15details of the capture file itself (e.g. timestamps). From there it passes the
16data on to the lowest-level data dissector, e.g. the Ethernet dissector for
17the Ethernet header. The payload is then passed on to the next dissector (e.g.
18IP) and so on. At each stage, details of the packet are decoded and
19displayed.
20
21Dissectors can either be built-in to Wireshark or written as a self-registering
22plugin (a shared library or DLL).
23There is little difference in having your dissector as either a plugin
24or built-in.  You have limited function access through the ABI exposed
25by functions declared as WS_DLL_PUBLIC.
26
27The big benefit of writing a dissector as a plugin is that rebuilding
28a plugin is much faster than rebuilding wireshark after editing a built-in
29dissector.
30As such, starting with a plugin often makes initial development quicker, while
31the finished code may make more sense as a built-in dissector.
32
33[NOTE]
34.Read README.dissector
35====
36The file _doc/README.dissector_ contains detailed information about writing
37a dissector. In many cases it is more up to date than this document.
38====
39
40[[ChDissectAdd]]
41
42=== Adding a basic dissector
43
44Let’s step through adding a basic dissector. We'll start with the made up "foo"
45protocol. It consists of the following basic items.
46
47* A packet type - 8 bits. Possible values: 1 - initialisation, 2 - terminate, 3 - data.
48
49* A set of flags stored in 8 bits. 0x01 - start packet, 0x02 - end packet, 0x04 - priority packet.
50
51* A sequence number - 16 bits.
52
53* An IPv4 address.
54
55[[ChDissectSetup]]
56
57==== Setting up the dissector
58
59The first decision you need to make is if this dissector will be a
60built-in dissector and included in the main program, or a plugin.
61
62Plugins are easier to write initially, so let’s start with that.
63With a little care, the plugin can be converted into a built-in dissector.
64
65.Dissector Initialisation.
66[source,c]
67----
68#include "config.h"
69#include <epan/packet.h>
70
71#define FOO_PORT 1234
72
73static int proto_foo = -1;
74
75void
76proto_register_foo(void)
77{
78    proto_foo = proto_register_protocol (
79        "FOO Protocol", /* name        */
80        "FOO",          /* short name  */
81        "foo"           /* filter_name */
82        );
83}
84----
85
86Let’s go through this a bit at a time. First we have some boilerplate
87include files. These will be pretty constant to start with.
88
89Then a `#define` for the UDP port that carries _foo_ traffic.
90
91Next we have `proto_foo`, an int that stores our protocol handle and is
92initialised to `-1`.
93This handle will be set when the dissector is registered within the main program.
94It’s good practice to make all variables and functions that aren't exported
95static to minimize name space pollution. This normally isn't a problem unless your
96dissector gets so big that it spans multiple files.
97
98Now that we have the basics in place to interact with the main program, we'll
99start with two protocol dissector setup functions: `proto_register_XXX` and
100`proto_reg_handoff_XXX`.
101
102Each protocol must have a register function with the form "proto_register_XXX".
103This function is used to register the protocol in Wireshark.
104The code to call the register routines is generated automatically and is
105called when Wireshark starts. In this example, the function is named
106`proto_register_foo`.
107
108`proto_register_foo` calls `proto_register_protocol()`, which takes a `name`,
109`short name`, and `filter_name`. The
110name and short name are used in the "Preferences" and "Enabled protocols"
111dialogs and the documentation's generated field name list. The
112`filter_name` is used as the display filter name. `proto_register_protocol()`
113returns a protocol handle, which can be used to refer to the protocol and
114obtain a handle to the protocol's dissector.
115
116
117Next we need a handoff routine.
118
119.Dissector Handoff.
120[source,c]
121----
122void
123proto_reg_handoff_foo(void)
124{
125    static dissector_handle_t foo_handle;
126
127    foo_handle = create_dissector_handle(dissect_foo, proto_foo);
128    dissector_add_uint("udp.port", FOO_PORT, foo_handle);
129}
130----
131
132A handoff routine associates a protocol handler with the protocol's
133traffic. It consists of two major steps: The first step is to create a
134dissector handle, which is a handle associated with the protocol and the
135function called to do the actual dissecting.
136The second step is to register the dissector handle so that traffic
137associated with the protocol calls the dissector.
138
139In this example, `proto_reg_handoff_foo()` calls `create_dissector_handle()`
140to obtain a dissector handle for the foo protocol. It then uses
141`dissector_add_uint()` to associate traffic on UDP port FOO_PORT (1234)
142with the foo protocol, so that Wireshark will call `dissect_foo()` when
143it receives UDP traffic on port 1234.
144
145Wireshark's dissector convention is to put `proto_register_foo()` and
146`proto_reg_handoff_foo()` as the last two functions in the dissector source.
147
148The next step is to write the dissecting function, `dissect_foo()`.
149We'll start with a basic placeholder.
150
151.Dissection.
152[source,c]
153----
154static int
155dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data _U_)
156{
157    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
158    /* Clear the info column */
159    col_clear(pinfo->cinfo,COL_INFO);
160
161    return tvb_captured_length(tvb);
162}
163----
164
165`dissect_foo()` is called to dissect the packets presented to it. The packet data
166is held in a special buffer referenced here as `tvb`. The packet_info structure
167contains general data about the protocol and we can update
168information here. The tree parameter is where the detail dissection takes place.
169Note that the `\_U_` following `tree` and `data` signals to the compiler that the
170parameters are unused, so that the compiler does not print a warning.
171
172For now we'll do the minimum we can get away with. `col_set_str()` is used to set
173Wireshark's Protocol column to "FOO" so everyone can see it’s being
174recognised. The
175only other thing we do is to clear out any data in the INFO column if it’s being
176displayed.
177
178At this point we have a basic dissector ready to compile and install.
179The dissector doesn't do anything other than identify the protocol and label it.
180Here is the dissector's complete code:
181
182.Complete _packet-foo.c_:.
183[source,c]
184----
185#include "config.h"
186#include <epan/packet.h>
187
188#define FOO_PORT 1234
189
190static int proto_foo = -1;
191
192static int
193dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data _U_)
194{
195    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
196    /* Clear the info column */
197    col_clear(pinfo->cinfo,COL_INFO);
198
199    return tvb_captured_length(tvb);
200}
201
202void
203proto_register_foo(void)
204{
205    proto_foo = proto_register_protocol (
206        "FOO Protocol", /* name        */
207        "FOO",          /* short_name  */
208        "foo"           /* filter_name */
209        );
210}
211
212void
213proto_reg_handoff_foo(void)
214{
215    static dissector_handle_t foo_handle;
216
217    foo_handle = create_dissector_handle(dissect_foo, proto_foo);
218    dissector_add_uint("udp.port", FOO_PORT, foo_handle);
219}
220
221----
222
223To compile this dissector and create a plugin a few support files
224are required, besides the dissector source in _packet-foo.c_:
225
226* _CMakeLists.txt_ - Contains the CMake file and version info for this plugin.
227
228* _packet-foo.c_ - Your dissector source.
229
230* _plugin.rc.in_ - Contains the DLL resource template for Windows. (optional)
231
232Samples of these files are available in the gryphon plugin directory
233(plugins/epan/gryphon).
234If you copy the files from the gryphon plugin, _CMakeLists.txt_ will need
235to be updated with the correct plugin name, version
236info, and the relevant files to compile.
237
238In the main top-level source directory, copy _CMakeListsCustom.txt.example_ to
239_CMakeListsCustom.txt_ and add the path of your plugin to the list in
240`CUSTOM_PLUGIN_SRC_DIR`.
241
242Compile the dissector to a DLL or shared library and either run Wireshark from
243the build directory as detailed in <<ChSrcRunFirstTime>> or copy the plugin
244binary into the plugin directory of your Wireshark installation and run that.
245
246[[ChDissectDetails]]
247
248==== Dissecting the protocol's details
249
250Now that we have our basic dissector up and running, let’s do something with it.
251The simplest thing to start with is labeling the payload. We can label the
252payload by building a subtree to decode our results into.
253This subtree will hold all the protocol's details and
254helps keep things looking nice in the detailed display.
255
256We add the new subtree with `proto_tree_add_item()`, as is depicted below:
257
258.Plugin Packet Dissection.
259[source,c]
260----
261static int
262dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
263{
264    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
265    /* Clear out stuff in the info column */
266    col_clear(pinfo->cinfo,COL_INFO);
267
268    proto_item *ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
269
270    return tvb_captured_length(tvb);
271}
272----
273
274As the `FOO` protocol does not encapsulate another protocol, we
275consume all of the tvb's data, from `0` to the end (`-1`).
276
277The final parameter specifies the "encoding" and is set to
278`ENC_NA` ("not applicable"), as the protocol doesn't specifically
279use big endian (`ENC_BIG_ENDIAN`) or little endian (`ENC_LITTLE_ENDIAN`).
280
281After adding the call to
282`proto_tree_add_item()`
283, there should be a label `FOO` in the protocol's detailed display.
284Selecting this label will highlight the remaining contents of the packet.
285
286Now let’s go to the next step and add some protocol dissection. To do this
287we'll need to construct tables to define which fields will be present in the
288packet and to store the opened/closed state of the subtree. We'll
289add these statically allocated arrays to the beginning of the file
290and name them
291`hf_register_info` ('hf' is short for 'header field') and `ett`.
292The arrays wil then registered after the call to
293`proto_register_protocol()` by calling `proto_register_field_array()`
294and `proto_register_subtree_array()`:
295
296.Registering data structures.
297[source,c]
298----
299static int hf_foo_pdu_type = -1;
300static gint ett_foo = -1;
301
302/* ... */
303
304void
305proto_register_foo(void)
306{
307    static hf_register_info hf[] = {
308        { &hf_foo_pdu_type,
309            { "FOO PDU Type", "foo.type",
310            FT_UINT8, BASE_DEC,
311            NULL, 0x0,
312            NULL, HFILL }
313        }
314    };
315
316    /* Setup protocol subtree array */
317    static gint *ett[] = {
318        &ett_foo
319    };
320
321    proto_foo = proto_register_protocol (
322        "FOO Protocol", /* name       */
323        "FOO",          /* short_name */
324        "foo"           /* filter_name*/
325        );
326
327    proto_register_field_array(proto_foo, hf, array_length(hf));
328    proto_register_subtree_array(ett, array_length(ett));
329}
330----
331
332As you can see, a field `foo.type` was defined inside the array of
333header fields.
334
335Now we can dissect the `FOO PDU Type` (referenced as `foo.type`)
336field in `dissect_foo()` by adding
337the FOO Protocol's subtree with `proto_item_add_subtree()` and
338then calling `proto_tree_add_item()` to add the field:
339
340.Dissector starting to dissect the packets.
341[source,c]
342----
343    proto_item *ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
344    proto_tree *foo_tree = proto_item_add_subtree(ti, ett_foo);
345    proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, 0, 1, ENC_BIG_ENDIAN);
346----
347
348As mentioned earlier, the foo protocol begins with an 8-bit `packet type`
349which can have three possible values: 1 - initialisation, 2 - terminate, 3 - data.
350Here's how we can add the packet details:
351
352The `proto_item_add_subtree()` call has added a child node
353to the protocol tree which is where we will do our detail dissection.
354The expansion of this node is controlled by the `ett_foo`
355variable. This remembers if the node should be expanded or not as you move
356between packets. All subsequent dissection will be added to this tree,
357as you can see from the next call.
358A call to `proto_tree_add_item()` in the foo_tree,
359this time using the `hf_foo_pdu_type` to control the formatting
360of the item. The pdu type is one byte of data, starting at 0. We assume it is
361in network order (also called big endian), so that is why we use `ENC_BIG_ENDIAN`.
362For a 1-byte quantity, there is no order issue, but it is good practice to
363make this the same as any multibyte fields that may be present, and as we will
364see in the next section, this particular protocol uses network order.
365
366If we look in detail at the `hf_foo_pdu_type` declaration in
367the static array we can see the details of the definition.
368
369----
370static hf_register_info hf[] = {
371    { &hf_foo_pdu_type,
372        { "FOO PDU Type", "foo.type",
373        FT_UINT8, BASE_DEC,
374        NULL, 0x0,
375        NULL, HFILL }
376    }
377};
378----
379
380* _hf_foo_pdu_type_ - The node's index.
381
382* _FOO PDU Type_ - The item's label.
383
384* _foo.type_ - The item's abbreviated name, for use in the display filter
385(e.g., `foo.type=1`).
386
387* _FT_UINT8_ - The item's type: An 8bit unsigned integer.
388This tallies with our call above where we tell it to only look at one byte.
389
390* _BASE_DEC_ - For an integer type, this tells it to be printed as a decimal
391number. It could be hexadecimal (BASE_HEX) or octal (BASE_OCT) if that made more sense.
392
393We'll ignore the rest of the structure for now.
394
395If you install this plugin and try it out, you'll see something that begins to look
396useful.
397
398Now let’s finish off dissecting the simple protocol. We need to add a few
399more variables to the hfarray, and a couple more procedure calls.
400
401.Wrapping up the packet dissection.
402[source,c]
403----
404...
405static int hf_foo_flags = -1;
406static int hf_foo_sequenceno = -1;
407static int hf_foo_initialip = -1;
408...
409
410static int
411dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
412{
413    gint offset = 0;
414
415    ...
416    proto_item *ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
417    proto_tree *foo_tree = proto_item_add_subtree(ti, ett_foo);
418    proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
419    offset += 1;
420    proto_tree_add_item(foo_tree, hf_foo_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
421    offset += 1;
422    proto_tree_add_item(foo_tree, hf_foo_sequenceno, tvb, offset, 2, ENC_BIG_ENDIAN);
423    offset += 2;
424    proto_tree_add_item(foo_tree, hf_foo_initialip, tvb, offset, 4, ENC_BIG_ENDIAN);
425    offset += 4;
426    ...
427
428    return tvb_captured_length(tvb);
429}
430
431void
432proto_register_foo(void) {
433    ...
434        ...
435        { &hf_foo_flags,
436            { "FOO PDU Flags", "foo.flags",
437            FT_UINT8, BASE_HEX,
438            NULL, 0x0,
439            NULL, HFILL }
440        },
441        { &hf_foo_sequenceno,
442            { "FOO PDU Sequence Number", "foo.seqn",
443            FT_UINT16, BASE_DEC,
444            NULL, 0x0,
445            NULL, HFILL }
446        },
447        { &hf_foo_initialip,
448            { "FOO PDU Initial IP", "foo.initialip",
449            FT_IPv4, BASE_NONE,
450            NULL, 0x0,
451            NULL, HFILL }
452        },
453        ...
454    ...
455}
456...
457----
458
459This dissects all the bits of this simple hypothetical protocol. We've
460introduced a new variable offsetinto the mix to help keep track of where we are
461in the packet dissection. With these extra bits in place, the whole protocol is
462now dissected.
463
464==== Improving the dissection information
465
466We can certainly improve the display of the protocol with a bit of extra data.
467The first step is to add some text labels. Let’s start by labeling the packet
468types. There is some useful support for this sort of thing by adding a couple of
469extra things. First we add a simple table of type to name.
470
471
472.Naming the packet types.
473[source,c]
474----
475static const value_string packettypenames[] = {
476    { 1, "Initialise" },
477    { 2, "Terminate" },
478    { 3, "Data" },
479    { 0, NULL }
480};
481----
482
483This is a handy data structure that can be used to look up a name for a value.
484There are routines to directly access this lookup table, but we don't need to
485do that, as the support code already has that added in. We just have to give
486these details to the appropriate part of the data, using the `VALS` macro.
487
488.Adding Names to the protocol.
489[source,c]
490----
491   { &hf_foo_pdu_type,
492        { "FOO PDU Type", "foo.type",
493        FT_UINT8, BASE_DEC,
494        VALS(packettypenames), 0x0,
495        NULL, HFILL }
496    }
497----
498
499This helps in deciphering the packets, and we can do a similar thing for the
500flags structure. For this we need to add some more data to the table though.
501
502.Adding Flags to the protocol.
503[source,c]
504----
505#define FOO_START_FLAG      0x01
506#define FOO_END_FLAG        0x02
507#define FOO_PRIORITY_FLAG   0x04
508
509static int hf_foo_startflag = -1;
510static int hf_foo_endflag = -1;
511static int hf_foo_priorityflag = -1;
512
513static int
514dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
515{
516    ...
517        ...
518        static int* const bits[] = {
519            &hf_foo_startflag,
520            &hf_foo_endflag,
521            &hf_foo_priorityflag,
522            NULL
523        };
524
525        proto_tree_add_bitmask(foo_tree, tvb, offset, hf_foo_flags, ett_foo, bits, ENC_BIG_ENDIAN);
526        offset += 1;
527        ...
528    ...
529    return tvb_captured_length(tvb);
530}
531
532void
533proto_register_foo(void) {
534    ...
535        ...
536        { &hf_foo_startflag,
537            { "FOO PDU Start Flags", "foo.flags.start",
538            FT_BOOLEAN, 8,
539            NULL, FOO_START_FLAG,
540            NULL, HFILL }
541        },
542        { &hf_foo_endflag,
543            { "FOO PDU End Flags", "foo.flags.end",
544            FT_BOOLEAN, 8,
545            NULL, FOO_END_FLAG,
546            NULL, HFILL }
547        },
548        { &hf_foo_priorityflag,
549            { "FOO PDU Priority Flags", "foo.flags.priority",
550            FT_BOOLEAN, 8,
551            NULL, FOO_PRIORITY_FLAG,
552            NULL, HFILL }
553        },
554        ...
555    ...
556}
557...
558----
559
560Some things to note here. For the flags, as each bit is a different flag, we use
561the type `FT_BOOLEAN`, as the flag is either on or off. Second, we include the flag
562mask in the 7th field of the data, which allows the system to mask the relevant bit.
563We've also changed the 5th field to 8, to indicate that we are looking at an 8 bit
564quantity when the flags are extracted. Then finally we add the extra constructs
565to the dissection routine.
566
567This is starting to look fairly full featured now, but there are a couple of
568other things we can do to make things look even more pretty. At the moment our
569dissection shows the packets as "Foo Protocol" which whilst correct is a little
570uninformative. We can enhance this by adding a little more detail. First, let’s
571get hold of the actual value of the protocol type. We can use the handy function
572`tvb_get_guint8()` to do this. With this value in hand, there are a couple of
573things we can do. First we can set the INFO column of the non-detailed view to
574show what sort of PDU it is - which is extremely helpful when looking at
575protocol traces. Second, we can also display this information in the dissection
576window.
577
578.Enhancing the display.
579[source,c]
580----
581static int
582dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
583{
584    gint offset = 0;
585    guint8 packet_type = tvb_get_guint8(tvb, 0);
586
587    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
588    /* Clear out stuff in the info column */
589    col_clear(pinfo->cinfo,COL_INFO);
590    col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s",
591             val_to_str(packet_type, packettypenames, "Unknown (0x%02x)"));
592
593    proto_item *ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
594    proto_item_append_text(ti, ", Type %s",
595        val_to_str(packet_type, packettypenames, "Unknown (0x%02x)"));
596    proto_tree *foo_tree = proto_item_add_subtree(ti, ett_foo);
597    proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
598    offset += 1;
599
600    return tvb_captured_length(tvb);
601}
602----
603
604So here, after grabbing the value of the first 8 bits, we use it with one of the
605built-in utility routines `val_to_str()`, to lookup the value. If the value
606isn't found we provide a fallback which just prints the value in hex. We use
607this twice, once in the INFO field of the columns -- if it’s displayed, and
608similarly we append this data to the base of our dissecting tree.
609
610[[ChDissectExpertInfo]]
611
612=== How to add an expert item
613
614A dissector showing the protocol fields and interpretation of their values is
615very informative. It can be even more helpful if the dissector can draw your
616attention to fields where something noteworthy can be seen. This can be something
617as simple as the start flag of a session, or something more severe as an invalid
618value.
619
620Here we take our dissector for `FOO` and add an expert item for the sequence
621number being zero (assuming that's a noteworthy thing for this protocol).
622
623.Expert item setup.
624[source,c]
625----
626#include <epan/expert.h>
627
628static expert_field ei_foo_seqn_zero = EI_INIT;
629
630/* ... */
631
632void
633proto_register_foo(void)
634{
635    /* ... */
636    expert_module_t* expert_foo;
637
638    /* ... */
639    static ei_register_info ei[] = {
640        {
641            &ei_foo_seqn_zero,
642            { "foo.seqn_zero", PI_SEQUENCE, PI_CHAT,
643              "Sequence number is zero", EXPFILL }
644        }
645    };
646
647    /* ... */
648    expert_foo = expert_register_protocol(proto_foo);
649    expert_register_field_array(expert_foo, ei, array_length(ei));
650}
651----
652
653Let's go through this step by step. The data structures and functions needed for
654expert items are found in epan/expert.h, so we have to include that file.
655
656Next we have to allocate an `expert_field` structure for every type of expert item
657we would like to add to the dissection. This structure is initialised with `EI_INIT`.
658
659Now we have to register with the protocol we are providing expert info for. Since
660we already have a function to register our protocol, we add the expert info
661registration there too. This is done by calling `expert_register_protocol()` with
662the handle for the protocol we received earlier in this function.
663
664Next we need to register an array of definitions of expert items that we would
665like to add to the dissection. This array, not unlike the array of header fields
666before, contains all the data the dissection engine needs to create and handle
667the expert items.
668
669The expert item definition consists of a pointer to the `expert_field` structure
670we defined before and a structure with data elements of the expert item itself.
671
672* _"foo.seqn_zero"_ - The expert items display filter
673
674* _PI_SEQUENCE_ - The group to which the expert item belongs
675
676* _PI_CHAT_ - The severity of the expert item
677
678* _"Sequence number is zero"_ - The text string added to the dissection
679
680We'll ignore the rest of the structure for now.
681
682To keep an overview of lots of expert items it helps to categorize them into groups.
683Currently there are several types of groups defined, e.g. `checksum`, `sequence`,
684`protocol`, etc. All these are defined in the epan/proto.h header file.
685
686Not every noteworthy field value is of equal severity. The start of a session
687is nice to know, while an invalid value may be significant error in the protocol.
688To differentiate between these severties the expert item is assigned one of them:
689`comment`, `chat`, `note`, `warn` or `error`. Try to choose the lowest one which
690is suitable. The topic you're currently working on seems probably more important
691than it will look like in a few weeks.
692
693With the expert item array setup, we add this to the dissection engine with a
694call to `expert_register_field_array()`.
695
696Now that all information of the expert item is defined and registered it's time
697to actually add the expert item to the dissection.
698
699.Expert item use.
700[source,c]
701----
702static int
703dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
704{
705    guint32 sequenceno = 0xFFFF;
706
707    /* ... */
708
709    ti = proto_tree_add_item_ret_uint(foo_tree, hf_foo_sequenceno,
710                                      tvb, offset, 2, ENC_BIG_ENDIAN, &sequenceno);
711    if (sequenceno == 0) {
712        expert_add_info(pinfo, ti, &ei_foo_seqn_zero);
713    }
714
715    /* ... */
716}
717----
718
719There's been a slight alteration to the function used to add the sequence number
720dissection. First the proto_item created by the function is saved in previously
721defined variable `ti`, and the actual value of the field is stored in the variable
722`sequenceno`. We can now use the value of this field to determine wether to add
723the expert item.
724
725Adding the expert item is simply done by calling `expert_add_info()` with reference
726to the `packet_info` structure, the proto item `ti` to add the expert item to and
727the previously defined and registered expert item information.
728
729[[ChDissectTransformed]]
730
731=== How to handle transformed data
732
733Some protocols do clever things with data. They might possibly
734encrypt the data, or compress data, or part of it. If you know
735how these steps are taken it is possible to reverse them within the
736dissector.
737
738As encryption can be tricky, let’s consider the case of compression.
739These techniques can also work for other transformations of data,
740where some step is required before the data can be examined.
741
742What basically needs to happen here, is to identify the data that needs
743conversion, take that data and transform it into a new stream, and then call a
744dissector on it. Often this needs to be done "on-the-fly" based on clues in the
745packet. Sometimes this needs to be used in conjunction with other techniques,
746such as packet reassembly. The following shows a technique to achieve this
747effect.
748
749.Decompressing data packets for dissection.
750[source,c]
751----
752    guint8 flags = tvb_get_guint8(tvb, offset);
753    offset ++;
754    if (flags & FLAG_COMPRESSED) { /* the remainder of the packet is compressed */
755        guint16 orig_size = tvb_get_ntohs(tvb, offset);
756        guchar *decompressed_buffer = (guchar*)wmem_alloc(pinfo->pool, orig_size);
757        offset += 2;
758        decompress_packet(tvb_get_ptr(tvb, offset, -1),
759                tvb_captured_length_remaining(tvb, offset),
760                decompressed_buffer, orig_size);
761        /* Now re-setup the tvb buffer to have the new data */
762        next_tvb = tvb_new_child_real_data(tvb, decompressed_buffer, orig_size, orig_size);
763        add_new_data_source(pinfo, next_tvb, "Decompressed Data");
764    } else {
765        next_tvb = tvb_new_subset_remaining(tvb, offset);
766    }
767    offset = 0;
768    /* process next_tvb from here on */
769----
770
771The first steps here are to recognise the compression. In this case a flag byte
772alerts us to the fact the remainder of the packet is compressed. Next we
773retrieve the original size of the packet, which in this case is conveniently
774within the protocol. If it’s not, it may be part of the compression routine to
775work it out for you, in which case the logic would be different.
776
777So armed with the size, a buffer is allocated to receive the uncompressed data
778using `wmem_alloc()` in pinfo->pool memory, and the packet is decompressed into
779it. The `tvb_get_ptr()` function is useful to get a pointer to the raw data of
780the packet from the offset onwards. In this case the decompression routine also
781needs to know the length, which is given by the
782`tvb_captured_length_remaining()` function.
783
784Next we build a new tvb buffer from this data, using the
785`tvb_new_child_real_data()` call. This data is a child of our original data, so
786calling this function also acknowledges that. No need to call
787`tvb_set_free_cb()` as the pinfo->pool was used (the memory block will be
788automatically freed when the pinfo pool lifetime expires). Finally we add this
789tvb as a new data source, so that the detailed display can show the
790decompressed bytes as well as the original.
791
792After this has been set up the remainder of the dissector can dissect the buffer
793next_tvb, as it’s a new buffer the offset needs to be 0 as we start again from
794the beginning of this buffer. To make the rest of the dissector work regardless
795of whether compression was involved or not, in the case that compression was not
796signaled, we use `tvb_new_subset_remaining()` to deliver us a new buffer based
797on the old one but starting at the current offset, and extending to the end.
798This makes dissecting the packet from this point on exactly the same regardless
799of compression.
800
801[[ChDissectReassemble]]
802
803=== How to reassemble split packets
804
805Some protocols have times when they have to split a large packet across
806multiple other packets. In this case the dissection can't be carried out correctly
807until you have all the data. The first packet doesn't have enough data,
808and the subsequent packets don't have the expect format.
809To dissect these packets you need to wait until all the parts have
810arrived and then start the dissection.
811
812The following sections will guide you through two common cases. For a
813description of all possible functions, structures and parameters, see
814_epan/reassemble.h_.
815
816[[ChDissectReassembleUdp]]
817
818==== How to reassemble split UDP packets
819
820As an example, let’s examine a protocol that is layered on top of UDP that
821splits up its own data stream. If a packet is bigger than some given size, it
822will be split into chunks, and somehow signaled within its protocol.
823
824To deal with such streams, we need several things to trigger from. We need to
825know that this packet is part of a multi-packet sequence. We need to know how
826many packets are in the sequence. We also need to know when we have all the
827packets.
828
829For this example we'll assume there is a simple in-protocol signaling mechanism
830to give details. A flag byte that signals the presence of a multi-packet
831sequence and also the last packet, followed by an ID of the sequence and a
832packet sequence number.
833
834----
835msg_pkt ::= SEQUENCE {
836    .....
837    flags ::= SEQUENCE {
838        fragment    BOOLEAN,
839        last_fragment   BOOLEAN,
840    .....
841    }
842    msg_id  INTEGER(0..65535),
843    frag_id INTEGER(0..65535),
844    .....
845}
846----
847
848.Reassembling fragments - Part 1
849[source,c]
850----
851#include <epan/reassemble.h>
852   ...
853save_fragmented = pinfo->fragmented;
854flags = tvb_get_guint8(tvb, offset); offset++;
855if (flags & FL_FRAGMENT) { /* fragmented */
856    tvbuff_t* new_tvb = NULL;
857    fragment_data *frag_msg = NULL;
858    guint16 msg_seqid = tvb_get_ntohs(tvb, offset); offset += 2;
859    guint16 msg_num = tvb_get_ntohs(tvb, offset); offset += 2;
860
861    pinfo->fragmented = TRUE;
862    frag_msg = fragment_add_seq_check(msg_reassembly_table,
863        tvb, offset, pinfo,
864        msg_seqid, NULL, /* ID for fragments belonging together */
865        msg_num, /* fragment sequence number */
866        tvb_captured_length_remaining(tvb, offset), /* fragment length - to the end */
867        flags & FL_FRAG_LAST); /* More fragments? */
868----
869
870We start by saving the fragmented state of this packet, so we can restore it
871later. Next comes some protocol specific stuff, to dig the fragment data out of
872the stream if it’s present. Having decided it is present, we let the function
873`fragment_add_seq_check()` do its work. We need to provide this with a certain
874amount of parameters:
875
876* The `msg_reassembly_table` table is for bookkeeping and is described later.
877
878* The tvb buffer we are dissecting.
879
880* The offset where the partial packet starts.
881
882* The provided packet info.
883
884* The sequence number of the fragment stream. There may be several streams of
885  fragments in flight, and this is used to key the relevant one to be used for
886  reassembly.
887
888* Optional additional data for identifying the fragment. Can be set to `NULL`
889  (as is done in the example) for most dissectors.
890
891* msg_num is the packet number within the sequence.
892
893* The length here is specified as the rest of the tvb as we want the rest of the packet data.
894
895* Finally a parameter that signals if this is the last fragment or not. This
896  might be a flag as in this case, or there may be a counter in the protocol.
897
898.Reassembling fragments part 2
899[source,c]
900----
901    new_tvb = process_reassembled_data(tvb, offset, pinfo,
902        "Reassembled Message", frag_msg, &msg_frag_items,
903        NULL, msg_tree);
904
905    if (frag_msg) { /* Reassembled */
906        col_append_str(pinfo->cinfo, COL_INFO,
907                " (Message Reassembled)");
908    } else { /* Not last packet of reassembled Short Message */
909        col_append_fstr(pinfo->cinfo, COL_INFO,
910                " (Message fragment %u)", msg_num);
911    }
912
913    if (new_tvb) { /* take it all */
914        next_tvb = new_tvb;
915    } else { /* make a new subset */
916        next_tvb = tvb_new_subset_remaining(tvb, offset);
917    }
918}
919else { /* Not fragmented */
920    next_tvb = tvb_new_subset_remaining(tvb, offset);
921}
922
923.....
924pinfo->fragmented = save_fragmented;
925----
926
927Having passed the fragment data to the reassembly handler, we can now check if
928we have the whole message. If there is enough information, this routine will
929return the newly reassembled data buffer.
930
931After that, we add a couple of informative messages to the display to show that
932this is part of a sequence. Then a bit of manipulation of the buffers and the
933dissection can proceed. Normally you will probably not bother dissecting further
934unless the fragments have been reassembled as there won't be much to find.
935Sometimes the first packet in the sequence can be partially decoded though if
936you wish.
937
938Now the mysterious data we passed into the `fragment_add_seq_check()`.
939
940.Reassembling fragments - Initialisation
941[source,c]
942----
943static reassembly_table reassembly_table;
944
945static void
946proto_register_msg(void)
947{
948    reassembly_table_register(&msg_reassemble_table,
949        &addresses_ports_reassembly_table_functions);
950}
951----
952
953First a `reassembly_table` structure is declared and initialised in the protocol
954initialisation routine. The second parameter specifies the functions that should
955be used for identifying fragments. We will use
956`addresses_ports_reassembly_table_functions` in order to identify fragments by
957the given sequence number (`msg_seqid`), the source and destination addresses
958and ports from the packet.
959
960Following that, a `fragment_items` structure is allocated and filled in with a
961series of ett items, hf data items, and a string tag. The ett and hf values
962should be included in the relevant tables like all the other variables your
963protocol may use. The hf variables need to be placed in the structure something
964like the following. Of course the names may need to be adjusted.
965
966.Reassembling fragments - Data
967[source,c]
968----
969...
970static int hf_msg_fragments = -1;
971static int hf_msg_fragment = -1;
972static int hf_msg_fragment_overlap = -1;
973static int hf_msg_fragment_overlap_conflicts = -1;
974static int hf_msg_fragment_multiple_tails = -1;
975static int hf_msg_fragment_too_long_fragment = -1;
976static int hf_msg_fragment_error = -1;
977static int hf_msg_fragment_count = -1;
978static int hf_msg_reassembled_in = -1;
979static int hf_msg_reassembled_length = -1;
980...
981static gint ett_msg_fragment = -1;
982static gint ett_msg_fragments = -1;
983...
984static const fragment_items msg_frag_items = {
985    /* Fragment subtrees */
986    &ett_msg_fragment,
987    &ett_msg_fragments,
988    /* Fragment fields */
989    &hf_msg_fragments,
990    &hf_msg_fragment,
991    &hf_msg_fragment_overlap,
992    &hf_msg_fragment_overlap_conflicts,
993    &hf_msg_fragment_multiple_tails,
994    &hf_msg_fragment_too_long_fragment,
995    &hf_msg_fragment_error,
996    &hf_msg_fragment_count,
997    /* Reassembled in field */
998    &hf_msg_reassembled_in,
999    /* Reassembled length field */
1000    &hf_msg_reassembled_length,
1001    /* Tag */
1002    "Message fragments"
1003};
1004...
1005static hf_register_info hf[] =
1006{
1007...
1008{&hf_msg_fragments,
1009    {"Message fragments", "msg.fragments",
1010    FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1011{&hf_msg_fragment,
1012    {"Message fragment", "msg.fragment",
1013    FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1014{&hf_msg_fragment_overlap,
1015    {"Message fragment overlap", "msg.fragment.overlap",
1016    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
1017{&hf_msg_fragment_overlap_conflicts,
1018    {"Message fragment overlapping with conflicting data",
1019    "msg.fragment.overlap.conflicts",
1020    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
1021{&hf_msg_fragment_multiple_tails,
1022    {"Message has multiple tail fragments",
1023    "msg.fragment.multiple_tails",
1024    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
1025{&hf_msg_fragment_too_long_fragment,
1026    {"Message fragment too long", "msg.fragment.too_long_fragment",
1027    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
1028{&hf_msg_fragment_error,
1029    {"Message defragmentation error", "msg.fragment.error",
1030    FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1031{&hf_msg_fragment_count,
1032    {"Message fragment count", "msg.fragment.count",
1033    FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
1034{&hf_msg_reassembled_in,
1035    {"Reassembled in", "msg.reassembled.in",
1036    FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1037{&hf_msg_reassembled_length,
1038    {"Reassembled length", "msg.reassembled.length",
1039    FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
1040...
1041static gint *ett[] =
1042{
1043...
1044&ett_msg_fragment,
1045&ett_msg_fragments
1046...
1047----
1048
1049These hf variables are used internally within the reassembly routines to make
1050useful links, and to add data to the dissection. It produces links from one
1051packet to another, such as a partial packet having a link to the fully
1052reassembled packet. Likewise there are back pointers to the individual packets
1053from the reassembled one. The other variables are used for flagging up errors.
1054
1055[[TcpDissectPdus]]
1056
1057==== How to reassemble split TCP Packets
1058
1059A dissector gets a `tvbuff_t` pointer which holds the payload
1060of a TCP packet. This payload contains the header and data
1061of your application layer protocol.
1062
1063When dissecting an application layer protocol you cannot assume
1064that each TCP packet contains exactly one application layer message.
1065One application layer message can be split into several TCP packets.
1066
1067You also cannot assume that a TCP packet contains only one application layer message
1068and that the message header is at the start of your TCP payload.
1069More than one messages can be transmitted in one TCP packet,
1070so that a message can start at an arbitrary position.
1071
1072This sounds complicated, but there is a simple solution.
1073`tcp_dissect_pdus()` does all this tcp packet reassembling for you.
1074This function is implemented in _epan/dissectors/packet-tcp.h_.
1075
1076.Reassembling TCP fragments
1077[source,c]
1078----
1079#include "config.h"
1080
1081#include <epan/packet.h>
1082#include <epan/prefs.h>
1083#include "packet-tcp.h"
1084
1085...
1086
1087#define FRAME_HEADER_LEN 8
1088
1089/* This method dissects fully reassembled messages */
1090static int
1091dissect_foo_message(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_)
1092{
1093    /* TODO: implement your dissecting code */
1094    return tvb_captured_length(tvb);
1095}
1096
1097/* determine PDU length of protocol foo */
1098static guint
1099get_foo_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1100{
1101    /* TODO: change this to your needs */
1102    return (guint)tvb_get_ntohl(tvb, offset+4); /* e.g. length is at offset 4 */
1103}
1104
1105/* The main dissecting routine */
1106static int
1107dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1108{
1109    tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN,
1110                     get_foo_message_len, dissect_foo_message, data);
1111    return tvb_captured_length(tvb);
1112}
1113
1114...
1115----
1116
1117As you can see this is really simple. Just call `tcp_dissect_pdus()` in your
1118main dissection routine and move you message parsing code into another function.
1119This function gets called whenever a message has been reassembled.
1120
1121The parameters tvb, pinfo, tree and data are just handed over to
1122`tcp_dissect_pdus()`. The 4th parameter is a flag to indicate if the data should
1123be reassembled or not. This could be set according to a dissector preference as
1124well. Parameter 5 indicates how much data has at least to be available to be
1125able to determine the length of the foo message. Parameter 6 is a function
1126pointer to a method that returns this length. It gets called when at least the
1127number of bytes given in the previous parameter is available. Parameter 7 is a
1128function pointer to your real message dissector. Parameter 8 is the data
1129passed in from parent dissector.
1130
1131Protocols which need more data before the message length can be determined can
1132return zero. Other values smaller than the fixed length will result in an
1133exception.
1134
1135[[ChDissectTap]]
1136
1137=== How to tap protocols
1138
1139Adding a Tap interface to a protocol allows it to do some useful things.
1140In particular you can produce protocol statistics from the tap interface.
1141
1142A tap is basically a way of allowing other items to see what’s happening as
1143a protocol is dissected. A tap is registered with the main program, and
1144then called on each dissection. Some arbitrary protocol specific data
1145is provided with the routine that can be used.
1146
1147To create a tap, you first need to register a tap. A tap is registered with an
1148integer handle, and registered with the routine `register_tap()`. This takes a
1149string name with which to find it again.
1150
1151.Initialising a tap
1152[source,c]
1153----
1154#include <epan/packet.h>
1155#include <epan/tap.h>
1156
1157static int foo_tap = -1;
1158
1159struct FooTap {
1160    gint packet_type;
1161    gint priority;
1162       ...
1163};
1164
1165void proto_register_foo(void)
1166{
1167       ...
1168    foo_tap = register_tap("foo");
1169----
1170
1171Whilst you can program a tap without protocol specific data, it is generally not
1172very useful. Therefore it’s a good idea to declare a structure that can be
1173passed through the tap. This needs to be a static structure as it will be used
1174after the dissection routine has returned. It’s generally best to pick out some
1175generic parts of the protocol you are dissecting into the tap data. A packet
1176type, a priority or a status code maybe. The structure really needs to be
1177included in a header file so that it can be included by other components that
1178want to listen in to the tap.
1179
1180Once you have these defined, it’s simply a case of populating the protocol
1181specific structure and then calling `tap_queue_packet`, probably as the last part
1182of the dissector.
1183
1184.Calling a protocol tap
1185[source,c]
1186----
1187static int
1188dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1189{
1190       ...
1191    fooinfo = wmem_alloc(pinfo->pool, sizeof(struct FooTap));
1192    fooinfo->packet_type = tvb_get_guint8(tvb, 0);
1193    fooinfo->priority = tvb_get_ntohs(tvb, 8);
1194       ...
1195    tap_queue_packet(foo_tap, pinfo, fooinfo);
1196
1197    return tvb_captured_length(tvb);
1198}
1199----
1200
1201This now enables those interested parties to listen in on the details
1202of this protocol conversation.
1203
1204[[ChDissectStats]]
1205
1206=== How to produce protocol stats
1207
1208Given that you have a tap interface for the protocol, you can use this
1209to produce some interesting statistics (well presumably interesting!) from
1210protocol traces.
1211
1212This can be done in a separate plugin, or in the same plugin that is
1213doing the dissection. The latter scheme is better, as the tap and stats
1214module typically rely on sharing protocol specific data, which might get out
1215of step between two different plugins.
1216
1217Here is a mechanism to produce statistics from the above TAP interface.
1218
1219.Initialising a stats interface
1220[source,c]
1221----
1222#include <epan/stats_tree.h>
1223
1224/* register all http trees */
1225static void register_foo_stat_trees(void) {
1226    stats_tree_register_plugin("foo", "foo", "Foo/Packet Types", 0,
1227        foo_stats_tree_packet, foo_stats_tree_init, NULL);
1228}
1229
1230WS_DLL_PUBLIC_DEF void plugin_register_tap_listener(void)
1231{
1232    register_foo_stat_trees();
1233}
1234----
1235
1236Working from the bottom up, first the plugin interface entry point is defined,
1237`plugin_register_tap_listener()`. This simply calls the initialisation function
1238`register_foo_stat_trees()`.
1239
1240This in turn calls the `stats_tree_register_plugin()` function, which takes three
1241strings, an integer, and three callback functions.
1242
1243. This is the tap name that is registered.
1244
1245. An abbreviation of the stats name.
1246
1247. The name of the stats module. A “/” character can be used to make sub menus.
1248
1249. Flags for per-packet callback
1250
1251. The function that will called to generate the stats.
1252
1253. A function that can be called to initialise the stats data.
1254
1255. A function that will be called to clean up the stats data.
1256
1257In this case we only need the first two functions, as there is nothing specific to clean up.
1258
1259.Initialising a stats session
1260[source,c]
1261----
1262static const guint8* st_str_packets = "Total Packets";
1263static const guint8* st_str_packet_types = "FOO Packet Types";
1264static int st_node_packets = -1;
1265static int st_node_packet_types = -1;
1266
1267static void foo_stats_tree_init(stats_tree* st)
1268{
1269    st_node_packets = stats_tree_create_node(st, st_str_packets, 0, STAT_DT_INT, TRUE);
1270    st_node_packet_types = stats_tree_create_pivot(st, st_str_packet_types, st_node_packets);
1271}
1272----
1273
1274In this case we create a new tree node, to handle the total packets,
1275and as a child of that we create a pivot table to handle the stats about
1276different packet types.
1277
1278
1279.Generating the stats
1280[source,c]
1281----
1282static tap_packet_status foo_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt, const void* p)
1283{
1284    struct FooTap *pi = (struct FooTap *)p;
1285    tick_stat_node(st, st_str_packets, 0, FALSE);
1286    stats_tree_tick_pivot(st, st_node_packet_types,
1287            val_to_str(pi->packet_type, packettypenames, "Unknown packet type (%d)"));
1288    return TAP_PACKET_REDRAW;
1289}
1290----
1291
1292In this case the processing of the stats is quite simple. First we call the
1293`tick_stat_node` for the `st_str_packets` packet node, to count packets. Then a
1294call to `stats_tree_tick_pivot()` on the `st_node_packet_types` subtree allows
1295us to record statistics by packet type.
1296
1297[[ChDissectConversation]]
1298
1299=== How to use conversations
1300
1301Some info about how to use conversations in a dissector can be found in the file
1302_doc/README.dissector_, chapter 2.2.
1303
1304[[ChDissectIdl2wrs]]
1305
1306=== __idl2wrs__: Creating dissectors from CORBA IDL files
1307
1308Many of Wireshark’s dissectors are automatically generated. This section shows
1309how to generate one from a CORBA IDL file.
1310
1311==== What is it?
1312
1313As you have probably guessed from the name, `idl2wrs` takes a user specified IDL
1314file and attempts to build a dissector that can decode the IDL traffic over
1315GIOP. The resulting file is “C” code, that should compile okay as a Wireshark
1316dissector.
1317
1318`idl2wrs` parses the data struct given to it by the `omniidl` compiler,
1319and using the GIOP API available in packet-giop.[ch], generates get_CDR_xxx
1320calls to decode the CORBA traffic on the wire.
1321
1322It consists of 4 main files.
1323
1324README.idl2wrs::
1325This document
1326
1327wireshark_be.py::
1328The main compiler backend
1329
1330wireshark_gen.py::
1331A helper class, that generates the C code.
1332
1333idl2wrs::
1334A simple shell script wrapper that the end user should use to generate the
1335dissector from the IDL file(s).
1336
1337==== Why do this?
1338
1339It is important to understand what CORBA traffic looks like over GIOP/IIOP, and
1340to help build a tool that can assist in troubleshooting CORBA interworking. This
1341was especially the case after seeing a lot of discussions about how particular
1342IDL types are represented inside an octet stream.
1343
1344I have also had comments/feedback that this tool would be good for say a CORBA
1345class when teaching students what CORBA traffic looks like “on the wire”.
1346
1347It is also COOL to work on a great Open Source project such as the case with
1348“Wireshark” ({wireshark-main-url}).
1349
1350
1351==== How to use idl2wrs
1352
1353To use the idl2wrs to generate Wireshark dissectors, you need the following:
1354
1355* Python must be installed.  See link:https://python.org/[]
1356
1357* `omniidl` from the omniORB package must be available. See link:http://omniorb.sourceforge.net/[]
1358
1359* Of course you need Wireshark installed to compile the code and tweak it if
1360required. idl2wrs is part of the standard Wireshark distribution
1361
1362To use idl2wrs to generate an Wireshark dissector from an idl file use the following procedure:
1363
1364* To write the C code to stdout.
1365+
1366--
1367----
1368$ idl2wrs <your_file.idl>
1369----
1370
1371e.g.:
1372
1373----
1374$ idl2wrs echo.idl
1375----
1376--
1377
1378* To write to a file, just redirect the output.
1379+
1380--
1381----
1382$ idl2wrs echo.idl > packet-test-idl.c
1383----
1384
1385You may wish to comment out the register_giop_user_module() code and that will
1386leave you with heuristic dissection.
1387
1388If you don't want to use the shell script wrapper, then try steps 3 or 4 instead.
1389--
1390
1391* To write the C code to stdout.
1392+
1393--
1394----
1395$ omniidl  -p ./ -b wireshark_be <your file.idl>
1396----
1397
1398e.g.:
1399
1400----
1401$ omniidl  -p ./ -b wireshark_be echo.idl
1402----
1403--
1404
1405* To write to a file, just redirect the output.
1406+
1407--
1408----
1409$ omniidl  -p ./ -b wireshark_be echo.idl > packet-test-idl.c
1410----
1411
1412You may wish to comment out the register_giop_user_module() code and that will
1413leave you with heuristic dissection.
1414--
1415
1416* Copy the resulting C code to subdirectory epan/dissectors/ inside your
1417Wireshark source directory.
1418+
1419--
1420----
1421$ cp packet-test-idl.c /dir/where/wireshark/lives/epan/dissectors/
1422----
1423
1424The new dissector has to be added to CMakeLists.txt in the same directory. Look
1425for the declaration DISSECTOR_SRC and add the new dissector there. For
1426example,
1427
1428----
1429DISSECTOR_SRC = \
1430        ${CMAKE_CURRENT_SOURCE_DIR}/packet-2dparityfec.c
1431        ${CMAKE_CURRENT_SOURCE_DIR}/packet-3com-njack.c
1432        ...
1433----
1434
1435becomes
1436
1437----
1438DISSECTOR_SRC = \
1439        ${CMAKE_CURRENT_SOURCE_DIR}/packet-test-idl.c       \
1440        ${CMAKE_CURRENT_SOURCE_DIR}/packet-2dparityfec.c    \
1441        ${CMAKE_CURRENT_SOURCE_DIR}/packet-3com-njack.c     \
1442        ...
1443----
1444--
1445
1446For the next steps, go up to the top of your Wireshark source directory.
1447
1448* Create a build dir
1449+
1450--
1451----
1452$ mkdir build && cd build
1453----
1454--
1455
1456* Run cmake
1457+
1458--
1459----
1460$ cmake ..
1461----
1462--
1463
1464* Build the code
1465+
1466--
1467----
1468$ make
1469----
1470--
1471
1472* Good Luck !!
1473
1474==== TODO
1475
1476* Exception code not generated  (yet), but can be added manually.
1477
1478* Enums not converted to symbolic values (yet), but can be added manually.
1479
1480* Add command line options etc
1481
1482* More I am sure :-)
1483
1484==== Limitations
1485
1486See the TODO list inside _packet-giop.c_
1487
1488==== Notes
1489
1490The `-p ./` option passed to omniidl indicates that the wireshark_be.py and
1491wireshark_gen.py are residing in the current directory. This may need tweaking
1492if you place these files somewhere else.
1493
1494If it complains about being unable to find some modules (e.g. tempfile.py), you
1495may want to check if PYTHONPATH is set correctly.
1496
1497
1498// End of WSDG Chapter Dissection
1499