More constification of arrays.
[obnox/wireshark/wip.git] / doc / README.developer
index c7b524da7be1d89182ca743d6603db57b72b9ed6..300be484f492e0e66f13b4a65a6d7c6e7af1e7d4 100644 (file)
@@ -1,4 +1,4 @@
-$Id: README.developer,v 1.47 2002/02/28 23:23:12 guy Exp $
+$Id$
 
 This file is a HOWTO for Ethereal developers. It describes how to start coding
 a Ethereal protocol dissector and the use some of the important functions and
@@ -27,6 +27,10 @@ example, doesn't do so by default).
 Don't use zero-length arrays; not all compilers support them.  If an
 array would have no members, just leave it out.
 
+Don't declare variables in the middle of executable code; not all C
+compilers support that.  Variables should be declared outside a
+function, or at the beginning of a function or compound statement.
+
 Don't use "inline"; not all compilers support it.  If you want to have a
 function be an inline function if the compiler supports it, use
 G_INLINE_FUNC, which is declared by <glib.h>.  This may not work with
@@ -34,13 +38,46 @@ functions declared in header files; if it doesn't work, don't declare
 the function in a header file, even if this requires that you not make
 it inline on any platform.
 
-Don't use "long long"; use "gint64" or "guint64", and only do so if
-G_HAVE_GINT64 is defined.  Make sure your code works even if
-G_HAVE_GINT64 isn't defined, even if that means treating 64-bit integral
-data types as opaque arrays of bytes on platforms where it's not
-defined.  Also, don't assume you can use "%lld", "%llu", "%llx", or
-"%llo" to print 64-bit integral data types - not all platforms support
-"%ll" for printing them.
+Don't use "uchar", "u_char", "ushort", "u_short", "uint", "u_int",
+"ulong", or "u_long"; they aren't defined on all platforms.  If you want
+an 8-bit unsigned quantity, use "guint8"; if you want an 8-bit character
+value with the 8th bit not interpreted as a sign bit, use "guchar"; if
+you want a 16-bit unsigned quantity, use "guint16"; if you want a 32-bit
+unsigned quantity, use "guint32"; and if you want an "int-sized"
+unsigned quantity, use "guint".  Use "%d", "%u", "%x", and "%o" to print
+those types; don't use "%ld", "%lu", "%lx", or "%lo", as longs are 64
+bits long on many platforms, but "guint32" is 32 bits long.
+
+Don't use "long" to mean "signed 32-bit integer", and don't use
+"unsigned long" to mean "unsigned 32-bit integer"; "long"s are 64 bits
+long on many platforms.  Use "gint32" for signed 32-bit integers and use
+"guint32" for unsigned 32-bit integers.
+
+Don't use "long" to mean "signed 64-bit integer" and don't use "unsigned
+long" to mean "unsigned 64-bit integer"; "long"s are 32 bits long on
+other many platforms.  Don't use "long long" or "unsigned long long",
+either, as not all platforms support them; use "gint64" or "guint64",
+which will be defined as the appropriate types for 64-bit signed and
+unsigned integers.
+
+When printing or displaying the values of 64-bit integral data types,
+don't assume use "%lld", "%llu", "%llx", or "%llo" - not all platforms
+support "%ll" for printing 64-bit integral data types.  Instead, use
+PRId64, PRIu64, PRIx64, and PRIo64, for example
+
+    proto_tree_add_text(tree, tvb, offset, 8,
+                       "Sequence Number: %" PRIu64, sequence_number);
+
+When specifying an integral constant that doesn't fit in 32 bits, don't
+use "LL" at the end of the constant - not all compilers use "LL" for
+that.  Instead, put the constant in a call to the "G_GINT64_CONSTANT()"
+macro, e.g.
+
+       G_GINT64_CONSTANT(11644473600U)
+
+rather than
+
+       11644473600ULL
 
 Don't use a label without a statement following it.  For example,
 something such as
@@ -64,13 +101,309 @@ will not work with all compilers - you have to do
 
 with some statement, even if it's a null statement, after the label.
 
-1.1.2 Name convention.
+Don't use "bzero()", "bcopy()", or "bcmp()"; instead, use the ANSI C
+routines
+
+       "memset()" (with zero as the second argument, so that it sets
+       all the bytes to zero);
+
+       "memcpy()" or "memmove()" (note that the first and second
+       arguments to "memcpy()" are in the reverse order to the
+       arguments to "bcopy()"; note also that "bcopy()" is typically
+       guaranteed to work on overlapping memory regions, while
+       "memcpy()" isn't, so if you may be copying from one region to a
+       region that overlaps it, use "memmove()", not "memcpy()" - but
+       "memcpy()" might be faster as a result of not guaranteeing
+       correct operation on overlapping memory regions);
+
+       and "memcmp()" (note that "memcmp()" returns 0, 1, or -1, doing
+       an ordered comparison, rather than just returning 0 for "equal"
+       and 1 for "not equal", as "bcmp()" does).
+
+Not all platforms necessarily have "bzero()"/"bcopy()"/"bcmp()", and
+those that do might not declare them in the header file on which they're
+declared on your platform.
+
+Don't use "index()" or "rindex()"; instead, use the ANSI C equivalents,
+"strchr()" and "strrchr()".  Not all platforms necessarily have
+"index()" or "rindex()", and those that do might not declare them in the
+header file on which they're declared on your platform.
+
+Don't fetch data from packets by getting a pointer to data in the packet
+with "tvb_get_ptr()", casting that pointer to a pointer to a structure,
+and dereferencing that pointer.  That point won't necessarily be aligned
+on the proper boundary, which can cause crashes on some platforms (even
+if it doesn't crash on an x86-based PC); furthermore, the data in a
+packet is not necessarily in the byte order of the machine on which
+Ethereal is running.  Use the tvbuff routines to extract individual
+items from the packet, or use "proto_tree_add_item()" and let it extract
+the items for you.
+
+Don't use "ntohs()", "ntohl()", "htons()", or "htonl()"; the header
+files required to define or declare them differ between platforms, and
+you might be able to get away with not including the appropriate header
+file on your platform but that might not work on other platforms. 
+Instead, use "g_ntohs()", "g_ntohl()", "g_htons()", and "g_htonl()";
+those are declared by <glib.h>, and you'll need to include that anyway,
+as Ethereal header files that all dissectors must include use stuff from
+<glib.h>.
+
+Don't put a comma after the last element of an enum - some compilers may
+either warn about it (producing extra noise) or refuse to accept it.
+
+Don't include <unistd.h> without protecting it with
+
+       #ifdef HAVE_UNISTD_H
+
+               ...
+
+       #endif
+
+and, if you're including it to get routines such as "open()", "close()",
+"read()", and "write()" declared, also include <io.h> if present:
+
+       #ifdef HAVE_IO_H
+       #include <io.h>
+       #endif
+
+in order to declare the Windows C library routines "_open()",
+"_close()", "_read()", and "_write()".  Your file must include <glib.h>
+- which many of the Ethereal header files include, so you might not have
+to include it explicitly - in order to get "open()", "close()",
+"read()", "write()", etc. mapped to "_open()", "_close()", "_read()",
+"_write()", etc..
+
+When opening a file with "fopen()", "freopen()", or "fdopen()", if the
+file contains ASCII text, use "r", "w", "a", and so on as the open mode
+- but if it contains binary data, use "rb", "wb", and so on.  On
+Windows, if a file is opened in a text mode, writing a byte with the
+value of octal 12 (newline) to the file causes two bytes, one with the
+value octal 15 (carriage return) and one with the value octal 12, to be
+written to the file, and causes bytes with the value octal 15 to be
+discarded when reading the file (to translate between C's UNIX-style
+lines that end with newline and Windows' DEC-style lines that end with
+carriage return/line feed).
+
+In addition, that also means that when opening or creating a binary
+file, you must use "open()" (with O_CREAT and possibly O_TRUNC if the
+file is to be created if it doesn't exist), and OR in the O_BINARY flag. 
+That flag is not present on most, if not all, UNIX systems, so you must
+also do
+
+       #ifndef O_BINARY
+       #define O_BINARY        0
+       #endif
+
+to properly define it for UNIX (it's not necessary on UNIX).
+
+Don't use forward declarations of static arrays without a specified size
+in a fashion such as this:
+
+       static const value_string foo_vals[];
+
+               ...
+
+       static const value_string foo_vals[] = {
+               { 0,            "Red" },
+               { 1,            "Green" },
+               { 2,            "Blue" },
+               { 0,            NULL }
+       };
+
+as some compilers will reject the first of those statements.  Instead,
+initialize the array at the point at which it's first declared, so that
+the size is known.
+
+Don't put declarations in the middle of a block; put them before all
+code.  Not all compilers support declarations in the middle of code,
+such as
+
+       int i;
+
+       i = foo();
+
+       int j;
+
+For #define names and enum member names, prefix the names with a tag so
+as to avoid collisions with other names - this might be more of an issue
+on Windows, as it appears to #define names such as DELETE and
+OPTIONAL.
+
+Don't use the "numbered argument" feature that many UNIX printf's
+implement, e.g.:
+
+       sprintf(add_string, " - (%1$d) (0x%1$04x)", value);
+
+as not all UNIX printf's implement it, and Windows printf doesn't appear
+to implement it.  Use something like
+
+       sprintf(add_string, " - (%d) (0x%04x)", value, value);
+
+instead.
+
+Don't use "variadic macros", such as
+
+       #define DBG(format, args...)    fprintf(stderr, format, ## args)
+
+as not all C compilers support them.  Use macros that take a fixed
+number of arguments, such as
+
+       #define DBG0(format)            fprintf(stderr, format)
+       #define DBG1(format, arg1)      fprintf(stderr, format, arg1)
+       #define DBG2(format, arg1, arg2) fprintf(stderr, format, arg1, arg2)
+
+               ...
+
+or something such as
+
+       #define DBG(args)               printf args
+
+snprintf() -> g_snprintf()
+snprintf() is not available on all platforms, so it's a good idea to use the 
+g_snprintf() function declared by <glib.h> instead.
+
+tmpnam() -> mkstemp()
+tmpnam is insecure and should not be used any more. Ethereal brings its
+own mkstemp implementation for use on platforms that lack mkstemp.
+Note: mkstemp does not accept NULL as a parameter.
+
+The pointer retured by a call to "tvb_get_ptr()" is not guaranteed to be
+aligned on any particular byte boundary; this means that you cannot
+safely cast it to any data type other than a pointer to "char",
+"unsigned char", "guint8", or other one-byte data types.  You cannot,
+for example, safely cast it to a pointer to a structure, and then access
+the structure members directly; on some systems, unaligned accesses to
+integral data types larger than 1 byte, and floating-point data types,
+cause a trap, which will, at best, result in the OS slowly performing an
+unaligned access for you, and will, on at least some platforms, cause
+the program to be terminated.
+
+Ethereal supports both platforms with GLib 1.2[.x]/GTK+ 1.2[.x] and GLib
+2.x/GTK+ 1.3[.x] and 2.x.  If at all possible, either use only
+mechanisms that are present in GLib 1.2[.x] and GTK+ 1.2[.x], use #if's
+to conditionally use older or newer mechanisms depending on the platform
+on which Ethereal is being built, or, if the code in GLib or GTK+ that
+implements that mechanism will build with GLib 1.2[.x]/GTK+ 1.2[.x],
+conditionally include that code as part of the Ethereal source and use
+the included version with GLib 1.2[.x] or GTK+ 1.2[.x].  In particular,
+if the GLib 2.x or GTK+ 2.x mechanism indicates that a routine is
+deprecated and shouldn't be used in new code, and that it was renamed in
+GLib 2.x or GTK+ 2.x and the new name should be used, disregard that and
+use the old name - it'll still work with GLib 2.x or GTK+ 2.x, but will
+also work with GLib 1.2[.x] and GTK+ 1.2[.x].
+
+When different code must be used on UN*X and Win32, use a #if or #ifdef
+that tests _WIN32, not WIN32.  Try to write code portably whenever
+possible, however; note that there are some routines in Ethereal with
+platform-dependent implementations and platform-independent APIs, such
+as the routines in epan/filesystem.c, allowing the code that calls it to
+be written portably without #ifdefs.
+
+1.1.2 Robustness.
+
+Ethereal is not guaranteed to read only network traces that contain
+correctly-formed packets; in fact, one of the reasons why Ethereal is
+used is to track down networking problems, and the problems might be due
+to a buggy protocol implementation sending out bad packets.
+
+Therefore, protocol dissectors not only have to be able to handle
+correctly-formed packets without, for example, crashing or looping
+infinitely, they also have to be able to handle *incorrectly*-formed
+packets without crashing or looping infinitely.
+
+Here are some suggestions for making dissectors more robust in the face
+of incorrectly-formed packets:
+
+If you are allocating a chunk of memory to contain data from a packet,
+or to contain information derived from data in a packet, and the size of
+the chunk of memory is derived from a size field in the packet, make
+sure all the data is present in the packet before allocating the buffer.
+Doing so means that
+
+       1) Ethereal won't leak that chunk of memory if an attempt to
+          fetch data not present in the packet throws an exception
+
+and
+
+       2) it won't crash trying to allocate an absurdly-large chunk of
+          memory if the size field has a bogus large value.
+
+If you're fetching into such a chunk of memory a string from the buffer,
+and the string has a specified size, you can use "tvb_get_string()",
+which will check whether the entire string is present before allocating
+a buffer for the string, and will also put a trailing '\0' at the end of
+the buffer.
+
+If you're fetching into such a chunk of memory a 2-byte Unicode string
+from the buffer, and the string has a specified size, you can use
+"tvb_fake_unicode()", which will check whether the entire string is
+present before allocating a buffer for the string, and will also put a
+trailing '\0' at the end of the buffer.  The resulting string will be a
+sequence of single-byte characters; the only Unicode characters that
+will be handled correctly are those in the ASCII range.  (Ethereal's
+ability to handle non-ASCII strings is limited; it needs to be
+improved.)
+
+If you're fetching into such a chunk of memory a sequence of bytes from
+the buffer, and the sequence has a specified size, you can use
+"tvb_memdup()", which will check whether the entire sequence is present
+before allocating a buffer for it.
+
+Otherwise, you can check whether the data is present by using
+"tvb_ensure_bytes_exist()" or by getting a pointer to the data by using
+"tvb_get_ptr()", although note that there might be problems with using
+the pointer from "tvb_get_ptr()" (see the item on this in the
+Portability section above, and the next item below).
+
+If you have gotten a pointer using "tvb_get_ptr()", you must make sure
+that you do not refer to any data past the length passed as the last
+argument to "tvb_get_ptr()"; while the various "tvb_get" routines
+perform bounds checking and throw an exception if you refer to data not
+available in the tvbuff, direct references through a pointer gotten from
+"tvb_get_ptr()" do not do any bounds checking.
+
+If you have a loop that dissects a sequence of items, each of which has
+a length field, with the offset in the tvbuff advanced by the length of
+the item, then, if the length field is the total length of the item, and
+thus can be zero, you *MUST* check for a zero-length item and abort the
+loop if you see one.  Otherwise, a zero-length item could cause the
+dissector to loop infinitely.  You should also check that the offset,
+after having the length added to it, is greater than the offset before
+the length was added to it, if the length field is greater than 24 bits
+long, so that, if the length value is *very* large and adding it to the
+offset causes an overflow, that overflow is detected.
+
+Any tvbuff offset that is added to as processing is done on a packet
+should be stored in a 32-bit variable, such as an "int"; if you store it
+in an 8-bit or 16-bit variable, you run the risk of the variable
+overflowing.
+
+sprintf() -> g_snprintf()
+Prevent yourself from using the sprintf() function, as it does not test the 
+length of the given output buffer and might be writing into memory areas not 
+intended for. This function is one of the main causes of security problems 
+like buffer exploits and many other bugs that are very hard to find. It's 
+much better to use the g_snprintf() function declared by <glib.h> instead.
+
+1.1.3 Name convention.
 
 Ethereal uses the underscore_convention rather than the InterCapConvention for
 function names, so new code should probably use underscores rather than
 intercaps for functions and variable names. This is especially important if you
 are writing code that will be called from outside your code.  We are just
-trying to keep thing consistent for other users.
+trying to keep things consistent for other users.
+
+1.1.4 White space convention.
+
+Avoid using tab expansions different from 8 spaces, as not all text editors in
+use by the developers support this.
+
+When creating a new file, you are free to choose an indentation logic. Most of
+the files in Ethereal tend to use 2-space or 4-space indentation. You are
+encouraged to write a short comment on the indentation logic at the beginning
+of this new file.
+
+When editing an existing file, try following the existing indentation logic.
 
 1.2 Skeleton code.
 
@@ -93,25 +426,30 @@ You may not need to include all the headers listed in the skeleton
 below, and you may need to include additional headers.  For example, the
 code inside
 
-       #ifdef NEED_SNPRINTF_H
+       #ifdef HAVE_LIBPCRE
 
                ...
 
        #endif
 
-is needed only if you are using the "snprintf()" function.
+is needed only if you are using a function from libpcre, e.g. the
+"pcre_compile()" function.
 
-The "$Id: README.developer,v 1.47 2002/02/28 23:23:12 guy Exp $"
+The "$Id$"
 in the comment will be updated by CVS when the file is
 checked in; it will allow the RCS "ident" command to report which
 version of the file is currently checked out.
 
+When creating a new file, it is fine to just write "$Id$" as RCS will
+automatically fill in the identifier at the time the file will be added to the
+CVS repository (checked in).
+
 ------------------------------------Cut here------------------------------------
 /* packet-PROTOABBREV.c
  * Routines for PROTONAME dissection
  * Copyright 2000, YOUR_NAME <YOUR_EMAIL_ADDRESS>
  *
- * $Id: README.developer,v 1.47 2002/02/28 23:23:12 guy Exp $
+ * $Id$
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -146,21 +484,12 @@ version of the file is currently checked out.
 #include <stdlib.h>
 #include <string.h>
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
 #include <glib.h>
 
-#ifdef NEED_SNPRINTF_H
-# include "snprintf.h"
-#endif
-
 #include <epan/packet.h>
+
+/* IF PROTO exposes code to other dissectors, then it must be exported
+   in a header file. If not, a header file is not needed at all. */
 #include "packet-PROTOABBREV.h"
 
 /* Initialize the protocol and registered fields */
@@ -213,8 +542,43 @@ dissect_PROTOABBREV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        if (check_col(pinfo->cinfo, COL_INFO)) 
                col_set_str(pinfo->cinfo, COL_INFO, "XXX Request");
 
-/* In the interest of speed, if "tree" is NULL, don't do any work not
-   necessary to generate protocol tree items. */
+/* A protocol dissector can be called in 2 different ways:
+
+       (a) Operational dissection
+
+               In this mode, Ethereal is only interested in the way protocols
+               interact, protocol conversations are created, packets are reassembled
+               and handed over to higher-level protocol dissectors.
+               This way Ethereal does not build a so-called "protocol tree".
+
+       (b) Detailed dissection
+
+               In this mode, Ethereal is also interested in all details of a given
+               protocol, so a "protocol tree" is created.
+
+   Ethereal distinguishes between the 2 modes with the proto_tree pointer:
+       (a) <=> tree == NULL
+       (b) <=> tree != NULL
+
+   In the interest of speed, if "tree" is NULL, avoid building a
+   protocol tree and adding stuff to it, or even looking at any packet
+   data needed only if you're building the protocol tree, if possible.
+
+   Note, however, that you must fill in column information, create
+   conversations, reassemble packets, build any other persistent state
+   needed for dissection, and call subdissectors regardless of whether
+   "tree" is NULL or not.  This might be inconvenient to do without
+   doing most of the dissection work; the routines for adding items to
+   the protocol tree can be passed a null protocol tree pointer, in
+   which case they'll return a null item pointer, and
+   "proto_item_add_subtree()" returns a null tree pointer if passed a
+   null item pointer, so, if you're careful not to dereference any null
+   tree or item pointers, you can accomplish this by doing all the
+   dissection work.  This might not be as efficient as skipping that
+   work if you're not building a protocol tree, but if the code would
+   have a lot of tests whether "tree" is null if you skipped that work,
+   you might still be better off just doing all that work regardless of
+   whether "tree" is null or not. */
        if (tree) {
 
 /* NOTE: The offset and length values in the call to
@@ -231,7 +595,8 @@ dissect_PROTOABBREV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                PROTOABBREV_tree = proto_item_add_subtree(ti, ett_PROTOABBREV);
 
 /* add an item to the subtree, see section 1.6 for more information */
-               proto_tree_add_uint(tree, hf_PROTOABBREV_FIELDABBREV, tvb, offset, len, value)
+               proto_tree_add_item(PROTOABBREV_tree,
+                   hf_PROTOABBREV_FIELDABBREV, tvb, offset, len, FALSE)
 
 
 /* Continue adding tree items to process the packet here */
@@ -258,7 +623,7 @@ proto_register_PROTOABBREV(void)
                { &hf_PROTOABBREV_FIELDABBREV,
                        { "FIELDNAME",           "PROTOABBREV.FIELDABBREV",
                        FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,          
-                       "FIELDDESCR" }
+                       "FIELDDESCR", HFILL }
                },
        };
 
@@ -303,17 +668,24 @@ YOUR_NAME Your name, of course.  You do want credit, don't you?
 YOUR_EMAIL_ADDRESS     Keep those cards and letters coming.
 WHATEVER_FILE_YOU_USED Add this line if you are using another file as a
                starting point.
-PROTONAME      The name of the protocol.
-PROTOABBREV    An abbreviated name for the protocol. (NO SPACES) (rec. 
-               a-z, 0-9 only and try to conform with IANA names)
+PROTONAME      The name of the protocol; this is displayed in the
+               top-level protocol tree item for that protocol.
+PROTOSHORTNAME An abbreviated name for the protocol; this is displayed
+               in the "Preferences" dialog box if your dissector has
+               any preferences, and in the dialog box for filter fields
+               when constructing a filter expression.
+PROTOABBREV    A name for the protocol for use in filter expressions;
+               it should contain only lower-case letters, digits, and
+               hyphens.
 FIELDNAME      The displayed name for the header field.
 FIELDABBREV    The abbreviated name for the header field. (NO SPACES)
 FIELDTYPE      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_STRINGZ, FT_UINT_STRING, FT_ETHER, FT_BYTES, FT_IPv4,
-               FT_IPv6, FT_IPXNET
-FIELDBASE      BASE_NONE, BASE_DEC, BASE_HEX, BASE_OCT, BASE_BIN
+               FT_UINT32, FT_UINT64, FT_INT8, FT_INT16, FT_INT24, FT_INT32,
+               FT_INT64, FT_FLOAT, FT_DOUBLE, FT_ABSOLUTE_TIME,
+               FT_RELATIVE_TIME, FT_STRING, FT_STRINGZ, FT_UINT_STRING,
+               FT_ETHER, FT_BYTES, FT_IPv4, FT_IPv6, FT_IPXNET,
+               FT_FRAMENUM
+FIELDBASE      BASE_NONE, BASE_DEC, BASE_HEX, BASE_OCT
 FIELDCONVERT   VALS(x), TFS(x), NULL
 BITMASK                Usually 0x0 unless using the TFS(x) field conversion.
 FIELDDESCR     A brief description of the field.
@@ -321,6 +693,9 @@ PARENT_SUBFIELD     Lower level protocol field used for lookup, i.e. "tcp.port"
 ID_VALUE       Lower level protocol field value that identifies this protocol
                For example the TCP or UDP port number
 
+If, for example, PROTONAME is "Internet Bogosity Discovery Protocol",
+PROTOSHORTNAME would be "IBDP", and PROTOABBREV would be "ibdp".  Try to
+conform with IANA names.
 
 1.4 The dissector and the data it receives.
 
@@ -328,7 +703,8 @@ ID_VALUE    Lower level protocol field value that identifies this protocol
 1.4.1 Header file.
 
 This is only needed if the dissector doesn't use self-registration to
-register itself with the lower level dissector.
+register itself with the lower level dissector, or if the protocol dissector
+wants/needs to expose code to other subdissectors.
 
 The dissector has the following header that must be placed into
 packet-PROTOABBREV.h.
@@ -354,20 +730,32 @@ Single-byte accessor:
 
 guint8  tvb_get_guint8(tvbuff_t*, gint offset);
 
-Network-to-host-order access for shorts (guint16), longs (guint24), and
-24-bit ints:
+Network-to-host-order accessors for 16-bit integers (guint16), 32-bit
+integers (guint32), and 24-bit integers:
 
 guint16 tvb_get_ntohs(tvbuff_t*, gint offset);
 guint32 tvb_get_ntohl(tvbuff_t*, gint offset);
 guint32 tvb_get_ntoh24(tvbuff_t*, gint offset);
 
-Little-Endian-to-host-order access for shorts (guint16), longs (guint24), and
-24-bit ints:
+Network-to-host-order accessors for single-precision and
+double-precision IEEE floating-point numbers:
+
+gfloat tvb_get_ntohieee_float(tvbuff_t*, gint offset);
+gdouble tvb_get_ntohieee_double(tvbuff_t*, gint offset);
+
+Little-Endian-to-host-order accessors for 16-bit integers (guint16),
+32-bit integers (guint32), and 24-bit integers:
 
 guint16 tvb_get_letohs(tvbuff_t*, gint offset);
 guint32 tvb_get_letohl(tvbuff_t*, gint offset);
 guint32 tvb_get_letoh24(tvbuff_t*, gint offset);
 
+Little-Endian-to-host-order accessors for single-precision and
+double-precision IEEE floating-point numbers:
+
+gfloat tvb_get_letohieee_float(tvbuff_t*, gint offset);
+gdouble tvb_get_letohieee_double(tvbuff_t*, gint offset);
+
 NOTE: IPv4 addresses are not to be converted to host byte order before
 being passed to "proto_tree_add_ipv4()".  You should use "tvb_memcpy()"
 to fetch them, not "tvb_get_ntohl()" *OR* "tvb_get_letohl()" - don't,
@@ -376,10 +764,35 @@ wrong answer on the PC on which you're doing development, and try
 "tvb_get_letohl()" instead, as "tvb_get_letohl()" will give the wrong
 answer on big-endian machines.
 
+String accessors:
+
+guint8 *tvb_get_string(tvbuff_t*, gint offset, gint length);
+
+Returns a null-terminated buffer, allocated with "g_malloc()" (so it
+must be freed with "g_free()"), containing data from the specified
+tvbuff, starting at the specified offset, and containing the specified
+length worth of characters (the length of the buffer will be length+1,
+as it includes a null character to terminate the string).
+
+guint8 *tvb_get_stringz(tvbuff_t *tvb, gint offset, gint *lengthp);
+
+Returns a null-terminated buffer, allocated with "g_malloc()",
+containing data from the specified tvbuff, starting with at the
+specified offset, and containing all characters from the tvbuff up to
+and including a terminating null character in the tvbuff.  "*lengthp"
+will be set to the length of the string, including the terminating null.
+
 Copying memory:
 guint8* tvb_memcpy(tvbuff_t*, guint8* target, gint offset, gint length);
+
+Copies into the specified target the specified length's worth of data
+from the specified tvbuff, starting at the specified offset.
+
 guint8* tvb_memdup(tvbuff_t*, gint offset, gint length);
 
+Returns a buffer, allocated with "g_malloc()", containing the specified
+length's worth of data from the specified tvbuff, starting at the
+specified offset.
 
 Pointer-retrieval:
 /* WARNING! This function is possibly expensive, temporarily allocating
@@ -389,11 +802,12 @@ Pointer-retrieval:
  */ 
 guint8* tvb_get_ptr(tvbuff_t*, gint offset, gint length);
 
-The reason that tvb_get_ptr() have to allocate a copy of its data only
-occurs with TVBUFF_COMPOSITES, data that spans multiple tvbuffers. If the
-user request a pointer to a range of bytes that spans the member tvbuffs that
-make up the TVBUFF_COMPOSITE, the data will have to be copied to another
-memory region to assure that all the bytes are contiguous.
+The reason that tvb_get_ptr() might have to allocate a copy of its data
+only occurs with TVBUFF_COMPOSITES, data that spans multiple tvbuffers. 
+If the user request a pointer to a range of bytes that spans the member
+tvbuffs that make up the TVBUFF_COMPOSITE, the data will have to be
+copied to another memory region to assure that all the bytes are
+contiguous.
 
 
 
@@ -417,7 +831,7 @@ packet for that protocol, is COL_INFO.
 
 A value for a column should only be added if the user specified that it
 be displayed; to check whether a given column is to be displayed, call
-'col_info' with the COL_ value for that field as an argument - it will
+'check_col' with the COL_ value for that field as an argument - it will
 return TRUE if the column is to be displayed and FALSE if it is not to
 be displayed.
 
@@ -535,6 +949,14 @@ it yourself as part of the string being appended.)
 current value for the column, rather than replacing the value for that
 column.
 
+1.5.7 The col_append_sep_str and col_append_sep_fstr functions.
+
+In specific situations the developer knows that a column's value will be
+created in a stepwise manner, where the appended values are listed. Both
+'col_append_sep_str' and 'col_append_sep_fstr' functions will add an item
+separator between two consecutive items, and will not add the separator at the
+beginning of the column. The remainder of the work both functions do is
+identical to what 'col_append_str' and 'col_append_fstr' do.
 
 1.6 Constructing the protocol tree.
 
@@ -577,7 +999,7 @@ 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";
+       added to "DISSECTOR_SRC" in "epan/dissectors/Makefile.common";
  
        the "register" routine must have a name of the form
        "proto_register_XXX";
@@ -661,7 +1083,7 @@ 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
+would have "ip.src" 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:
@@ -685,21 +1107,27 @@ The type of value this field holds. The current field types are:
                                FT_NONE field.
        FT_BOOLEAN              0 means "false", any other value means
                                "true".
+       FT_FRAMENUM             A frame number; if this is used, the "Go
+                               To Corresponding Frame" menu item can
+                               work on that field.
        FT_UINT8                An 8-bit unsigned integer.
        FT_UINT16               A 16-bit unsigned integer.
        FT_UINT24               A 24-bit unsigned integer.
        FT_UINT32               A 32-bit unsigned integer.
+       FT_UINT64               A 64-bit unsigned integer.
        FT_INT8                 An 8-bit signed integer.
        FT_INT16                A 16-bit signed integer.
        FT_INT24                A 24-bit signed integer.
        FT_INT32                A 32-bit signed integer.
-       FT_DOUBLE               A floating point number.
-       FT_ABSOLUTE_TIME        Seconds (4 bytes) and microseconds (4 bytes)
+       FT_INT64                A 64-bit signed integer.
+       FT_FLOAT                A single-precision floating point number.
+       FT_DOUBLE               A double-precision floating point number.
+       FT_ABSOLUTE_TIME        Seconds (4 bytes) and nanoseconds (4 bytes)
                                of time displayed as month name, month day,
-                               year, hours, minutes, and seconds with 4
+                               year, hours, minutes, and seconds with 9
                                digits after the decimal point.
-       FT_RELATIVE_TIME        Seconds (4 bytes) and microseconds (4 bytes)
-                               of time displayed as seconds and 6 digits
+       FT_RELATIVE_TIME        Seconds (4 bytes) and nanoseconds (4 bytes)
+                               of time displayed as seconds and 9 digits
                                after the decimal point.
        FT_STRING               A string of characters, not necessarily
                                NUL-terminated, but possibly NUL-padded.
@@ -743,12 +1171,10 @@ are:
 
        BASE_DEC,
        BASE_HEX,
-       BASE_OCT,
-       BASE_BIN
+       BASE_OCT
 
 BASE_DEC, BASE_HEX, and BASE_OCT are decimal, hexadecimal, and octal,
-respectively.  BASE_BIN is reserved for binary, although it's currently
-treated as decimal - if you want decimal, use BASE_DEC, not BASE_BIN.
+respectively.
 
 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
@@ -790,11 +1216,6 @@ For fields of that type, you would declare an array of "value_string"s:
 indicate the end of the array).  The 'strings' field would be set to
 'VALS(valstringname)'.
 
-(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).
-
 If the field has a numeric rather than an enumerated type, the 'strings'
 field would be set to NULL.
 
@@ -858,11 +1279,11 @@ the protocol that is the parent of the fields. Here is a complete example:
 
                { &hf_field_a,
                { "Field A",    "proto.field_a", FT_UINT8, BASE_HEX, NULL,
-                       0xf0, "Field A represents Apples" }},
+                       0xf0, "Field A represents Apples", HFILL }},
 
                { &hf_field_b,
                { "Field B",    "proto.field_b", FT_UINT16, BASE_DEC, VALS(vs),
-                       0x0, "Field B represents Bananas" }}
+                       0x0, "Field B represents Bananas", HFILL }}
        };
 
        proto_eg = proto_register_protocol("Example Protocol",
@@ -888,10 +1309,36 @@ If you don't have any fields to register, do *NOT* create a zero-length
 Just omit the "hf" array, and the "proto_register_field_array()" call,
 entirely.
 
+It is OK to have header fields with a different format be registered with
+the same abbreviation. For instance, the following is valid:
+
+       static hf_register_info hf[] = {
+
+               { &hf_field_8bit, /* 8-bit version of proto.field */
+               { "Field (8 bit)", "proto.field", FT_UINT8, BASE_DEC, NULL,
+                       0x00, "Field represents FOO", HFILL }},
+
+               { &hf_field_32bit, /* 32-bit version of proto.field */
+               { "Field (32 bit)", "proto.field", FT_UINT32, BASE_DEC, NULL,
+                       0x00, "Field represents FOO", HFILL }}
+       };
+
+This way a filter expression can match a header field, irrespective of the
+representation of it in the specific protocol context. This is interesting
+for protocols with variable-width header fields.
+
+The HFILL macro at the end of the struct will set resonable default values
+for internally used fields.
+
 1.6.2 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_XXX() functions.
+handful of proto_XXX_DO_YYY() functions.
+
+Remember that it only makes sense to add items to a protocol tree if its
+proto_tree pointer is not null. Should you add an item to a NULL tree, then
+the proto_XXX_DO_YYY() function will immediately return. The cost of this
+function call can be avoided by checking for the tree pointer.
 
 Subtrees can be made with the proto_item_add_subtree() function:
 
@@ -924,59 +1371,163 @@ There are several 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_tree_add_item(tree, id, tvb, start, length, little_endian);
 
        proto_item*
-       proto_tree_add_item_hidden(tree, id, start, length, value);
+       proto_tree_add_item_hidden(tree, id, tvb, start, length, little_endian);
 
        proto_item*
-       proto_tree_add_protocol_format(tree, id, start, length, format, ...);
+       proto_tree_add_none_format(tree, id, tvb, start, length, format, ...);
+
+       proto_item*
+       proto_tree_add_protocol_format(tree, id, tvb, start, length,
+           format, ...);
+
+       proto_item *
+       proto_tree_add_bytes(tree, id, tvb, start, length, start_ptr);
+
+       proto_item *
+       proto_tree_add_bytes_hidden(tree, id, tvb, start, length, start_ptr);
 
        proto_item *
-       proto_tree_add_bytes_format(tree, id, start, length, start_ptr,
+       proto_tree_add_bytes_format(tree, id, tvb, start, length, start_ptr,
            format, ...);
 
        proto_item *
-       proto_tree_add_time_format(tree, id, start, length, value_ptr,
+       proto_tree_add_time(tree, id, tvb, start, length, value_ptr);
+
+       proto_item *
+       proto_tree_add_time_hidden(tree, id, tvb, start, length, value_ptr);
+
+       proto_item *
+       proto_tree_add_time_format(tree, id, tvb, start, length, value_ptr,
            format, ...);
 
        proto_item *
-       proto_tree_add_ipxnet_format(tree, id, start, length, value,
+       proto_tree_add_ipxnet(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_ipxnet_hidden(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_ipxnet_format(tree, id, tvb, start, length, value,
            format, ...);
 
        proto_item *
-       proto_tree_add_ipv4_format(tree, id, start, length, value,
+       proto_tree_add_ipv4(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_ipv4_hidden(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_ipv4_format(tree, id, tvb, start, length, value,
            format, ...);
 
        proto_item *
-       proto_tree_add_ipv6_format(tree, id, start, length, value_ptr,
+       proto_tree_add_ipv6(tree, id, tvb, start, length, value_ptr);
+
+       proto_item *
+       proto_tree_add_ipv6_hidden(tree, id, tvb, start, length, value_ptr);
+
+       proto_item *
+       proto_tree_add_ipv6_format(tree, id, tvb, start, length, value_ptr,
            format, ...);
 
        proto_item *
-       proto_tree_add_ether_format(tree, id, start, length, value_ptr,
+       proto_tree_add_ether(tree, id, tvb, start, length, value_ptr);
+
+       proto_item *
+       proto_tree_add_ether_hidden(tree, id, tvb, start, length, value_ptr);
+
+       proto_item *
+       proto_tree_add_ether_format(tree, id, tvb, start, length, value_ptr,
            format, ...);
 
        proto_item *
-       proto_tree_add_string_format(tree, id, start, length, value_ptr,
+       proto_tree_add_string(tree, id, tvb, start, length, value_ptr);
+
+       proto_item *
+       proto_tree_add_string_hidden(tree, id, tvb, start, length, value_ptr);
+
+       proto_item *
+       proto_tree_add_string_format(tree, id, tvb, start, length, value_ptr,
            format, ...);
 
        proto_item *
-       proto_tree_add_boolean_format(tree, id, start, length, value,
+       proto_tree_add_boolean(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_boolean_hidden(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_boolean_format(tree, id, tvb, start, length, value,
            format, ...);
 
        proto_item *
-       proto_tree_add_uint_format(tree, id, start, length, value,
+       proto_tree_add_float(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_float_hidden(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_float_format(tree, id, tvb, start, length, value,
+           format, ...);
+
+       proto_item *
+       proto_tree_add_double(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_double_hidden(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_double_format(tree, id, tvb, start, length, value,
+           format, ...);
+
+       proto_item *
+       proto_tree_add_uint(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_uint_hidden(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_uint_format(tree, id, tvb, start, length, value,
+           format, ...);
+
+       proto_item *
+       proto_tree_add_uint64(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_uint64_format(tree, id, tvb, start, length, value,
+           format, ...);
+
+       proto_item *
+       proto_tree_add_int(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_int_hidden(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_int_format(tree, id, tvb, start, length, value,
+           format, ...);
+
+       proto_item *
+       proto_tree_add_int64(tree, id, tvb, start, length, value);
+
+       proto_item *
+       proto_tree_add_int64_format(tree, id, tvb, start, length, value,
            format, ...);
 
        proto_item*
-       proto_tree_add_text(tree, start, length, format, ...);
+       proto_tree_add_text(tree, tvb, start, length, format, ...);
+
+       proto_item*
+       proto_tree_add_text_valist(tree, tvb, start, length, format, ap);
 
 The 'tree' argument is the tree to which the item is to be added.  The
-'start' argument is the offset from the beginning of the frame (not the
-offset from the beginning of the part of the packet belonging to this
-protocol, but the offset from the beginning of the frame as a whole) of
-the item being added, and the 'length' argument is the length, in bytes,
-of the item.
+'tvb' argument is the tvbuff from which the item's value is being
+extracted; the 'start' argument is the offset from the beginning of that
+tvbuff of the item being added, and the 'length' argument is the length,
+in bytes, of the item.
 
 The length of some items cannot be determined until the item has been
 dissected; to add such an item, add it with a length of -1, and, when the
@@ -992,16 +1543,18 @@ proto_tree_add_item()
 ---------------------
 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 can 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:
+proto_register_*() function) and a value.  The value will be fetched
+from the tvbuff by proto_tree_add_item(), based on the type of the field
+and, for integral and Boolean fields, the byte order of the value; the
+byte order is specified by the 'little_endian' argument, which is TRUE
+if the value is little-endian and FALSE if it is big-endian.
+
+Now that definitions of fields have detailed information about bitfield
+fields, you can 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"
@@ -1015,17 +1568,14 @@ against the parent field, the first byte of the TH.
 
 The code to add the FID to the tree would be;
 
-       guint8 th_0 = tvb_get_guint8(tvb, offset);
-       proto_tree_add_item(bf_tree, hf_sna_th_fid, offset, 1, th_0);
+       proto_tree_add_item(bf_tree, hf_sna_th_fid, tvb, offset, 1, TRUE);
 
-Note: we do not do *any* manipulation of th_0 in order to get 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.)
+The definition of the field 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 create 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[] = {
@@ -1058,7 +1608,7 @@ 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
+use proto_tree_add_none_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
@@ -1067,13 +1617,13 @@ programmer might code this.
        char *rif;
        rif = create_rif_string(...);
 
-       proto_tree_add_item_format(tree, hf_tr_rif_label,..., "RIF: %s", rif);
+       proto_tree_add_none_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]);
+               proto_tree_add_item_hidden(tree, hf_tr_rif_ring, ..., FALSE);
        }
        for(i = 0; i < num_rings - 1; i++) {
-               proto_tree_add_item_hidden(tree, hf_tr_rif_ring, ..., bridge[i]);
+               proto_tree_add_item_hidden(tree, hf_tr_rif_bridge, ..., FALSE);
        }
 
 The logical tree has these items:
@@ -1103,6 +1653,107 @@ arguments are a "printf"-style format and any arguments for that format.
 The caller must include the name of the protocol in the format; it is
 not added automatically as in proto_tree_add_item().
 
+proto_tree_add_none_format()
+----------------------------
+proto_tree_add_none_format is used to add an item of type FT_NONE.
+The caller must include the name of the field in the format; it is
+not added automatically as in proto_tree_add_item().
+
+proto_tree_add_bytes()
+proto_tree_add_time()
+proto_tree_add_ipxnet()
+proto_tree_add_ipv4()
+proto_tree_add_ipv6()
+proto_tree_add_ether()
+proto_tree_add_string()
+proto_tree_add_boolean()
+proto_tree_add_float()
+proto_tree_add_double()
+proto_tree_add_uint()
+proto_tree_add_uint64()
+proto_tree_add_int()
+proto_tree_add_int64()
+----------------------------
+These routines are used to add items to the protocol tree if either:
+
+       the value of the item to be added isn't just extracted from the
+       packet data, but is computed from data in the packet;
+
+       the value was fetched into a variable.
+
+The 'value' argument has the value to be added to the tree.
+
+NOTE: in all cases where the 'value' argument is a pointer, a copy is
+made of the object pointed to; if you have dynamically allocated a
+buffer for the object, that buffer will not be freed when the protocol
+tree is freed - you must free the buffer yourself when you don't need it
+any more.
+
+For proto_tree_add_bytes(), the 'value_ptr' argument is a pointer to a
+sequence of bytes.
+
+For proto_tree_add_time(), the 'value_ptr' argument is a pointer to an
+"nstime_t", which is a structure containing the time to be added; it has
+'secs' and 'nsecs' members, giving the integral part and the fractional
+part of a time in units of seconds, with 'nsecs' being the number of
+nanoseconds.  For absolute times, "secs" is a UNIX-style seconds since
+January 1, 1970, 00:00:00 GMT value.
+
+For proto_tree_add_ipxnet(), the 'value' argument is a 32-bit IPX
+network address.
+
+For proto_tree_add_ipv4(), the 'value' argument is a 32-bit IPv4
+address, in network byte order.
+
+For proto_tree_add_ipv6(), the 'value_ptr' argument is a pointer to a
+128-bit IPv6 address.
+
+For proto_tree_add_ether(), the 'value_ptr' argument is a pointer to a
+48-bit MAC address.
+
+For proto_tree_add_string(), the 'value_ptr' argument is a pointer to a
+text string.
+
+For proto_tree_add_boolean(), the 'value' argument is a 32-bit integer;
+zero means "false", and non-zero means "true".
+
+For proto_tree_add_float(), the 'value' argument is a 'float' in the
+host's floating-point format.
+
+For proto_tree_add_double(), the 'value' argument is a 'double' in the
+host's floating-point format.
+
+For proto_tree_add_uint(), the 'value' argument is a 32-bit unsigned
+integer value, in host byte order.  (This routine cannot be used to add
+64-bit integers.)
+
+For proto_tree_add_uint64(), the 'value' argument is a 64-bit unsigned
+integer value, in host byte order.
+
+For proto_tree_add_int(), the 'value' argument is a 32-bit signed
+integer value, in host byte order.  (This routine cannot be used to add
+64-bit integers.)
+
+For proto_tree_add_int64(), the 'value' argument is a 64-bit signed
+integer value, in host byte order.
+
+proto_tree_add_bytes_hidden()
+proto_tree_add_time_hidden()
+proto_tree_add_ipxnet_hidden()
+proto_tree_add_ipv4_hidden()
+proto_tree_add_ipv6_hidden()
+proto_tree_add_ether_hidden()
+proto_tree_add_string_hidden()
+proto_tree_add_boolean_hidden()
+proto_tree_add_float_hidden()
+proto_tree_add_double_hidden()
+proto_tree_add_uint_hidden()
+proto_tree_add_int_hidden()
+----------------------------
+These routines add fields and values to a tree, but don't show them in
+the GUI tree.  They are used for the same reason that
+proto_tree_add_item() is used.
+
 proto_tree_add_bytes_format()
 proto_tree_add_time_format()
 proto_tree_add_ipxnet_format()
@@ -1111,29 +1762,20 @@ proto_tree_add_ipv6_format()
 proto_tree_add_ether_format()
 proto_tree_add_string_format()
 proto_tree_add_boolean_format()
+proto_tree_add_float_format()
+proto_tree_add_double_format()
 proto_tree_add_uint_format()
+proto_tree_add_uint64_format()
+proto_tree_add_int_format()
+proto_tree_add_int64_format()
 ----------------------------
-
-The other "proto_tree_add_XXX_format" routines are used to add items to
-the protocol tree when the dissector routines wants complete control
-over how the field and value will be represented on the GUI tree.
-
-For "proto_tree_add_time_format", the "value_ptr" argument is a pointer
-to an "nstime_t", which is a structure containing the time to be added;
-it has "secs" and "nsecs" members, giving the integral part and the
-fractional part of a time in seconds, with "nsecs" being the number of
-nanoseconds.  For absolute times, "secs" is a UNIX-style seconds since
-January 1, 1970, 00:00:00 GMT value.
-
-For the other functions that take a "value_ptr" argument, that argument
-is a pointer to the first byte of the value to be added.
-
-For the other functions, the "value" argument is a 32-bit integral value
-to be added.
-
-The rest of the arguments are a "printf"-style format and any arguments
-for that format.  The caller must include the name of the field in the
-format; it is not added automatically as in proto_tree_add_item().
+These routines are used to add items to the protocol tree when the
+dissector routines wants complete control over how the field and value
+will be represented on the GUI tree.  The argument giving the value is
+the same as the corresponding proto_tree_add_XXX() function; the rest of
+the arguments are a "printf"-style format and any arguments for that
+format.  The caller must include the name of the field in the format; it
+is not added automatically as in the proto_tree_add_XXX() functions.
 
 proto_tree_add_text()
 ---------------------
@@ -1155,10 +1797,10 @@ of the items in the subtree have been dissected.  To do this, use
 'proto_item_set_text()' or 'proto_item_append_text()':
 
        void
-       proto_tree_set_text(proto_item *ti, ...);
+       proto_item_set_text(proto_item *ti, ...);
 
        void
-       proto_tree_append_text(proto_item *ti, ...);
+       proto_item_append_text(proto_item *ti, ...);
 
 'proto_item_set_text()' takes as an argument the value returned by
 'proto_tree_add_text()', a 'printf'-style format string, and a set of
@@ -1171,7 +1813,7 @@ the item the result of applying the arguments to the format string.
 
 For example, early in the dissection, one might do:
 
-       ti = proto_tree_add_text(tree, offset, length, <label>);
+       ti = proto_tree_add_text(tree, tvb, offset, length, <label>);
 
 and later do
 
@@ -1187,6 +1829,13 @@ available.  Thus, one should create the item with text that is as
 meaningful as possible, and set it or append additional information to
 it as the values needed to supply that information is extracted.
 
+proto_tree_add_text_valist()
+---------------------
+This is like proto_tree_add_text(), but takes, as the last argument, a
+'va_list'; it is used to allow routines that take a printf-like
+variable-length list of arguments to add a text item to the protocol
+tree.
+
 1.7 Utility routines
 
 1.7.1 match_strval and val_to_str
@@ -1203,7 +1852,19 @@ to generate a COL_INFO line for a frame.
 
 It will look up the value 'val' in the 'value_string' table pointed to
 by 'vs', and return either the corresponding string, or NULL if the
-value could not be found in the table.
+value could not be found in the table.  Note that, unless 'val' is
+guaranteed to be a value in the 'value_string' table ("guaranteed" as in
+"the code has already checked that it's one of those values" or "the
+table handles all possible values of the size of 'val'", not "the
+protocol spec says it has to be" - protocol specs do not prevent invalid
+packets from being put onto a network or into a purported packet capture
+file), you must check whether 'match_strval()' returns NULL, and arrange
+that its return value not be dereferenced if it's NULL.  In particular,
+don't use it in a call to generate a COL_INFO line for a frame such as
+
+       col_add_fstr(COL_INFO, ", %s", match_strval(val, table));
+
+unless is it certain that 'val' is in 'table'.
 
 'val_to_str()' can be used to generate a string for values not found in
 the table:
@@ -1282,25 +1943,20 @@ dissect_ipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        dissector_next( next_tvb, pinfo, tree);
 
 
-1.9 Editing Makefile.am and Makefile.nmake to add your dissector.
+1.9 Editing Makefile.common to add your dissector.
 
 To arrange that your dissector will be built as part of Ethereal, you
-must add the name of the source file for your dissector, and the header
-file that declares your main dissector routine, to the
-'DISSECTOR_SOURCES' macro in the 'Makefile.am' file in the top-level
-directory, and must add the name the object file for the dissector will
-have when built on Windows - if your dissector source file is
-'packet-PROTOABBREV.c', the object file for it will be
-'packet-PROTOABBREV.obj' - to the 'DISSECTOR_OBJECTS' macro in the
-'Makefile.nmake' file in the top-level directory.  (Note that this is
-for modern versions of UNIX, so there is no 14-character limitation on
-file names, and for modern versions of Windows, so there is no
-8.3-character limitation on file names.)
-
-Please remember to update both files; it may not be necessary to do so
-in order for you to build Ethereal on your machine, but both changes
-will need to be checked in to the Ethereal source code, to allow it to
-build on all platforms.
+must add the name of the source file for your dissector to the
+'DISSECTOR_SRC' macro in the 'Makefile.common' file in the 'epan/dissectors'
+directory.  (Note that this is for modern versions of UNIX, so there
+is no 14-character limitation on file names, and for modern versions of
+Windows, so there is no 8.3-character limitation on file names.)
+
+If your dissector also has its own header file or files, you must add
+them to the 'DISSECTOR_INCLUDES' macro in the 'Makefile.common' file in
+the 'epan/dissectors' directory, so that it's included when release source
+tarballs are built (otherwise, the source in the release tarballs won't
+compile).
 
 1.10 Using the CVS source code tree.
 
@@ -1310,7 +1966,7 @@ build on all platforms.
 
 2.1 ?? 
 
-2.2 Following "conversations."
+2.2 Following "conversations".
 
 In ethereal a conversation is defined as a series of data packet between two
 address:port combinations.  A conversation is not sensitive to the direction of
@@ -1435,14 +2091,14 @@ conversation.  Using the protocol number allows several dissectors to
 associate data with a given conversation.
 
 
-2.2.5 The conversation_get_protocol_data function.
+2.2.5 The conversation_get_proto_data function.
 
 After you have located a conversation with find_conversation, you can use
 this function to retrieve any data associated with it.
 
-The conversation_get_protocol_data prototype:
+The conversation_get_proto_data prototype:
 
-       void *conversation_get_protocol_data(conversation_t *conv, int proto);
+       void *conversation_get_proto_data(conversation_t *conv, int proto);
 
 Where:
        conversation_t *conv = the conversation in question
@@ -1530,7 +2186,7 @@ else {
 
     conversation_new( &pinfo->src, &pinfo->dst, pinfo->ptype,
            pinfo->srcport, pinfo->destport, 0);
-    conversation_add_proto_data(conversation, my_proto, (void *) data_ptr;
+    conversation_add_proto_data(conversation, my_proto, (void *) data_ptr);
 }
 
 /* at this point the conversation data is ready */
@@ -1538,7 +2194,7 @@ else {
 
 /******************* in the dissector init routine *******************/
 
-#define proto_hash_init_count 20
+#define my_init_count 20
 
 static void
 my_dissector_init( void){
@@ -1753,7 +2409,7 @@ Where:
        proto_data - pointer to the dissector data.
 
 
-2.5 User Preferences
+2.6 User Preferences
 
 If the dissector has user options, there is support for adding these preferences
 to a configuration dialog.
@@ -1780,22 +2436,42 @@ Then you can register the fields that can be configured by the user with these r
        /* Register a preference with an enumerated value. */
        void prefs_register_enum_preference(module_t *module, const char *name,
            const char *title, const char *description, gint *var,
-           const enum_val *enumvals, gboolean radio_buttons)
+           const enum_val_t *enumvals, gboolean radio_buttons)
 
        /* Register a preference with a character-string value. */
        void prefs_register_string_preference(module_t *module, const char *name,
            const char *title, const char *description, char **var)
 
 Where: module - Returned by the prefs_register_protocol routine
-        name   - Appended to the module name to identify the field in the preference file
-        title  - Field title in the preferences dialog
+        name     - This is appended to the name of the protocol, with a
+                   "." between them, to construct a name that identifies
+                   the field in the preference file; the name itself
+                   should not include the protocol name, as the name in
+                   the preference file will already have it
+        title    - Field title in the preferences dialog
         description - Comments added to the preference file above the 
-                       preference value
+                      preference value
         var      - pointer to the storage location that is updated when the
                    field is changed in the preference dialog box
-        enumvals - an array of enum_val structures.  This must be NULL terminated
-        radio_buttons - Is the enumvals a list of radio buttons?
-
+        enumvals - an array of enum_val_t structures.  This must be
+                   NULL-terminated; the members of that structure are:
+
+                       a short name, to be used with the "-o" flag - it
+                       should not contain spaces or upper-case letters,
+                       so that it's easier to put in a command line;
+
+                       a description, which is used in the GUI (and
+                       which, for compatibility reasons, is currently
+                       what's written to the preferences file) - it can
+                       contain spaces, capital letters, punctuation,
+                       etc.;
+
+                       the numerical value corresponding to that name
+                       and description
+        radio_buttons - TRUE if the field is to be displayed in the
+                        preferences dialog as a set of radio buttons,
+                        FALSE if it is to be displayed as an option
+                        menu
 
 An example from packet-beep.c -
        
@@ -1819,6 +2495,98 @@ An example from packet-beep.c -
                                 "terminator, and not just CR or LF",
                                 &global_beep_strict_term);
 
+This will create preferences "beep.tcp.port" and
+"beep.strict_header_terminator", the first of which is an unsigned
+integer and the second of which is a Boolean.
+
+2.7 Reassembly/desegmentation for protocols running atop TCP
+
+There are two main ways of reassembling PDUs spanning across multiple
+TCP segmentss.  The first one is simpler, but assumes you are running
+atop of TCP when this occurs (but your dissector might run atop of UDP,
+too, for example), and that your PDUs consist of a fixed amount of data
+that includes enough information to determine the PDU length, possibly
+followed by additional data.  The second one is more generic but
+requires more code and is less efficient.
+
+For the first method, you register two different dissection methods, on
+for the TCP case, and one for the other cases.  It is a good idea to
+have a dissect_PROTO_common function which will parse the generic
+content that you can find in all PDUs which is called from
+dissect_PROTO_tcp when the reassembly is complete and from
+dissect_PROTO_udp (or dissect_PROTO_other).
+
+To register the distinct dissector functions, consider the following
+example, stolen from packet-dns.c:
+
+       dissector_handle_t dns_udp_handle;
+       dissector_handle_t dns_tcp_handle;
+       dissector_handle_t mdns_udp_handle;
+
+       dns_udp_handle = create_dissector_handle(dissect_dns_udp,
+           proto_dns);
+       dns_tcp_handle = create_dissector_handle(dissect_dns_tcp,
+           proto_dns);
+       mdns_udp_handle = create_dissector_handle(dissect_mdns_udp,
+           proto_dns);
+
+       dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
+       dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);
+       dissector_add("udp.port", UDP_PORT_MDNS, mdns_udp_handle);
+       dissector_add("tcp.port", TCP_PORT_MDNS, dns_tcp_handle);
+
+The dissect_dns_udp function does very little work and calls
+dissect_dns_common, while dissect_dns_tcp calls tcp_dissect_pdus with a
+reference to a callback which will be called with reassembled data:
+
+       static void
+       dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+       {
+               tcp_dissect_pdus(tvb, pinfo, tree, dns_desegment, 2,
+                   get_dns_pdu_len, dissect_dns_tcp_pdu);
+       }
+
+(The dissect_dns_tcp_pdu function acts similarly to dissect_dns_udp.) 
+The arguments to tcp_dissect_pdus are:
+
+       the tvbuff pointer, packet_info pointer, and proto_tree pointer
+       passed to the dissector;
+
+       a gboolean flag indicating whether desegmentation is enabled for
+       your protocol;
+
+       the number of bytes of PDU data required to determine the length
+       of the PDU;
+
+       a routine that takes as arguments a tvbuff pointer and an offset
+       value representing the offset into the tvbuff at which a PDU
+       begins and should return - *without* throwing an exception (it
+       is guaranteed that the number of bytes specified by the previous
+       argument to tcp_dissect_pdus is available, but more data might
+       not be available, so don't refer to any data past that) - the
+       total length of the PDU, in bytes;
+
+       a routine that's passed a tvbuff pointer, packet_info pointer,
+       and proto_tree pointer, with the tvbuff containing a
+       possibly-reassembled PDU, and that should dissect that PDU.
+
+The second method is to return a modified pinfo structure when
+dissect_PROTO is called.  In this case, you have to check if you have
+collected enough bytes: if you have enough, you parse the PDU, and if
+don't have enough bytes, you return from the dissector supplying
+information to the caller on how many bytes you need to proceed.  This
+is done by indicating the offset where you would like to start again and
+the number of bytes that you need in pinfo->desegment_*:
+
+       if (i_miss_five_bytes) {
+               pinfo->desegment_offset = offset;
+               pinfo->desegment_len = 5;
+       }
+
+You can repeat this procedure until you've got enough bytes; for
+example, you can request one byte more until you've got the byte you're
+searching for if the data to be dissected consists of a sequence of
+bytes ending with a particular byte value.
 
 3. Plugins
 
@@ -1827,7 +2595,59 @@ a dissector.
 
 4.0 Extending Wiretap.
 
-5.0 Adding new capabilities.
+5.0 How the Display Filter Engine works
+
+code:
+epan/dfilter/* - the display filter engine, including
+               scanner, parser, syntax-tree semantics checker, DFVM bytecode
+               generator, and DFVM engine.
+epan/ftypes/* - the definitions of the various FT_* field types.
+epan/proto.c   - proto_tree-related routines
+
+5.1 Parsing text
+
+The scanner/parser pair read the string representing the display filter
+and convert it into a very simple syntax tree.  The syntax tree is very
+simple in that it is possible that many of the nodes contain unparsed
+chunks of text from the display filter.
+
+5.1 Enhancing the syntax tree.
+
+The semantics of the simple syntax tree are checked to make sure that
+the fields that are being compared are being compared to appropriate
+values.  For example, if a field is an integer, it can't be compared to
+a string, unless a value_string has been defined for that field.
+
+During the process of checking the semantics, the simple syntax tree is
+fleshed out and no longer contains nodes with unparsed information.  The
+syntax tree is no longer in its simple form, but in its complete form.
+
+5.2 Converting to DFVM bytecode
+
+The syntax tree is analyzed to create a sequence of bytecodes in the
+"DFVM" language.  "DFVM" stands for Display Filter Virtual Machine.  The
+DFVM is similar in spirit, but not in definition, to the BPF VM that
+libpcap uses to analyze packets.
+
+A virtual bytecode is created and used so that the actual process of
+filtering packets will be fast.  That is, it should be faster to process
+a list of VM bytecodes than to attempt to filter packets directly from
+the syntax tree.  (heh...  no measurement has been made to support this
+supposition)
+
+5.3 Filtering
+
+Once the DFVM bytecode has been produced, it's a simple matter of
+running the DFVM engine against the proto_tree from the packet
+dissection, using the DFVM bytecodes as instructions.  If the DFVM
+bytecode is known before packet dissection occurs, the
+proto_tree-related code can be "primed" to store away pointers to
+field_info structures that are interesting to the display filter.  This
+makes lookup of those field_info structures during the filtering process
+faster.
+
+
+6.0 Adding new capabilities.
 
 
 
@@ -1836,5 +2656,6 @@ James Coe <jammer@cin.net>
 Gilbert Ramirez <gram@alumni.rice.edu>
 Jeff Foster <jfoste@woodward.com>
 Olivier Abad <oabad@cybercable.fr>
-Laurent Deniel <deniel@worldnet.fr>
+Laurent Deniel <laurent.deniel@free.fr>
 Gerald Combs <gerald@ethereal.com>
+Guy Harris <guy@alum.mit.edu>