PLUGIN BASICS ============= A plugin set is a set of one or more plugin objects derived from the KNDPlugin class, defined in "knd_plugin.h". Plugins can be divided into two groups, configuration and display plugins. In principal, a configuration plugin is a dialog into which the user can enter configuration information, while a display plugin is used to display results. However, the only real distinction is that a configuration plugin can be accesed at any time, while a display plugin is only available when a sniffer is executing. A simple case is a plugin set that consists of a single display instance of KNDPlugin for which there is no configuration information; the included "summary" and "endtoend" plugins are examples of these. A second simple case would be a single configuration instance of KNDPlugin which also displays results. The included "demo" plugin comprises one configuration and one display instance of KNDPlugin. A plugin derived from KNDPlugin should implement some of the following virtual methods, of which the first two, "getLabel" and "isConfig" must be implemented (they are defined kn "knd_plugin.h" to be pure virtual). Most of these appear as examples in the "demo" plugin. PLUGIN METHODS ============== const char *getLabel () ----------------------- This method should return the text which is to appear in the tab bar. Note that this is distinct to the second argument to the KNDPlugin object, which is a distinct name used to identify the tab under which the plug appears to the parent KTabCrl object. bool isConfig () ---------------- Configuration plugins should return true, display plugins should return false. As noted above, the tabs for configuration plugins are always enabled; those for display plugins are only enabled once the sniffer has been started. void clickSet () ---------------- Called when the "Set" button is clicked. Typically, this is used to copy configuration information for fields in configuration plugins. To be consistent with the main sniffer configuration object, values in configuration fields should be copied when "clickSet" is called, and the copied values subsequently used in "setOptions" calls. void clickReset () ------------------ Called when the "Reset" button is clicked. This should restore configuration field values to those values copied the last time that "clickSet" was invoked. void clickClear () ------------------ Called when the "Clear" button is clicked. Configuration fields (but not any values copied on "clickSet") should be cleared to their default values. void *setOptions (void *) ------------------- Configuration information is passed between configuration and display plugins using this method. This method is called on each plugin in the plugin set in turn; for the first plugin it is called with a null argument; each subsequent plugin is called with the result of the call to the previous plugin. Generally, he first plugin should return a pointer at a configuration structure (into which it places configuration information); subsequent plugins should add or extract information as appropriate, and return the argument as the result. void setOnView (bool) --------------------- This method is called when the plugin becomes visible (with the argument set to true), or is hidden (with the arguement set to false). It can be used by plugins which may consume significant amounts of CPU time in updating the display, so that update can be skipped when they are hidden. void execute (bool) ------------------- This method is called with a true argument when the sniffer starts executing, and a false argument when the sniffer stops executing. The plugin object should only receive "addPacket", "timerTick" and "freeze" calls while the sniffer is executing. void freeze (bool) ------------------ This method is called when the used freezes or unfreezes the display; a true argument indicates freezing. Generally, a display plugin should continue to accumulate network information while it is froze, but should not update the display. void timerTick (long) --------------------- This method is called once per second. The argument is the system time in seconds. Note that ticks are never missed, and are always interleaved correctly with captured packets. void writeConfig (KConfig *) ---------------------------- This method is called when the program configuration is to be saved. The plugin should write whatever configuration information is appropriate. Note that the KConfig object will have been set to the correct group, and the plugin should not call "setGroup" on the KConfig configuration object. void addPacket (PktInfo *) -------------------------- This method is called for each captured packet that passes the sniffer filter and trigger settings. The PktInfo structure is defined in "pktinfo.h". If the plugin needs to ensure that the PktInfo pointer remains valid after returning from "addPacket", it can call the "usePktInfo" routine with the packet pointer as its argument. However, the plugin must at some later time (and certainly before exiting from its destructor) call "freePktInfo", or memory leakage will occur. PLUGIN INTERFACE ================ A plugin set must be built as a single dyncamically linked library file, and must export the routine "getPlugin". Note that this must be defined as 'extern "C"' in order to prevent name mangling. When a plugin is loaded, this routine is called with the appropriate KNDView * and KNDConfig * arguments; it should return a pointer at a malloc'ed PluginSet structure (see "knd_plugin.h"). This should contain the number of plugins in the plugin set, plus pointers at each KNDPlugin object. In addition (as of V0.6) it contains a pointer at the plugin name. This _must_ match the name under which it is installed: ie., "/opt/kde/share/apps/ksnuffle/plugins/aplugin.so" must have the name "aplugin". A warning should be issued if there is a mismatch, and you will not be able to unload the plugin. Note that a plugin library file is only loaded once, however many plugins are instantiated. Hence, plugins should be re-entrant. In addition, since the main executable program is linked with the "-rdynamic" flag, all global symbols in the main executable are available to the plugin. If an attempt to load a plugin fails (specifically the call to dlopen(3) fails), then the error message returned by dlerror(3) is written to standard output. BUILDING A PLUGIN ================= Assuming you are working from the KSnuffle source distribution, and want to create a new plugin called "myplugin", the following is a simple cookbook method that should work. Create a subdirectory called "myplugin" in the "plugins" directory, and copy the files Makefile.am, knd_demo.cpp and knd_demo.h from the "demo" subdirectory. Rename the C++ files as "knd_myplugin.cpp" and "knd_myplugin.h", and edit Makefile.am to replace each instance of "demo" with "myplugin". You will also need to edit "plugins/Makefile.am" to include the "myplugin" subdirectory, and "configure.in" (in the top-level directory) to include "plugins/myplugin/Makefile" in the list of makefile's to be built. Next, from the top-level directory, run the following commands: autoconf automake ./automoc ./configure The "plugins/myplugin" directory should now, in addition, contain the files "Makefile.in" and "Makefile". Issuing the command make should build the program in the normal way; in addition, it should build a library file called "myplugin" in the "plugins/myplugin" directory. Now, create a file in "plugins/myplugin" called "myplugin.spec". This should contain a short text description of the plugin, the first line of which appears in the R/H column of the plugin selection dialog. Change to the directory "plugins/plugins" and execute the commands: ln -s ../myplugin/myplugin myplugin.so ln -s ../myplugin/myplugin.spec myplugin.spec You can test the plugin without installing anything by changing to the "ksnuffle" directory and, as root, executing the command (with the appropriate path): ./ksnuffle -P/home/mike/....../ksnuffle-0.6/plugins/plugins Your plugin should appear in the plugin list when the "Plugin" button is clicked; clicking on its entry should display its description. Note that the -P option only works if root runs KSnuffle (ie., not when the program is running setuid-root), so privileged users cannot run their own, possibly trojan, plugins.