/**
 * @file FAVE.h
 * @brief  FAVE - FLAM anti virus exit
 * @author limes datentechnik gmbh
 * @date  21.10.2018
 * @copyright (c) 2018 limes datentechnik gmbh
 *
 * @mainpage FAVE - Service Provider Interface
 *
 * This service provider interface enables the possibility to write a
 * custom converter for virus scanning when reading or writing original
 * data with FLAM. Any malware solution can be used that offers some
 * form of API. FLAM comes with default implementation for malware
 * scanning using the ClamAV daemon.
 *
 * A service provider interface implementation can be invoked as a
 * conversion step during data processing. See example below:
 *
 * <pre>
 * write.text(... avscan(
 *                       METHOD=DELETE/ERROR,TRACE,STATISTICS,
 *                       LIBRARY='favelib',
 *                       FUNC='clamav',
 *                       PARAMETER="clamav.daemon:3310'"
 *                       ) ...)
 * </pre>
 *
 * The different functions can have different parameter strings. All of them
 * depend on the implementation of the custom anti virus exit according
 * to this service provider interface.
 *
 * @section IMPL Implementation overview
 * The interface that must be implemented to create a custom exit is
 * described in the @ref MAINFUNC "FAVE function" section. This interface
 * function must be an external function of a DLL/SO or load module (z/OS).
 * A conversion (<code>AVSCAN()/CNVAVS()</code>) object is used to configure
 * how to call the custom exit routine.
 *
 * First, the DLL/SO is loaded based on the specified library name or
 * @ref DEFAULTNAMES "default name". Then the function address is
 * determined based on the provided function name or @ref DEFAULTNAMES "default name").
 * For load modules on z/OS, the function name is the load module name and
 * the library name must be empty. It is also possible to use DLLs on z/OS.
 *
 * If the @ref MAINFUNC "function pointer" is determined, the exit driver
 * calls the exit function with the function code for opening
 * (@ref FUNCCODE "see function codes"). A function-code-specific parameter
 * structure ((@ref FUNCSTRUCT "see FaveOpn struct")) contains the parameter string
 * from the exit call specification (<code>AVSCAN(PARAMETER="xxx")</code>).
 * Additionally, a read or write indication, a compression indication, a
 * re-open indication and trace/statistics flags (@ref FAVEFALGS "see here")
 * are provided as input.
 *
 * The re-open flag is set by the exit driver if another data stream must be
 * scanned where no additional log information must be returned. The service
 * provider should implement the opening function as fast as possible.
 *
 * The first parameter of the exit function contains a handle. When it is
 * first called with the function code for opening (FAVE_FUNC_OPN), the
 * handle's value is NULL. This handle can be used to store state information
 * that may be needed during data processing by the exit (i.e. subsequent
 * calls with the FAVE_FUNC_RUN code). The exit function is responsible for
 * allocating memory for the handle (if needed) when called with the function
 * code for opening (FAVE_FUNC_OPN) and must release it (and all other
 * resources) when called with the function code for closing the exit
 * (FAVE_FUNC_CLS).
 *
 * When called with the run function code (FAVE_FUNC_RUN), the exit function
 * gets the input data length and a pointer to the input data as input
 * (see @ref FaveRun) and returns an error if malware is found. The exit
 * driver provides 4096 byte in front and 4096 byte after the data
 * chunk which can be used to prevent copying the data.
 *
 * The exit function is called with the FAVE_FUNC_CLS function code to
 * allow the release of all resources.
 *
 * The run and close functions can return FLMRTC_VRS to indicate found
 * malware.
 *
 * All function code specific parameter structures contain a length and
 * a buffer of size 4096 bytes for an error message. The error message is
 * displayed to the user if the return code differs from zero. If the open
 * and close function return with FLMRTC_OK (0-SUCCESS) and a message is
 * defined then these message are printed as informational to the log of
 * FLAM. This can be used to produce statistics at close or provide a
 * version or identification information at open.
 *
 * @section ITFSTD Interface standards
 * The interface is built on one function with four parameters, a classic
 * load module interface. All parameters of the function are
 * call-by-reference. The function does not have a return value.
 * The return code is the second parameter of the function. There are only
 * two types of parameters:
 *
 * <pre>
 * POINTER:   pointer to an address (usually 32 (PIC S9(9) COMP) or 64 bit)
 * INTEGER:   pointer to a 32 bit number in two's complement (PIC S9(9) COMP)
 * </pre>
 *
 * The type INTEGER has local endianness. On mainframes, this is usually
 * big endian and little endian on x86 platforms.
 *
 * The POINTER type is used for the handle and the parameter structures.
 * The handle is a black box to FLAM. The parameter structures are unions
 * with the function code acting as selector
 * (@ref FUNCSTRUCT "see structures section").
 *
 * To support 64 bit RISC architectures, a strong alignment to 64 bit in the
 * parameter structures is required. This requires a 32 bit dummy field
 * behind each 32 bit length field. The trick with the dummy fields makes
 * the parameter structures compatible between the different supported
 * architectures of FLAM and prevents bus errors on certain platforms.
 *
 * All strings passed to the exit function are null-terminated and the
 * corresponding lengths are set to the string length in bytes without
 * the null character. The exit driver does not expect null-termination from
 * the exit function, but the length fields must be set correctly. For the
 * error message, the length can be set to the size of the error message
 * buffer (4096), respectively, if a null-terminated string is returned
 * by the exit function.
 *
 * @section RTCH Return code handling
 * The return code of the function must be one of the defined FLAM return
 * codes (see module return codes). The return code FLMRTC_VRS indicates
 * that malware was found. The handling depends on the defined method.
 * All other return codes will result in an error and FLAM aborts the
 * remaining processing.
 *
 * @section EXAMPLE Coding example for an FAVE
 * The standard implementation using the ClamAV daemon is deployed
 * as sample C source (FAVECAV.c) in the installation package (SRCLIBC/
 * samples). This implementation uses an internal platform independent API
 * for IP communication and must be linked with the FL5CORE library. It
 * can be used as template for other implementations.
 *
 * The implementation of an exit does not have to be done in C, but the
 * binary interface of the compiled and linked DLL/SO or load module must
 * be compatible to the C calling convention.
 *
 **********************************************************************/

/*! @cond PRIVATE */
#ifdef __cplusplus
   extern "C" {
#endif

#ifndef INC_FAVE_H
#define INC_FAVE_H
/*! @endcond */

/**********************************************************************/

#include"FLMRTC.h"
#include"FLMDEF.h"

/**********************************************************************/

/**
 * @defgroup FUNCCODE Function codes
 * @brief Function codes for anti virus exit
 *
 * The function codes below are passed to the exit function by the exit driver
 * as the third parameter. It signals the current state to the exit function
 * which may act accordingly. The function code also defines the format of the
 * parameter structure. Only the union member of #TuFavePar may be accessed
 * that matches the function code.
 * @{
 */
#define FAVE_FUNC_OPN      1 /**< @brief Function code for opening (used in the first call of the exit function) */
#define FAVE_FUNC_RUN      2 /**< @brief Function code for intermediate processing data */
#define FAVE_FUNC_CLS      3 /**< @brief Function code for closing (used in the last call of the exit function) */
/**@}*/

/**
 * @defgroup DEFAULTNAMES Default names
 * @brief Default names used for library and function name
 *
 * The default names for the DLL/SO and the function name (load module
 * name) are used if no library name or function name are specified in
 * the object specification.
 * @{
 */
#define FAVE_DEFLIB_NAME  "libfave" /**< @brief Default library name  */
#define FAVE_DEFFUC_NAME  "CLAMAVC" /**< @brief Default function name */
/**@}*/

 /**
  * @defgroup FAVEFALGS Flags for FAVE processing
  * @brief Definitions for the flag word in the parameter structure used for open
  *
  * In the opening function, the first word of the parameter structure contains
  * a bit field with the following flags.
  * @{
  */
#define FAVE_FLAG_WRITE     0x00000001U /**< @brief [INPUT]  If set by exit driver, this signals that the exit is called in write operation */
#define FAVE_FLAG_REOPN     0x00000004U /**< @brief [INPUT]  If set by exit driver, indicates that the exit should realize a fast open without additional information */
#define FAVE_FLAG_TRACE     0x00000010U /**< @brief [INPUT]  If set by exit driver, this signals that the exit can produce statistics information when closing (optional) */
#define FAVE_FLAG_STATISTIC 0x00000020U /**< @brief [INPUT]  If set by exit driver, this signals that the exit can produce trace information (optional) */
#define FAVE_FLAG_ACCESS    0x00000040U /**< @brief [INPUT]  If set by exit driver, this signals that the exit can perform additional access control checks (optional) */
#define FAVE_FLAG_STRONG    0x00000080U /**< @brief [INPUT]  If set by exit driver, this signals that the exit must perform strong access control checks (optional) */
#define FAVE_FLAG_COMPRESS  0x00000100U /**< @brief [OUTPUT] If set by service provider, indicates that compression conforming to RFC1952/51 (GZIP) is supported */
 /**@}*/

/**********************************************************************/

/**
* @defgroup FUNCSTRUCT Function structures
* @brief Definition of the function code dependent structures for FAVE.
* @{
*/

/**
* @brief FAVE parameter structure for function code #FAVE_FUNC_OPN
*
* This structure is used when the exit function is called with the function
* code #FAVE_FUNC_OPN.
*
* The first member contains flags that can be set in both directions.
* If the exit is opened for output data, the flag bit #FAVE_FLAG_WRITE
* is set. If it is not set, the exit is opened for reading input data.
* See the flags section for further flags.
*
* The next pair of members contains the length and a pointer to the
* parameter string interpreted by the service provider.
*
* The last member pair is a buffer of 4096 bytes for an error message. The
* corresponding length must be set to the length of the error message.
*/
typedef struct FaveOpn {
   /** @brief [INOUT] Flag word (32 bit) with several bit settings*/
   unsigned int         uiFlg;
   /** @brief [INPUT] Length of the parameter string (32 bit word)*/
   unsigned int         uiPar;
   /** @brief [INPUT] Pointer to the parameter string (32 or 64 bit)*/
   char*                pcPar;
   /** @brief [OUTPUT] Length of error message (32 bit word)*/
   unsigned int         uiMsg;
   /** @brief [DUMMY] 32 bit dummy field for 64 bit alignment*/
   unsigned int         uiDy5;
   /** @brief [OUTPUT] Maximal 4096 byte long error string*/
   char                 acMsg[4096];
}TsFaveOpn;

/**
* @brief FAVE Run structure
*
* This structure is used when the exit function is called with the function
* code #FAVE_FUNC_RUN. It is called for each read/written data segment.
*
* The exit drivers passes the length and a pointer to the input data of the
* current data segment as the first pair of members of the structure.
*
* The last member pair is a 4096 bytes buffer for an error message. The
* corresponding length must be set to the length of the error message.
*/
typedef struct FaveRun {
   /** @brief [INPUT] Length of the input data (32 bit word)*/
   unsigned int         uiInp;
   /** @brief [DUMMY] 32 bit dummy field for 64 bit alignment*/
   unsigned int         uiDy1;
   /** @brief [INPUT] Pointer to the input data (32 or 64 bit)*/
   unsigned char*       pcInp;
   /** @brief [OUTPUT] Length of error message (32 bit word)*/
   unsigned int         uiMsg;
   /** @brief [DUMMY] 32 bit dummy field for 64 bit alignment*/
   unsigned int         uiDy2;
   /** @brief [OUTPUT] Maximal 4096 byte long error string*/
   char                 acMsg[4096];
}TsFaveRun;

/**
* @brief FAVE Close structure
*
* This structure is used when the exit function is called with the function
* code #FAVE_FUNC_CLS. It is always called after data processing is finished,
* no matter if there was error or not.
*
* The only member pair is a 4096 bytes buffer for an error message. The
* corresponding length must be set to the length of the error message.
*/
typedef struct FaveCls {
   /** @brief [OUTPUT] Length of error message (32 bit word)*/
   unsigned int         uiMsg;
   /** @brief [DUMMY] 32 bit dummy field for 64 bit alignment*/
   unsigned int         uiDy1;
   /** @brief [OUTPUT] Maximal 4096 byte long error string*/
   char                 acMsg[4096];
}TsFaveCls;

/**
* @brief FAVE Union of function structures
*
* This union must be used to access structure fields depending on the function
* code that was passed to the exit function. Only the member that corresponds to
* the function code may be accessed. Failing to do so results in undefined behavior!
*/
typedef union FavePar {
   /** @brief [INOUT] Structure for function code #FAVE_FUNC_OPN*/
   TsFaveOpn            stOpn;
   /** @brief [INOUT] Structure for function code #FAVE_FUNC_RUN*/
   TsFaveRun            stRun;
   /** @brief [INOUT] Structure for function code #FAVE_FUNC_CLS*/
   TsFaveCls            stCls;
}TuFavePar;
/**@}*/

/**********************************************************************/

/**
* @defgroup MAINFUNC FAVE function
* @brief This is the only function which must be provided by a DLL/SO or
* load module to fulfill the FLAM Anti Virus Exit (FAVE) Service
* Provider Interface (SPI).
* @{
*/

/**
 * @brief FAVE function
 *
 * This is the function which must be implemented for user-specific
 * virus scanning with FLAM. The same handle is passed to consecutive
 * calls and may be used by the exit function to store internal state.
 *
 * The return code must be set as output parameter by the exit function.
 * The function code is an input parameter and contains one of the values
 * defined in @ref FUNCCODE "this section". Depending on the provided function
 * code, a pointer to a specific parameter structure is given as last parameter.
 *
 * @param [inout] ppHdl   POINTER Service provider handle
 * @param [out]   piRetco INTEGER Return code
 * @param [in]    piFunc  INTEGER Function code (OPN/RUN/CLS)
 * @param [inout] puPara  POINTER Parameter structure
 */
typedef void (TfFavExit)(
   void**         ppHdl,
   int*           piRetco,
   const int*     piFunc,
   TuFavePar*     puPara);
/**@}*/

/**********************************************************************/

/*! @cond PRIVATE */
#endif /* INC_FAVE_H */

#ifdef __cplusplus
   }
#endif
/*! @endcond */
