diff options
author | Gilbert Ramirez <gram@alumni.rice.edu> | 2000-05-12 04:00:05 +0000 |
---|---|---|
committer | Gilbert Ramirez <gram@alumni.rice.edu> | 2000-05-12 04:00:05 +0000 |
commit | af9016663dcc74c929654d57f3ab605cc2b37560 (patch) | |
tree | 0666fb376f651cb3615e71edee8c16148ee88e73 /doc | |
parent | 0c39c03bf544a6968d896818561fd591fdc659e7 (diff) |
Remove proto_tree doc, as all necessary info in it is in README.developer.
Add tvbtest.c to list of packaged files.
svn path=/trunk/; revision=1944
Diffstat (limited to 'doc')
-rw-r--r-- | doc/proto_tree | 471 |
1 files changed, 0 insertions, 471 deletions
diff --git a/doc/proto_tree b/doc/proto_tree deleted file mode 100644 index 2c88513ec9..0000000000 --- a/doc/proto_tree +++ /dev/null @@ -1,471 +0,0 @@ -$Id: proto_tree,v 1.7 1999/11/30 05:49:14 guy Exp $ - -The Ethereal Protocol Tree -========================== - -Up until version 0.6.3 of Ethereal, the protocol tree that is displayed -in the middle pane of the Ethereal GUI had been created by having -the protocol dissection routines add strings to a GTK+ tree. This -GUI container was not easily manipulated; the print routines had to -reach inside what should be an opaque GUI structure and pull out the -data. The tree of strings also did not lend itself to filtering on the -data available in the tree. - -Mostly to solve the display filter problem, I decided to have the protocol -dissection routines put their data into a logical tree instead of a -GUI tree. This tree structure would provide a generic way for multiple -routines, like the dissection routines, the display filter routines, -and the print routines, to retrieve data about the protocol fields. The -GUI routines would then be modified to draw the GUI tree based on the -data in the logical tree. By structuring this logical tree well, with -well-defined field types, Ethereal can have a very powerful display -filter option. No longer would display filters be limited to the ability -of the BPF compiler (libpcap or wiretap), but would have access to the -full range of C field types available within Ethereal. - -In Ethereal 0.7.6, I decided to extend the information that the -programmer must provide about each field. I was frustrated by the way -in which the original proto_tree code handled bitfields. By providing -a small amount of extra info, bitfields can now be added very easily -to the proto_tree. In addition, filtering on bitfields now works -more naturally. - -The protocol tree, or proto_tree, is a GNode, the N-way tree structure -available within GLIB. Of course the protocol dissectors don't care -what a proto_tree really is; they just pass the proto_tree pointer as an -argument to the routines which allow them to add items and new branches -to the tree. - -When a packet is selected in the packet-list pane, a new logical protocol -tree (proto_tree) is created. The pointer to the proto_tree (in this -case, 'protocol tree'), is passed to the top-level protocol dissector, -and then to all subsequent protocol dissectors for that packet, and then -the GUI tree is drawn via proto_tree_draw(). - -Programming for the proto_tree -============================== -The logical proto_tree needs to know detailed information about the -protocols and fields about which information will be collected from the -dissection routines. By strictly defining (or "typing") the data that can -be attached to a proto tree, searching and filtering becomes possible. -This means that the for every protocol and field (which I also call -"header fields", since they are fields in the protocol headers) which -might be attached to a tree, some information is needed. - -Every dissector routine will need to register its protocols and fields -with the central protocol routines (in proto.c). At first I thought I -might keep all the protocol and field information about all the -dissectors in one file, but decentralization seemed like a better idea. -That one file would have gotten very large; one small change would have -required a re-compilation of the entire file. Also, by allowing -registration of protocols and fields at run-time, loadable modules of -protocol dissectors (perhaps even user-supplied) is feasible. - -To do this, each protocol should have a register routine, which will be -called when Ethereal starts. The code to call the register routines is -generated automatically; to arrange that a protocol's register routine -be called at startup: - - the file containing a dissector's "register" routine must be - added to "DISSECTOR_SOURCES" in "Makefile.am"; - - the "register" routine must have a name of the form - "proto_register_XXX"; - - the "register" routine must take no argument, and return no - value; - - the "register" routine's name must appear in the source file - either at the beginning of the line, or preceded only by "void " - at the beginning of the line (that'd typically be the - definition) - other white space shouldn't cause a problem, e.g.: - -void proto_register_XXX(void) { - - ... - -} - -and - -void -proto_register_XXX( void ) -{ - - ... - -} - - and so on should work. - -For every protocol or field that a dissector wants to register, a variable of -type int needs to be used to keep track of the protocol. The IDs are -needed for establishing parent/child relationships between protocols and -fields, as well as associating data with a particular field so that it -can be stored in the logical tree and displayed in the GUI protocol -tree. - -Some dissectors will need to create branches within their tree to help -organize header fields. These branches should be registered as header -fields. Only true protocols should be registered as protocols. This is -so that a display filter user interface knows how to distinguish -protocols from fields. - -A protocol is registered with the name of the protocol and its -abbreviation. - -Here is how the frame "protocol" is registered. - - int proto_frame; - - proto_frame = proto_register_protocol ( - /* name */ "Frame", - /* abbrev */ "frame" ); - - -A header field is also registered with its name and abbreviation, but -information about the its data type is needed. It helps to look at -the header_field_info struct to see what information is expected: - -struct header_field_info { - char *name; - char *abbrev; - enum ftenum type; - int display; - void *strings; - guint bitmask; - char *blurb; - - int id; /* calculated */ - int parent; - int bitshift; /* calculated */ -}; - -name ----- -A string representing the name of the field. This is the name -that will appear in the graphical protocol tree. - -abbrev ------- -A string with an abbreviation of the field. We concatenate the -abbreviation of the parent protocol with an abbreviation for the field, -using a period as a separator. For example, the "src" field in an IP packet -would have "ip.addr" as an abbreviation. It is acceptable to have -multiple levels of periods if, for example, you have fields in your -protocol that are then subdivided into subfields. For example, TRMAC -has multiple error fields, so the abbreviations follow this pattern: -"trmac.errors.iso", "trmac.errors.noniso", etc. - -The abbreviation is the identifier used in a display filter. - -type ----- -The type of value this field holds. The current field types are: - - FT_NONE, - FT_BOOLEAN, - FT_UINT8, - FT_UINT16, - FT_UINT24, - FT_UINT32, - FT_INT8, - FT_INT16, - FT_INT24, - FT_INT32, - FT_DOUBLE, - FT_ABSOLUTE_TIME, - FT_RELATIVE_TIME, - FT_STRING, - FT_ETHER, - FT_BYTES, - FT_IPv4, - FT_IPv6, - FT_IPXNET - -Some of these field types are still not handled in the display filter -routines, but the most common ones are. The FT_UINT* variables all -represent unsigned integers; the number on the end represent how many -bits are used to represent the number. - -display -------- -The display field has a couple of overloaded uses. This is unfortunate, -but since we're C as an application programming language, this sometimes -makes for cleaner programs. Right now I still think that overloading -this variable was okay. - -For integer fields (FT_UINT*), this variable represents the base in -which you would like the value displayed. The acceptable bases are: - BASE_DEC, - BASE_HEX, - BASE_OCT, - BASE_BIN - -For FT_BOOLEAN fields that are also bitfields, 'display' is used -to tell the proto_tree how wide the parent bitfield is. With integers -this is not needed since the type of integer itself (FT_UINT8, FT_UINT16, -FT_UINT24, FT_UINT32) tells the proto_tree how wide the parent bitfield is. - -Additionally, BASE_NONE is used for 'display' as a NULL-value. That is, -for non-integers and non-bitfield FT_BOOLEANs, you'll want to use BASE_NONE -in the 'display' field. - -It is possible that in the future we will record the endianness of -integers. If so, it is likely that we'll use a bitmask on the display field -so that integers would be represented as BEND|BASE_DEC or LEND|BASE_HEX. -But that has not happened yet. - -strings -------- -Some integer fields need labels to represent the true value of a field. -A value_string structure is a way to map values to strings. - -typedef struct _value_string { - guint32 value; - gchar *strptr; -} value_string; - -For FT_UINT* fields, the 'string' field is a pointer to an array of -such value_string structs. (Note: before Ethereal 0.7.6, we had -separate field types like FT_VALS_UINT8 which denoted the use of value_strings. -Now, the non-NULLness of the pointer lets the proto_tree know that -a value_string is meant for this field). - -FT_BOOLEANS have a default map of 0 = "False", 1 (or anything else) = "True". -Sometimes it is useful to change the labels for boolean values (e.g., -to "Yes"/"No", "Fast"/"Slow", etc.). For these mappings, a struct called -true_false_string is used. (This struct is new as of Ethereal 0.7.6). - -typedef struct true_false_string { - char *true_string; - char *false_string; -} true_false_string; - -It's two fields are pointers to the string representing truth, and -the string representing falsehood. For FT_BOOLEAN fields that need a -true_false_string struct, the 'strings' field is a pointer to that struct. - -bitmask -------- -If the field is not a bitfield, then bitmask should be set to 0. -If it is a bitfield, then the bitmask is the mask which will -leave only the bits needed to make the field when ANDed with a value. -The proto_tree routines will calculate 'bitshift' automatically -from 'bitmask', by finding the first set bit in the bitmask. - -blurb ------ -This is a string giving a sentence or two description of the field. -It is meant to provide a more detailed description of the field than the -name alone provides. This information will be used in the man page, and -in a future GUI display-filter creation tool. We might also add tooltips -to the labels in the GUI protocol tree, in which case the blurb would -be used as the tooltip text. - -Field Registration ------------------- -Protocol registration is handled by creating an instance of the -header_field_info struct (or an array of such structs), and -calling the registration function along with the registration ID of -the protocol that is the parent of the fields. Here is a complete example: - - static int proto_eg = -1; - static int hf_field_a = -1; - static int hf_field_b = -1; - - static hf_register_info hf[] = { - - { &hf_field_a, - { "Field A", "proto.field_a", FT_UINT8, BASE_HEX, NULL, - 0xf0, "Field A represents Apples" }}, - - { &hf_field_b, - { "Field B", "proto.field_a", FT_UINT16, BASE_DEC, VALS(vs), - 0x0, "Field B represents Bananas" }} - }; - - proto_eg = proto_register_protocol("Example Protocol", "proto"); - proto_register_field_array(proto_eg, hf, array_length(hf)); - -Be sure that your array of hf_register_info structs is declared 'static', -since the proto_register_field_array() function does not create a copy -of the information in the array... it uses that static copy of the -information that the compiler created inside your array. Here's the -layout of the hf_register_info struct: - -typedef struct hf_register_info { - int *p_id; /* pointer to parent variable */ - header_field_info hfinfo; -} hf_register_info; - -Also be sure to use the handy array_length() macro found in packet.h -to have the compiler compute the array length for you at compile time. - -Adding Items and Values to the Protocol Tree --------------------------------------------- -A protocol item is added to an existing protocol tree with one of a -handful of proto_tree_add_item*() funtions. - -Subtrees can be made with the proto_item_add_subtree() function: - - item = proto_tree_add_item(....); - new_tree = proto_item_add_subtree(item, tree_type); - -Subtree types are integers, assigned by -"proto_register_subtree_array()". To register subtree types, pass an -array of pointers to "gint" variables to hold the subtree type values to -"proto_register_subtree_array()": - - static gint ett_eg = -1; - static gint ett_field_a = -1; - - static gint *ett[] = { - &ett_eg, - &ett_field_a, - }; - - proto_register_subtree_array(ett, array_length(ett)); - -in your "register" routine, just as you register the protocol and the -fields for that protocol. - -There are now 4 functions that the programmer can use to add either -protocol or field labels to the proto_tree: - - proto_item* - proto_tree_add_item(tree, id, start, length, value); - - proto_item* - proto_tree_add_item_format(tree, id, start, length, - value, format, ...); - - proto_item* - proto_tree_add_item_hidden(tree, id, start, length, value); - - proto_item* - proto_tree_add_text(tree, start, length, format, ...); - -proto_tree_add_item() ---------------------- -The first function, proto_tree_add_item, is used when you wish to do no -special formatting. The item added to the GUI tree will contain the name -(as passed in the proto_register_*() function) and any value. If your -field does have a value, it is passed after the length variable (notice -the ellipsis in the function prototype). - -Now that the proto_tree has detailed information about bitfield fields, -you an use proto_tree_add_item() with no extra processing to add bitfield -values to your tree. Here's an example. Take the Format Identifer (FID) -field in the Transmission Header (TH) portion of the SNA protocol. The -FID is the high nibble of the first byte of the TH. The FID would be -registered like this: - - name = "Format Identifer" - abbrev = "sna.th.fid" - type = FT_UINT8 - display = BASE_HEX - strings = sna_th_fid_vals - bitmask = 0xf0 - -The bitmask contains the value which would leave only the FID if bitwise-ANDed -against the parent field, the first byte of the TH. - -The code to add the FID to the tree would be; - - guint8 th_0 = pd[offset]; - proto_tree_add_item(bf_tree, hf_sna_th_fid, offset, 1, th_0); - -Note: we do not do *any* manipulation of th_0 in order to ge the FID value. -We just pass it to proto_tree_add_item(). The proto_tree already has -the information about bitmasking and bitshifting, so it does the work -of masking and shifting for us! This also means that you no longer -have to crate value_string structs with the values bitshifted. The -value_string for FID looks like this, even though the FID value is -actually contained in the high nibble. (You'd expect the values to be -0x0, 0x10, 0x20, etc.) - -/* Format Identifier */ -static const value_string sna_th_fid_vals[] = { - { 0x0, "SNA device <--> Non-SNA Device" }, - { 0x1, "Subarea Node <--> Subarea Node" }, - { 0x2, "Subarea Node <--> PU2" }, - { 0x3, "Subarea Node or SNA host <--> Subarea Node" }, - { 0x4, "?" }, - { 0x5, "?" }, - { 0xf, "Adjaced Subarea Nodes" }, - { 0, NULL } -}; - -The final implication of this is that display filters work the way you'd -naturally expect them to. You'd type "sna.th.fid == 0xf" to find Adjacent -Subarea Nodes. The user does not have to shift the value of the FID to -the high nibble of the byte ("sna.th.fid == 0xf0") as was necessary -before Ethereal 0.7.6. - -proto_tree_add_item_format() ----------------------------- -The second function, proto_tree_add_item_format(), is used when the -dissector routines wants complete control over how the field and value -will be represented on the GUI tree. The caller must pass include the -name of the protocol or field; it is not added automatically as in -proto_tree_add_item(). - -proto_tree_add_item_hidden() ----------------------------- -The third function is used to add fields and values to a tree, but not -show them on a GUI tree. The caller may want a value to be included in a -tree so that the packet can be filtered on this field, but the -representation of that field in the tree is not appropriate. An example -is the token-ring routing information field (RIF). The best way to show the -RIF in a GUI is by a sequence of ring and bridge numbers. Rings are -3-digit hex numbers, and bridges are single hex digits: - - RIF: 001-A-013-9-C0F-B-555 - -In the case of RIF, the programmer should use a field with no value and -use proto_tree_add_item_format() to build the above representation. The -programmer can then add the ring and bridge values, one-by-one, with -proto_tree_add_item_hidden() so that the user can then filter on or -search for a particular ring or bridge. Here's a skeleton of how the -programmer might code this. - - char *rif; - rif = create_rif_string(...); - - proto_tree_add_item_format(tree, hf_tr_rif_label,..., "RIF: %s", rif); - - for(i = 0; i < num_rings; i++) { - proto_tree_add_item_hidden(tree, hf_tr_rif_ring, ..., ring[i]); - } - for(i = 0; i < num_rings - 1; i++) { - proto_tree_add_item_hidden(tree, hf_tr_rif_ring, ..., bridge[i]); - } - -The logical tree has these items: - - hf_tr_rif_label, text="RIF: 001-A-013-9-C0F-B-555", value = NONE - hf_tr_rif_ring, hidden, value=0x001 - hf_tr_rif_bridge, hidden, value=0xA - hf_tr_rif_ring, hidden, value=0x013 - hf_tr_rif_bridge, hidden, value=0x9 - hf_tr_rif_ring, hidden, value=0xC0F - hf_tr_rif_bridge, hidden, value=0xB - hf_tr_rif_ring, hidden, value=0x555 - -GUI or print code will not display the hidden fields, but a display -filter or "packet grep" routine will still see the values. The possible -filter is then possible: - - tr.rif_ring eq 0x013 - -proto_tree_add_text() ---------------------- -The fourth function, proto_tree_add_text(), is used to add a label to the GUI tree. -It will contain no value, so it is not searchable in the display filter process. -This function was needed in the transition from the old-style proto_tree to this -new-style proto_tree so that Ethereal would still decode all protocols w/o being -able to filter on all protocols and fields. Otherwise we would have had to -cripple Ethereal's functionality while we converted all the old-style proto_tree -calls to the new-style proto_tree calls. - |