/* ** Copyright (C) 2001-2007 by Carnegie Mellon University. ** ** @OPENSOURCE_HEADER_START@ ** ** Use of the SILK system and related source code is subject to the terms ** of the following licenses: ** ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract F19628-00-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ */ #ifndef _DYNLIB_H #define _DYNLIB_H #include "silk.h" RCSIDENTVAR(rcsID_DYNLIB_H, "$SiLK: dynlib.h 7622 2007-06-22 15:25:43Z mthomas $"); #include "utils.h" #include "rwpack.h" #include "skstream.h" /* * Each plug-in should define a dynlib_api_version() routine that * returns this value. This allows the application to skip an old * plug-in without a SEGV. */ #define DYNLIB_API_VERSION 5 /* * The plug-in's setup() method should return on of these values, as * explained below. */ #define DYNLIB_FAILED 1 #define DYNLIB_WILLPROCESS 2 #define DYNLIB_WONTPROCESS 3 /* * dynlib provides an interface to C-plug-ins---dynamic libraries * loaded at run time. * * TO USE A PLUG-IN: * * The application that wants to use a plug-in does the following: * * 1. Calls dynlibCreate(appType) where 'appType' is one of the * symbols listed in the 'dynlibSymbolId' enumeration and describes * the type of the application; this function will return an * interface pointer, 'dlISP'. * * 2. Calls dynlibLoad(dlISP, path) where 'path' is the path to the * dynamic library. If 'path' does not contain a slash, dynlibLoad() * will first look for the plug-in * $SILK_PATH/SILK_SUBDIR_PLUGINS/path. If that fails (or if 'path' * contains a slash), 'path' is handed to dlopen() unaltered. * dlopen() may consult LD_LIBRARY_PATH (or similar). If dlopen() * fails, DYNLIB_FAILED is returned. * * If dlopen() succeeds, dynlibLoad() will verify that the plug-in's * version matches the DYNLIB_API_VERSION given above and that the * plug-in has all the required subroutines. If it does not, * DYNLIB_FAILED is returned. Finally, dynlibLoad() will call the * plug-in's setup() method and the result of that method is returned * to the caller. The details of the setup() method are described * below. * * 2a. Should the application desire to print any options associated * with the plug-in, it may call dynlibOptionsUsage(dlISP) which will * call the plug-in's optionsUage() method, if it exists. * * 3. Some plug-ins may require additional configuration prior to * options handling. The dynlibConfigure() method will call the * plug-in's configure() method, if it exists. * * 4. Once the application has called the options parser, it can use * dynlibCheckActive(dlISP) to see if the plug-in should be called as * part of the application's processing--some applications only * become active when the user specifies an option related to the * plug-in. Some applications may have to explicitly initialize and * activate the plug-in by calling the dynlibInitialize() method. * * 5. If the plug-in is active, dynlibGetRWProcessor(dlISP) returns a * pointer to the function that the application should call. For a * filtering application, dynlibGetRWProcessor() returns a pointer to * the plug-in's filter() subroutine. * * 6. Once processing is completed, the application should call * dynlibTeardown(dlISP) which will free the dlISP data structure and * call teardown() on the plug-in. * * * * TO BE A PLUG-IN: * * The code that expects to by used by the dynlib interface must * provide the following C subroutines: * * - int setup(dynlibInfoStruct_t *dlISP, dynlibSymbolId appType); * * This subroutine should set up the plug-in; if the plug-in has its * own options, they can to be registered now. setup() should * return one of: * * DYNLIB_FAILED - if processing fails * DYNLIB_WONTPROCESS - if application should do normal output * DYNLIB_WILLPROCESS - if this plug-in takes over output * * - void teardown(dynlibSymbolId appType); * * Any cleanup the plug-in requires should happen in this * subroutine. * * In addition, the following subroutines MAY exist in the plug-in: * * - int dynlib_api_version(void) { return DYNLIB_API_VERSION; } * * This subroutine, if it exists, is called first to verify that * the plug-in and application are using a common API. If it does * not exist, the application will assume the APIs are correct. * * - int configure(dynlibInfoStruct_t *dlISP, void *data); * * This subroutine is optional. It provides a way to pass * arbitrary data between the plug-in and the application. It is * often used as an alternate way to configure the options. The * exact purpose of this routine will depend on the application and * the plug-in. * * - int initialize(dynlibInfoStruct_t *dlISP, dynlibSymbolId appType); * * This subroutine should do any "expensive" initialization * required by the plug-in in preparation for calling one of the * interface subroutines listed below. * * - void optionsUsage(dynlibSymbolId appType, FILE *fh); * * If the plug-in has registered options, this subroutine should * print a them and a short usage message to the given file handle. * * To be used by an application type, the plug-in must provide the * necessary interface subroutine. The interface routine depends on * the 'appType' that is specified in the dynlibCreate() call that * the application makes: * * DYNLIB_SHAR_FILTER: used by rwfilter * int filter(rwRec *rwRec); * * This subroutine works in tadem with the standard filtering rules * of rwfilter (and other shared filter plug-ins) to determine * whether the rwRec should pass the filter. This subroutine may * not see all rwRec records since they may be filtered by one of * the standard rules before reaching this plug-in. The subroutine * should return 0 if the rwRec passes the filter; 1 otherwise. * * The dynlib plug-in code will call this filter() routine ONCE per * SiLK Flow record. If a single plug-in provides multiple * filtering switches, the plug-in must pass the record through all * of the applicable filtering tests before returning. * * If the filter() function is not present, the check() function * will be used instead if available. This is to support older * plug-ins, and this functionality should not be relied upon. * * DYNLIB_EXCL_FILTER: used by rwfilter * int check(rwRec *rwRec); * * Obsolete. Has the same functionality as DYNLIB_SHAR_FILTER. * * DYNLIB_CUT: used by rwcut * int cut(unsigned int f, char *out, size_t len_out, rwRec *rwrec) * * Arguments: * f: which field to output (indexed from 1) * out: a string buffer to hold the output * len_out: the length of the string buffer 'out' * rwrec: a SiLK flow record * Returns: * when 'f' is zero * => the number of supported fields * when 'f' is non-zero * when 'out' is NULL and 'len_out' has any value * when 'rwrec' is NULL * => the size of buffer needed to hold the complete title * of field 'f' * when 'rwrec' is non-NULL * => the size of buffer needed to hold the longest * possible (textual) value of field 'f' * when 'out' is non-NULL * when 'rwrec' is NULL * => length of buffer necessary to hold full title; writes * the first 'len_out'-1 bytes of the title of field 'f' * into 'out' * when 'rwrec' is non-NULL * => length of buffer necessary to hold full textual * value; writes the first 'len_out'-1 bytes of the * textual value of field 'f' into 'out' * * * DYNLIB_SORT: used by rwsort * int sort(unsigned int f, uint8_t *bin_val, const rwRec *rec) * * Arguments: * f: field to get the binary or textual value of * bin_val: buffer to fill with a binary value that rwsort will * use for sorting; rwsort will not ask the plug-in for * more data; this value should be everything rwsort * needs to know. rwsort will use memcmp() to compare * values; the values should be in big-endian byte * order. THIS BUFFER MAY NOT BE WORD ALIGNED. * rec: SiLK flow record * Returns: * when 'f' is zero * => the number of supported fields * when 'f' is non-zero * when 'bin_val' or 'rec' is NULL * => the number of bytes required to hold the binary value * of field 'f' * when 'bin_val' and 'rec' are non-NULL * => length of the binary value; uses 'rec' to compute the * value of field 'f' and writes that binary value into * 'bin_val'. ASSUMES 'bin_val' IS BIG ENOUGH! * * * DYNLIB_UNIQ: used by rwuniq * int uniq(unsigned int f, uint8_t bin_val, char *text_val, size_t text_len, rwRec *rec) * * Arguments: * f: field to get the binary or textual value of * bin_val: when reading SiLK records, this is an output buffer * that this function fills with the binary value * representing field 'f'; during output, rwuniq will * use this parameter to pass a value into the function * which the function should convert to text. THIS * BUFFER MAY NOT BE WORD ALIGNED. * text_val: buffer to fill with the textual value * text_len: length of the buffer 'text_val' * rec: SiLK flow record * Returns: * when 'f' is zero * => the number of supported fields * when 'f' is non-zero * when 'bin_val' is NULL * => the result of running cut(f, text_val, text_len, rwrec) * when 'bin_val' is non-NULL * when 'text_val' is non-NULL and 'rec' has any value * => length of buffer necessary to hold the complete * textual value; fills 'text_val' with the first * 'text_len'-1 bytes of converting the binary value in * 'bin_val', corresponding to field 'f', to text. * when 'text_val' is NULL and 'text_len' has any value * when 'rec' is non-NULL * => length of the binary value; uses 'rec' to compute * the value of field 'f' and writes that binary value * into 'bin_val'. ASSUMES 'bin_val' IS BIG ENOUGH! * when 'rec' is NULL * => the number of bytes required to hold the binary * value of field 'f' * * * DYNLIB_PTOFLOW: used by rwptoflow * int ptoflow(rwRec *a, void *pktsrc) * * Arguments: * the flow record to generate from packet data * the packet source, packet header, and packet data * Returns: * 0 to output the flow record but the application should check * any additional dynamic libraries as well. * 1 to immediately output the flow record, bypassing any * additional dynamic libraries * 2 to immediately output the packet into the 'packet reject' * file, bypassing any additional dynamic libraries * 3 to immediately ignore the packet, outputing neither the flow * record nor the packet, bypassing any additional dynamic * libraries * Side Effects: * May modify the record to obfuscate the data it contains. * */ /* * A list of application types. One of these should be passed to * dynlibCreate(). */ typedef enum _dynlibSymbolId { DYNLIB_SETUP, /* internal use -- must be first*/ DYNLIB_TEARDOWN, /* internal use */ DYNLIB_VERSION, /* internal use */ DYNLIB_CONFIGURE, /* internal use */ DYNLIB_INITIALIZE, /* internal use */ DYNLIB_OPT_USAGE, /* internal use */ DYNLIB_EXCL_FILTER, /* rwfilter: augment other filter rules */ DYNLIB_SHAR_FILTER, /* rwfilter: augment other filter rules */ DYNLIB_CUT, /* rwcut: output of data */ DYNLIB_SORT, /* rwsort: orders records by attributes */ DYNLIB_UNIQ, /* rwuniq: bin records by attribute(s) */ DYNLIB_PTOFLOW, /* rwptoflow: create flow from packet data */ DYNLIB_VOID /* internal use -- must be last */ } dynlibSymbolId; /* * Pointer to function returning int---the actual argument list * varies by function. We store an array of these in the * dynlibInfoStruct_t, and it is the return type of * dynlibGetRWProcessor(). */ typedef int (*dynlib_fn_t)(); /* * The structure that holds information about the plug-in. */ struct _dynlibInfoStruct; typedef struct _dynlibInfoStruct dynlibInfoStruct_t; typedef dynlibInfoStruct_t * dynlibInfoStructPtr; #define dynlibInfoStruct dynlibInfoStruct_t /* * dynlibCreate: * get space and initialize struct * Inputs: * The type of application * Outputs: * dynlibInfoStruct_t *dlISP; */ dynlibInfoStruct_t *dynlibCreate(dynlibSymbolId appType); /* * dynlibLoad: * check all stuff about potential dynamic lib: load the library * and check that it has the necessary functions. To find Call * the dynamic library's setup() subroutine which may register * options * Input: * dynlibInfoStruct_t *dlISP * path to dyn lib * Output: * 0 if ok; 1 else * Side Effects: * struct dlISP filled. */ int dynlibLoad(dynlibInfoStruct_t *dlISP, const char *dlPath); /* * dynlibConfigure * * Do any additional setup/configuration by calling the plug-in's * configure() method. This function returns 0 if the plug-in * has a configure() method, and 1 otherwise. The return status * of the confiugre() method is returned in *out_status. */ int dynlibConfigure(dynlibInfoStruct_t *dlISP, void *data); /* * dynlibInitialize: * Call the dynamic library's initalize() subroutine. The idea * is to put expensive initialization code in the initialize() * routine, and only call it once the application knows the * dynamic library will be used. * * Once the initialize() routine returns 0, this wrapper will not * call it again; if you must call initialize() multiple times, * use the dynlibClearInitialized() macro to clear the * 'initialized()-was-called' flag. * Input: * dynlibInfoStruct_t *dlISP * Output: * Returns 0 if * -- initialized() does not exist, or * -- initialized() returns 0, or * -- initialized() previously returned 0 * Otherwise returns status of call to initialize() * Side Effects: * Depends on shared library */ int dynlibInitialize(dynlibInfoStruct_t *dlISP); /* * dynlibOptionsUsage: * Calls the dynamic library's optionsUsage() subroutine * Input: * dynlibInfoStruct_t *dlISP * FILE *fh * Output: * none * Side Effects: * Depends on shared library */ void dynlibOptionsUsage(dynlibInfoStruct_t *dlISP, FILE *fh); /* * dynlibGetRWProcessor: * Returns a pointer to the function applicable to this app-type; * e.g., for DYNLIB_CUT returns a pointer to cut(). The * existence of the function was checked in dynlibLoad * Input: * dynlibInfoStruct_t *dlISP * Output: * function ptr * Side Effects: * None. */ dynlib_fn_t dynlibGetRWProcessor(dynlibInfoStruct_t *dlISP); /* * dynlibTeardown: * close and free mem * Inputs: * dynlibInfoStruct_t *dlISP * Outputs: * None */ void dynlibTeardown(dynlibInfoStruct_t *dlISP); /* * dynlibGetPath * Return the path to the dynamic library * Inputs: * dynlibInfoStruct_t *dlISP * Outputs: * A \0 terminated string. String should be considered * read-only. Returns the path passed to dlopen to open * the dynamic library. * Side Effects: * None. */ const char *dynlibGetPath(const dynlibInfoStruct_t *dlIPS); /* * dynlibCheckLoaded * Returns status of loading and checking the plug-in * Inputs: * dynlibInfoStruct_t *dlISP * Outputs: * Return 1 if the plug-in was successfully loaded and checked, 0 * otherwise. * Side Effects: * None. * Notes: * dlISP may be NULL */ int dynlibCheckLoaded(const dynlibInfoStruct_t *dlISP); /* * dynlibGetAppType * Returns the application type as set in dynlibCreate() * Inputs: * dynlibInfoStruct_t *dlISP * Outputs: * The dynlibSymbolId for this application * Side Effects: * None. */ dynlibSymbolId dynlibGetAppType(const dynlibInfoStruct_t *dlISP); /* * dynlibGetStatus * Return the status of the call to dynlibLoad() * Inputs: * dynlibInfoStruct_t *dlISP * Outputs: * An integer value of: * * DYNLIB_FAILED - if processing fails * DYNLIB_WONTPROCESS - if application should do normal output * DYNLIB_WILLPROCESS - if this plug-in takes over output * Side Effects: * None. */ int dynlibGetStatus(const dynlibInfoStruct_t *dlISP); /* * dynlibGetAppContext * Return the application context: a pointer to a struct * containing the application's name and its options * * Plug-ins should call skAppContextSet() with the value returned * by this macro in their setup() routines. This will ensure * that the plug-in's options are in the application's main * options structure. * * Inputs: * dynlibInfoStruct_t *dlISP * Outputs: * The global application context object, skAppContext_t* * Side Effects: * None. */ skAppContext_t *dynlibGetAppContext(const dynlibInfoStruct_t *dlISP); /* * dynlibCheckActive * Return non-zero if this plug-in will be processing the * rwRecPtr's and thus should be called. * Inputs: * dynlibInfoStruct_t *dlISP * Outputs: * The state of the active flag * Side Effects: * None. * Notes: * dlISP may be NULL */ int dynlibCheckActive(const dynlibInfoStruct_t *dlISP); /* * dynlibMakeActive * Mark the plug-in as being active: i.e., the plug-in will be * processing the rwRecPtr's * Inputs: * dynlibInfoStruct_t *dlISP * Outputs: * None. * Side Effects: * None. */ void dynlibMakeActive(dynlibInfoStruct_t *dlISP); /* * dynlibClearInitialized * Clear the flag that indicates that the initialize() routine * has been run. See dynlibInitialize() for details. * Inputs: * dynlibInfoStruct_t *dlISP * Outputs: * None. * Side Effects: * None. */ void dynlibClearInitialized(dynlibInfoStruct_t *dlISP); /* * dynlibSetDoNotClose * Set the do-not-close flag to TRUE. This will prevent * dlclose() from being called on the plug-in. We do this do * work around an Oracle problem with unloading libraries. * Inputs: * dynlibInfoStruct_t *dlISP * Outputs: * None. * Side Effects: * None. */ void dynlibSetDoNotClose(dynlibInfoStruct_t *dlISP); /* * dynlibLastError * Return the most recent value from dlerror() * Inputs: * dynlibInfoStruct_t *dlISP * Outputs: * A \0 terminated string. String should be considered * read-only. The string only contains a valid error message * immediately after an error occurred. At other times, the * string may be empty or contain a previous error. * Side Effects: * None. */ const char *dynlibLastError(const dynlibInfoStruct_t *dlISP); /* * dynlibOpenDataInputStream * Create an skstream_t object using the specified 'content_type' * and 'filename', open it, and fill the location pointed to by * 'stream' with the object. If the application has called * dynlibSetOpenInputFunction(), that function will be used if it * is non-null. * Inputs: * location in which to return address of skstream_t object * content_type of the filename * name of file to open * Outputs: * Returns 0 if stream was successfully opened and should be * used. Returns -1 on error. Returns 1 if the plug-in should * ignore the file. * Side Effects: * 'stream' is filled with address of skstream_t object. */ int dynlibOpenDataInputStream( skstream_t **stream, skcontent_t content_type, const char *filename); /* * Type signature of the function that dynlibOpenDataInputStream() * will call. */ typedef int (*open_data_input_fn_t)( skstream_t **stream, skcontent_t content_type, const char *filename); /* * dynlibSetOpenInputFunction * Sets the function that dynlibOpenDataInputStream() should for * opening data files. If this function is not called or called * with a NULL parameter, the sequence of functions * skStreamCreate(), skStreamBind(), skStreamOpen() is called. * Inputs: * function pointer to use for opening files * Outputs: * None. * Side Effects: * None. */ void dynlibSetOpenInputFunction(open_data_input_fn_t open_fn); /* These are the functions on the plug-in that this code may call */ int dynlib_api_version(/*(void)*/); int setup(/*(dynlibInfoStruct_t *dlISP, dynlibSymbolId appType)*/); int configure(/*(dynlibInfoStruct_t *dlISP, void *data)*/); void teardown(/*(dynlibSymbolId appType)*/); void optionsUsage(/*(dynlibSymbolId appType, FILE *fh)*/); int initialize(/*(dynlibInfoStruct_t *dlISP, dynlibSymbolId appType)*/); int filter(/*(rwRec *rwrec)*/); int cut(/*(unsigned int type, char *out, size_t len_out, rwRec *rwrec)*/); int sort(/*(rwRec *a, rwRec *b)*/); int uniq(/*(TO BE DECIDED)*/); int ptoflow(/*(rwRec *rwrec, void *pktsrc)*/); #endif /* _DYNLIB_H */ /* ** Local Variables: ** mode:c ** indent-tabs-mode:nil ** c-basic-offset:4 ** End: */