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