#ifndef LOCAL_PACKETBL_H
#  define LOCAL_PACKETBL_H

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <resolv.h>
#include <netdb.h>
#include <ctype.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <time.h>
#include <errno.h>
#include <linux/netfilter.h>
#include <libconfig.h>
#include <libnetfilter_queue.h>

#  ifdef HAVE_CONFIG_H
#    include "config.h"
#  endif

#  ifdef USE_SOCKSTAT
#    ifndef SOCKSTAT_PATH
#      define SOCKSTAT_PATH "/tmp/.packetbl.sock"
#    endif
#  endif


#ifdef USE_SOCKSTAT
#include <sys/socket.h>
#include <sys/un.h>
#include <pthread.h>
#endif

#ifdef HAVE_FIREDNS
#include <firedns.h>
#endif

#ifndef BUFFERSIZE
#define BUFFERSIZE 65536
#endif
#ifdef USE_CACHE
#  ifndef USE_CACHE_DEF_LEN
#    define USE_CACHE_DEF_LEN 8192
#  endif
#  ifndef USE_CACHE_DEF_TTL
#    define USE_CACHE_DEF_TTL 3600
#  endif
#endif

#  define TH_FIN        0x01
#  define TH_SYN        0x02
#  define TH_RST        0x04
#  define TH_PUSH       0x08
#  define TH_ACK        0x10
#  define TH_URG        0x20

# define SET_VERDICT nfq_set_verdict
# define PBL_HANDLE nfq_q_handle
# define PBL_SET_MODE nfq_set_mode
# define PBL_COPY_PACKET NFQNL_COPY_PACKET
# define PBL_ID_T u_int32_t
# define PBL_ERRSTR ""

#define DEBUG(x, y) if (conf.debug >= x) { printf(y "\n"); }
#define INVALID_OCTET(x) x < 0 || x > 255
#define DPRINT(format, args...) if (conf.debug == 0) { \
	syslog(LOG_INFO, format , ## args); \
} else { \
	fprintf(stderr, format , ## args); \
}

#define DPRINTQ(format, args...) if (!conf.quiet) { DPRINT(format, ## args) };

struct packet_info {

	uint8_t b1;
	uint8_t b2;
	uint8_t b3;
	uint8_t b4;

	unsigned int s_port;
	unsigned int d_port;

	int flags;
};

struct cidr {

	uint32_t ip;
	uint32_t network;
	uint32_t processed;		/* network, but as a bitmask */

};

struct config_entry {

	char *string;
	struct config_entry *next;
	struct packet_info ip;
	struct cidr	cidr;
	int index;

};

struct config {
	int	allow_non25;
	int	allow_nonsyn;
	int	default_accept;
	int	dryrun;
	int 	log_facility;
	int	queueno;
	int	quiet;
	int	debug;
	struct config_entry *blacklistbl;
	struct config_entry *whitelistbl;
	struct config_entry *blacklist;
	struct config_entry *whitelist;
};

static struct config conf = { 0, 0, 1, 0, LOG_DAEMON, 1, 0, 0, NULL, NULL, NULL, NULL };

struct pbl_stat_info {
	uint32_t	cacheaccept;
	uint32_t	cachereject;
	uint32_t	whitelistblhits;
	uint32_t	blacklistblhits;
	uint32_t	whitelisthits;
	uint32_t	blacklisthits;
	uint32_t	fallthroughhits;
	uint32_t	totalpackets;
};
static struct pbl_stat_info statistics = { 0, 0, 0, 0, 0, 0, 0 };

#ifdef USE_CACHE
struct packet_cache_t {
	uint32_t ipaddr;
	time_t	expires;
	int	action;
};
struct packet_cache_t *packet_cache = NULL;
uint32_t packet_cache_len = USE_CACHE_DEF_LEN;
uint32_t packet_cache_ttl = USE_CACHE_DEF_TTL;
#endif

struct config_entry *hostlistcache = NULL;

int get_packet_info(char *payload, struct packet_info *ip);

int check_packet_list(const struct packet_info *ip, struct config_entry *list);
int check_packet_dnsbl(const struct packet_info *ip, struct config_entry *list);
int parse_cidr(struct config_entry *ce);
/* int validate_blacklist(char *); */
void parse_config(void);
void parse_arguments(int argc, char **argv);
void pbl_init_sockstat(void);
char * get_ip_string(const struct packet_info *ip);
static void pbl_set_verdict(struct PBL_HANDLE *h, PBL_ID_T id,
        unsigned int verdict);

static int pbl_callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
	struct nfq_data *nfa, void *data);
	
typedef struct facility {
	char *string;
	int num;
} facility;

static struct facility facenum[] = {
	{"auth", LOG_AUTH},
	{"authpriv", LOG_AUTHPRIV},
	{"cron", LOG_CRON},
	{"daemon", LOG_DAEMON},
	{"kern", LOG_KERN},
	{"lpr", LOG_LPR},
	{"mail", LOG_MAIL},
	{"news", LOG_NEWS},
	{"syslog", LOG_SYSLOG},
	{"user", LOG_USER},
	{"uucp", LOG_UUCP},
	{"local0", LOG_LOCAL0},
	{"local1", LOG_LOCAL1},
	{"local2", LOG_LOCAL2},
	{"local3", LOG_LOCAL3},
	{"local4", LOG_LOCAL4},
	{"local5", LOG_LOCAL5},
	{"local6", LOG_LOCAL6},
	{"local7", LOG_LOCAL7},
	NULL
};

#endif
