/*
Copyright (c) 2010, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.
* Redistributions in binary form must reproduce the above 
  opyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials
  provided with the distribution.
* Neither the name of the Dirk Krause nor the names of
  contributors may be used to endorse or promote
  products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/

/**	@file	fsnmp.h	Include file for fsnmp modules.
*/

#ifndef FSNMP_INCLUDED
#define FSNMP_INCLUDED 1

#include <dk.h>

#include <stdio.h>
#if DK_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if DK_HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#if DK_HAVE_ERRNO_H
#include <errno.h>
#endif
#if DK_HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if DK_HAVE_UNISTD_H
#include <unistd.h>
#endif
#if DK_HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if DK_HAVE_SIGNAL_H
#include <signal.h>
#endif
#if DK_HAVE_SYS_VARARGS_H
#include <sys/varargs.h>
#endif
#if DK_HAVE_VARARGS_H
#include <varargs.h>
#endif
#if DK_HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#if DK_HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#if DK_HAVE_NETDB_H
#include <netdb.h>
#endif
#if DK_TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#if DK_HAVE_TIME_H
#include <time.h>
#else
#if DK_HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#endif
#endif
#if DK_HAVE_MATH_H
#include <math.h>
#endif
#if DK_HAVE_STRING_H
#include <string.h>
#endif
#if DK_HAVE_CTYPE_H
#include <ctype.h>
#endif

#if DK_HAVE_LIBNETSNMP
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/utilities.h>
#if DK_HAVE_NETSNMP_ENABLE_FILELOG
#if defined(__cplusplus)
extern "C" {
#endif
/**	Enable logging to file.
 * 	@param	h	Log handler.
 * 	@param	v	Log level.
 */
void netsnmp_enable_filelog DK_PR((netsnmp_log_handler *h, int v));
#if defined(__cplusplus)
};
#endif
#endif
#endif

#include <dkmem.h>
#include <dksf.h>
#include <dkstr.h>
#include <dksignal.h>
#include <dkma.h>

/**	Filter job.
*/
typedef struct {
  int		flags;		/**< Flags, see FSNMP_FLAG_xxx. */
  int		exit_code;	/**< Exit status code. */
  char		**argv;		/**< -Xxxx arguments. */
  char		*arg_0;		/**< The argument without -. */
  char		*buffer_in;	/**< Input/output buffer. */
  size_t	sz_buffer_in;	/**< Input buffer size. */
  char		*buffer_out;	/**< Output buffer. */
  size_t	sz_buffer_out;	/**< Output buffer size. */
  size_t	sz_bo_used;	/**< Number of bytes used in output buffer. */
  char		*temp_file;	/**< File name buffer for temporary file. */
  size_t	sz_temp_file;	/**< Size of \a temp_file. */
  time_t	last_timestamp;	/**< Last printed timestamp. */
  int		os;		/**< Output socket or fd. */
  struct sockaddr_in	sain;	/**< Peer name. */
  char		*a_hostport;	/**< Allocated host name and port. */
  char		*a_acctdest;	/**< Allocated space for accounting destination. */
  char		*hostname;	/**< Host name to connect to. */
  unsigned short	portnumber;	/**< Port to connect to in host representation */
  char		*a_community;	/**< SNMP community. */
  int		snmp_vers;	/**< SNMP version. */
  struct timeval	shd;	/**< Timeout for shutdown data socket. */
  struct timeval	shp;	/**< Timeout for shutdown accounting socket. */
  int		mintimepc;	/**< Minimum time if pagecount not changed. */
  oid		*oid_ds;	/**< Device state OID. */
  oid		*oid_ps;	/**< Printer state OID. */
  oid		*oid_pc;	/**< Page count OID. */
  size_t	sz_oid_ds;	/**< Length of \a oid_ds. */
  size_t	sz_oid_ps;	/**< Length of \a oid_ps. */
  size_t	sz_oid_pc;	/**< Length of \a oid_pc. */
  time_t	snmp_start_time;	/**< Start timestampe. */
  unsigned long	pc1;		/**< Pagecount before starting the job. */
  unsigned long pc2;		/**< pagecount after job. */
  unsigned	dt_pmin;	/**< Minimum local port number for data. */
  unsigned	dt_pmax;	/**< maximum local port number for data. */
  unsigned	ac_pmin;	/**< Minimum local port number for accounting. */
  unsigned	ac_pmax;	/**< Maximum local port number for accounting. */
} FC;


/**	Summary of SNMP response.
*/
typedef struct {
  int ds;		/**< Device state. */
  int ps;		/**< Printer state. */
  unsigned long pc;	/**< Page count. */
} SUMMARY;

/*	Flags for operations
*/

/**	Flag: Running as output filter. */
#define FSNMP_FLAG_OF		1

/**	Flag: Ensure CTRL-D at start. */
#define FSNMP_FLAG_CTRL_D_START	2

/**	Flag: Ensure CTRL-D at end. */
#define FSNMP_FLAG_CTRL_D_END	4

/**	Flag: Issue debug output. */
#define FSNMP_FLAG_DEBUG	8

/**	Flag: do logging. */
#define FSNMP_FLAG_HAVE_LOG	16

/**	Flag: Logging to stdout. */
#define FSNMP_FLAG_STDOUT	32

/**	Flag: Shutdown transfer socket. */
#define FSNMP_SHUTDOWN_TRANSFER	64

/**	Flag: Use timeout when shutting down transfer socket. */
#define FSNMP_TIMEOUT_TRANSFER	128

/**	Flag: Shutdown accounting socket. */
#define FSNMP_SHUTDOWN_PAGECOUNT	256

/**	Flag: Use timeout when shutting down accounting socket. */
#define FSNMP_TIMEOUT_PAGECOUNT	512


/**	Log messages: No message yet. */
#define FSNMP_LOG_NONE			0

/**	Log messages: No SNMP response. */
#define FSNMP_LOG_NO_RESPONSE		1

/**	Log messages: Error in SNMP response. */
#define FSNMP_LOG_ERROR_IN_RESPONSE	2

/**	Log messages: Printer problem. */
#define FSNMP_LOG_PRINTER_PROBLEM	3

/**	Log messages: Printer busy. */
#define FSNMP_LOG_PRINTER_BUSY		4

/**	Log messages: Printer ready. */
#define FSNMP_LOG_PRINTER_READY		5

/**	Log messages: Error while retrieving SNMP response. */
#define FSNMP_LOG_ERROR_RETRIEVING	6

/**	Log messages: Have SNMP. */
#define FSNMP_LOG_HAVE_SNMP		7

/**	Log messages: Not yet printed. */
#define FSNMP_LOG_NOT_YET_PRINTED	8


/**	Device state: Unknown. */
#define DEVICE_UNKNOWN		1

/**	Device state: Running. */
#define DEVICE_RUNNING		2

/**	Device state: Warning. */
#define DEVICE_WARNING		3

/**	Device state: Power-on self test. */
#define DEVICE_TESTING		4

/**	Device state: Down. */
#define DEVICE_DOWN		5

/**	Printer state: Other. */
#define PRINTER_OTHER		1

/**	Printer state: Unknown. */
#define PRINTER_UNKNOWN		2

/**	Printer state: Idle. */
#define PRINTER_IDLE		3

/**	Printer state: Printing. */
#define PRINTER_PRINTING	4

/**	Printer state: Warmup. */
#define PRINTER_WARMUP		5

/**	Default flags. */
#define FSNMP_FLAGS_DEFAULTS	0

/*	Exit status codes
*/

/**	Exit code: Printed successfully. */
#define	EXIT_SUCCESS		0

/**	Exit code: Printing failed, retry later. */
#define EXIT_FAILED		1

/**	Exit code: Job aborted, do not retry. */
#define EXIT_ABORT		2

/**	Exit code: Remove job. */
#define EXIT_REMOVE		3

/**	Exit code: Hold job in queue for later printing. */
#define	EXIT_HOLD		6

/**	Exit code: Spooling is deactivated for this queue. */
#define EXIT_NOSPOOL		7

/**	Exit code: Printing is deactivated for this queue. */
#define EXIT_NOPRINT		8

/**	Exit code: Killed by signal. */
#define EXIT_SIGNAL		9

/**	Exit code: Processing failed definitely, do not retry. */
#define EXIT_FAILNORETRY	10

/**	Log priority: Unprinted message. */
#define PRIO_NONE		0

/**	Log priority: Fatal error. */
#define PRIO_FATAL		1

/**	Log priority: Error. */
#define PRIO_ERROR		2

/**	Log priority: Warning. */
#define PRIO_WARNING		3

/**	Log priority: Informational. */
#define PRIO_INFO		4

/**	Log priority: Progress. */
#define PRIO_PROGRESS		5

/**	Log priority: Debug. */
#define PRIO_DEBUG		7

/*	Size of input/output buffer.
*/
#ifndef FSNMP_BUFFER_SIZE
/**	Buffer size. */
#define FSNMP_BUFFER_SIZE	8192
#endif

/*	fsnmpm.c module
*/
#if defined(EXTERN)
#undef EXTERN
#endif
#if FSNMPM_C
#define EXTERN /* dummy */
#else
#if DK_HAVE_PROTOTYPES
#define EXTERN /* dummy */
#else
#define EXTERN extern
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif
/**	Check whether or not we can continue.
 * 	@param	fc	FSNMP job.
 * 	@return	Flag: Can continue.
 */
EXTERN int fsnmp_cc DK_PR((FC *fc));
#if defined(__cplusplus)
};
#endif

/*	fsnmp.c module
*/
#if defined(EXTERN)
#undef EXTERN
#endif
#if FSNMP_C
#define EXTERN /* dummy */
#else
#if DK_HAVE_PROTOTYPES
#define EXTERN /* dummy */
#else
#define EXTERN extern
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif
/**	Run as normal filter.
 * 	@param	fc	FSNMP job.
 */
EXTERN void fsnmp_filter DK_PR((FC *fc));

/**	Run as output filter.
 * 	@param	fc	FSNMP job.
 */
EXTERN void fsnmp_of DK_PR((FC *fc));

/**	Check peer.
 * 	@param	fc	FSNMP job.
 */
EXTERN void fsnmp_check_peer DK_PR((FC *fc));
#if defined(__cplusplus)
};
#endif
#if !FSNMP_C
extern char *fsnmp_kw[];
#endif

/*	fsnmpcmd.c module
*/
#if defined(EXTERN)
#undef EXTERN
#endif
#if FSNMPCMD_C
#define EXTERN /* dummy */
#else
#if DK_HAVE_PROTOTYPES
#define EXTERN /* dummy */
#else
#define EXTERN extern
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif
/**	Initialize FSNMP job.
 * 	@param	fc	FSNMP job.
 */
EXTERN void fsnmpcmd_init DK_PR((FC *fc));

/**	Process command line arguments.
 * 	@param	fc	FSNMP job.
 * 	@param	argc	Number of command line arguments.
 * 	@param	argv	Command line arguments array.
 */
EXTERN void fsnmpcmd_apply_argv DK_PR((FC *fc, int argc, char **argv));

/**	Get command line option argument.
 * 	@param	fc	FSNMP job.
 * 	@param	k	Key character.
 * 	@return	Option argument or NULL.
 */
EXTERN char *fsnmpcmd_get_argv DK_PR((FC *fc, char k));

/**	Create file name for temporary file.
 * 	@param	fc	FSNMP job.
 */
EXTERN void fsnmpcmd_create_temp_file_name DK_PR((FC *fc));

/**	Read configuration file.
 * 	@param	fc	FSNMP job.
 */
EXTERN void fsnmpcmd_read_config_file DK_PR((FC *fc));

/**	Convert IP4 address from dotted decimal notation to address.
 * 	@param	hn	Host name (IP address) to convert.
 * 	@return	Address or 0UL.
 */
EXTERN unsigned long fsnmp_dotted_string_to_ip DK_PR((char *hn));

/**	Look up host name.
 * 	@param	hn	Host name to search.
 * 	@return	IP4 address of host or 0UL on error.
 */
EXTERN unsigned long fsnmp_lookup_host  DK_PR((char *hn));
#if defined(__cplusplus)
};
#endif


/*	fsnmplog.c module
*/
#if defined(EXTERN)
#undef EXTERN
#endif
#if FSNMPLOG_C
#define EXTERN /* dummy */
#else
#if DK_HAVE_PROTOTYPES
#define EXTERN /* dummy */
#else
#define EXTERN extern
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif
/**	Log message to file.
 * 	@param	fc	FSNMP job.
 * 	@param	prio	Log priority.
 * 	@param	format	Message format.
 */
EXTERN void fsnmplog DK_PR((FC *fc, int prio, char *format, ...));

/**	Log that response was received.
 * 	@param	fc	FSNMP job.
 * 	@param	bytes	Number of bytes in response.
 */
EXTERN void fsnmplog_response DK_PR((FC *fc, int bytes));
#if defined(__cplusplus)
};
#endif



/**	Only one filter can write to the status file. */
#define	FORCE_OF_LOGGING_TO_STDERR	0

/**	Socket address for Internet access. */
typedef struct sockaddr_in SOIN;

/**	Size of socket address. */
#define SZSOIN (sizeof(SOIN))


#if !FSNMPM_C
/**	Keywords for writing log messages. */
extern char *fsnmp_kw[];
#endif

#endif

