From Josip Medved:
[obnox/wireshark/wip.git] / doc / README.tapping
index b53120b8505fb05e6aa4bc4e1dd69f8ea1e7c27e..5584a6c4fda6b8524ae27a3f187539aa4256e23a 100644 (file)
@@ -1,14 +1,18 @@
-$Id: README.tapping,v 1.4 2002/11/28 20:29:46 guy Exp $
+$Id$
 
-The TAP system in ethereal is a powerful and flexible mechanism to get event 
+The TAP system in Wireshark is a powerful and flexible mechanism to get event
 driven notification on packets matching certain protocols and/or filters.
-In order to use the tapping system, very little knowledge of ethereal
+In order to use the tapping system, very little knowledge of Wireshark
 internals are required.
 
-As examples on how to use the tap system see the implementation of 
-tap-rpcstat.c          (tethereal version)
-gtk2/gtk2-rpcstat.c    (gtk2-ethereal version)
+As examples on how to use the tap system see the implementation of
+tap-rpcstat.c          (tshark version)
+gtk/rpc_stat.c         (gtk-wireshark version)
 
+If all you need is to keep some counters, there's the stats_tree API,
+which offers a simple way to make a GUI and tshark tap-listener; see
+README.stats_tree.  However, keep reading, as you'll need much of what's
+in this document.
 
 The tap system consists of two parts:
 1, code in the actual dissectors to allow tapping data from that particular
@@ -26,12 +30,13 @@ TAP
 First you must decide which protocol you are interested in writing a tap
 application for and check if that protocol has already got a tap installed
 in it.
-If it already has a tap device installed then you dont have to do anything.
-If not, then you have to add a tap but dont worry, this is extremely easy to 
+If it already has a tap device installed then you don't have to do anything.
+If not, then you have to add a tap but don't worry, this is extremely easy to
 do and is done in four easy steps;
 (see packet-rpc.c and search for tap for an example)
 
-1, We need tap.h so just add '#include "tap.h"' to the includes.
+1, We need tap.h so just add '#include "tap.h"' (preceded by packet.h) to
+the includes.
 
 2, We need a tap handler so just add 'static int <protocol>_tap = -1;'
 
@@ -41,11 +46,11 @@ do and is done in four easy steps;
 4, In the actual dissector for that protocol, after any child dissectors
 have returned, just add 'tap_queue_packet(<protocol>_tap, pinfo, <pointer>);'
 
-<pointer> is used if the tap has any special additional data to provide to
-the tap listeners. What this points to is dependant on the protocol that
-is tapped, or if there are no useful extra data to provide just specify NULL.
-For packet-rpc.c what we specify there is the persistant structure 'rpc_call'
-which contains lots of useful information the rpc layer that a listener might
+<pointer> is used if the tap has any special additional data to provide to the
+tap listeners. What this points to is dependent on the protocol that is tapped,
+or if there are no useful extra data to provide just specify NULL.  For
+packet-rpc.c what we specify there is the persistent structure 'rpc_call' which
+contains lots of useful information from the rpc layer that a listener might
 need.
 
 
@@ -59,10 +64,11 @@ Only 3 callbacks and two functions.
 
 The two functions to start or stop tapping are
 
-register_tap_listener(char *tapname, void *tapdata, char *fstring,
+register_tap_listener(const char *tapname, void *tapdata, const char *fstring,
+       guint flags,
        void (*reset)(void *tapdata),
-       int  (*packet)(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, void *<pointer>),
-       void (*draw)(void *tapdata),
+        gboolean (*packet)(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *data),
+       void (*draw)(void *tapdata));
 
 remove_tap_listener(void *tapdata);
 
@@ -73,11 +79,11 @@ This function is used to deregister and stop a tap listener.
 register_tap_listener() is used to register an instance of a tap application
 to the tap system.
 
-*tapname 
+*tapname
 is the name of the tap we want to listen to. I.e. the name used in
 step 3 above.
 
-*tapdata 
+*tapdata
 is the instance identifier. The tap system uses the value of this
 pointer to distinguish between different instances of a tap.
 Just make sure that it is unique by letting it be the pointer to a struct
@@ -86,8 +92,8 @@ instances, just put ALL state variables inside a struct allocated by
 g_malloc() and use that pointer.
 (tap-rpcstat.c use this technique to allow multiple simultaneous instances)
 
-*fstring 
-is a pointer to a filter string. 
+*fstring
+is a pointer to a filter string.
 If this is NULL, then the tap system will provide ALL packets passing the
 tapped protocol to your listener.
 If you specify a filter string here the tap system will first try
@@ -96,35 +102,58 @@ matched the filter to your listener.
 The syntax for the filter string is identical to normal display filters.
 
 NOTE: Specifying filter strings will have a significant performance impact
-on your application and ethereal. If possible it is MUCH better to take
+on your application and Wireshark. If possible it is MUCH better to take
 unfiltered data and just filter it yourself in the packet-callback than
 to specify a filter string.
 ONLY use a filter string if no other option exist.
 
+flags
+is a set of flags for the tap listener.  The flags that can be set are:
+
+    TL_REQUIRES_PROTO_TREE
+
+       set if your tap listener "packet" routine requires a protocol
+       tree to be built.  It will require a protocol tree to be
+       built if either
+
+               1) it looks at the protocol tree in edt->tree
+
+       or
+
+               2) the tap-specific data passed to it is constructed only if
+                  the protocol tree is being built.
+
+    TL_REQUIRES_COLUMNS
+
+       set if your tap listener "packet" routine requires the column
+       strings to be constructed.
+
+    If no flags are needed, use TL_REQUIRES_NOTHING.
+
 void (*reset)(void *tapdata)
-This callback is called whenever ethereal wants to inform your
+This callback is called whenever Wireshark wants to inform your
 listener that it is about to start [re]reading a capture file or a new capture
 from an interface and that your application should reset any state it has
 in the *tapdata instance.
 
-int (*packet)(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, void *data)
+gboolean (*packet)(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *data)
 This callback is used whenever a new packet has arrived at the tap and that
 it has passed the filter (if there were a filter).
 The *data structure type is specific to each tap.
-This function returns an int and it should return 
1, if the data in the packet aused state to be updated
-    (asnd thus a redraw of the window would later be required)
0, if we dont need to redraw the window.
+This function returns an gboolean and it should return
TRUE, if the data in the packet caused state to be updated
+       (and thus a redraw of the window would later be required)
FALSE, if we don't need to redraw the window.
 NOTE: that (*packet) should be as fast and efficient as possible. Use this
-function ONLY to store data for later and do the cpu-intensive processing
+function ONLY to store data for later and do the CPU-intensive processing
 or GUI updates down in (*draw) instead.
 
+
 void (*draw)(void *tapdata)
-This callback is used when ethereal wants your application to redraw its
+This callback is used when Wireshark wants your application to redraw its
 output. It will usually not be called unless your application has received
 new data through the (*packet) callback.
-On some ports of ethereal (gtk2) (*draw) will be called asynchronously 
+On some ports of Wireshark (gtk2) (*draw) will be called asynchronously
 from a separate thread up to once every 2-3 seconds.
 On other ports it might only be called once when the capture is finished
 or the file has been [re]read completely.
@@ -136,21 +165,57 @@ So, create three callbacks:
 2, packet  to update these state variables.
 3, draw    to take these state variables and draw them on the screen.
 
-then just make ethereal call register_tap_listener() when you want to tap
+then just make Wireshark call register_tap_listener() when you want to tap
 and call remove_tap_listener() when you are finished.
 
 
+WHEN DO TAP LISTENERS GET CALLED?
+===================================
+Tap listeners are only called when Wireshark reads a new capture for
+the first time or whenever Wireshark needs to rescan/redissect
+the capture.
+Redissection occurs when you apply a new display filter or if you
+change and Save/Apply a preference setting that might affect how
+packets are dissected.
+After each individual packet has been completely dissected and all
+dissectors have returned, all the tap listeners that have been flagged
+to receive tap data during the dissection of the frame will be called in
+sequence.
+The order in which the tap listeners will be called is not defined.
+Not until all tap listeners for the frame has been called and returned
+will Wireshark continue to dissect the next packet.
+This is why it is important to make the *_packet() callbacks execute as
+quickly as possible, else we create an extra delay until the next packet
+is dissected.
+
+Keep in mind though: for some protocols, such as IP, the protocol can
+appear multiple times in different layers inside the same packet.
+For example, IP encapsulated over IP which will call the ip dissector
+twice for the same packet.
+IF the tap is going to return private data using the last parameter to
+tap_queue_packet() and IF the protocol can appear multiple times inside the
+same packet, you will have to make sure that each instance of
+tap_queue_packet() is using its own instance of private struct variable
+so they don't overwrite each other.
+
+See packet-ip.c which has a simple solution to the problem. It creates
+a unique instance of the IP header using ep_alloc().
+Previous versions used a static struct of 4 instances of the IP header
+struct and cycled through them each time the dissector was called. (4
+was just a number taken out of the blue but it should be enough for most
+cases.) This would fail if there were more than 4 IP headers in the same
+packet, but that was unlikely.
 
 
 TIPS
 ====
 Of course, there is nothing that forces you to make (*draw) draw stuff
-on the screen. 
+on the screen.
 You can hand register_tap_listener() NULL for both (*draw) and (*reset)
 (well also for (*packet) but that would be a very boring extension).
 
 Perhaps you want an extension that will execute a certain command
-everytime it sees a certain packet?
+every time it sees a certain packet?
 Well, try this :
        int packet(void *tapdata,...) {
                ...
@@ -161,8 +226,8 @@ Well, try this :
        register_tap_listener("tcp", struct, "tcp.port==57", NULL, packet, NULL);
 
        Let struct contain an email address?
-       Then you have something simple that will make ethereal send an email
-       out automagically for each and every time it dissects 
+       Then you have something simple that will make Wireshark send an email
+       out automagically for each and every time it dissects
        a packet containing TCP traffic to port 57.
        Please put in some rate limitation if you do this.
 
@@ -172,7 +237,7 @@ Well, try this :
 
 
 See tap-rpcstat.c for an example
-See tap.c as well. It contains lots of comments and descriptions on the tap 
+See tap.c as well. It contains lots of comments and descriptions on the tap
 system.