#include <ctype.h>
#include <stdarg.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <net/ethernet.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <sys/syslog.h>

extern int debug_level;

/**************************** Constants ***********************************/

#define DEFAULT_DEBUG_LEVEL 1
#define HASH_SIZE           133981  /* prime number near 100000 */
#define SNAPLEN             65536   /* largest possible MTU we'll see */

#define FLOW_TX             1
#define FLOW_RX             2

/**************************** Structures **********************************/

typedef u_int32_t tcp_seq;

typedef struct {
  unsigned long int mallocs;
  unsigned long int cleans;
  unsigned long int packets;
  unsigned long int drops;
  unsigned long int debug;
  unsigned long int reuse;
} stats_t;

typedef struct {
  u_int32_t src;		/* Source IP address */
  u_int32_t dst;		/* Destination IP address */
  u_int16_t sport;		/* Source port number */
  u_int16_t dport;		/* Destination port number */
} flow_t;


typedef struct flow_state_struct {
  struct flow_state_struct *next; /* Link to next one */
  struct flow_state_struct *prev; /* Link to previous one */
  flow_t flow;			  /* Description of this flow */
  tcp_seq isn_tx;		  /* Initial sequence number transmiter */
  tcp_seq isn_rx;		  /* Initial sequence number receiver */
  int packet_tx;		  /* Number of packets in tx flow */
  int packet_rx;		  /* Number of packets in rx flow */
  time_t time_creation;		  /* "Time" of creation */
  time_t time_last_access;	  /* "Time" of last access */
} flow_state_struct;

typedef struct flow_state_struct flow_state_t;

  
/***************************** Macros *************************************/

#define MALLOC(type, num)  (type *) check_malloc((num) * sizeof(type))

#define DEBUG(message_level) if (debug_level >= message_level) debug_real

#define HASH_FLOW(flow) ( ( \
( (flow.sport & 0xffff) ^ (flow.dport & 0xffff) ) | \
 ( ( (flow.src & 0xffff) ^ (flow.dst & 0xffff) ) << 16 ) \
) % HASH_SIZE)


/************************* Function prototypes ****************************/

/* util.c */
void statistics();
char *copy_argv(char *argv[]);
void init_debug(char *argv[]);
void *check_malloc(size_t size);
char *flow_name(flow_t flow);
void debug_real(char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
void die(char *fmt, ...) __attribute__ ((format (printf, 1, 2)));

/* datalink.c */
pcap_handler find_handler(int datalink_type, char *device);

/* tcpip.c */
void process_ip(const u_char *data, u_int32_t length);
void process_tcp(const u_char *data, u_int32_t length, u_int32_t src,
		 u_int32_t dst);

/* flow.c */
void init_flow_state();
flow_state_t *find_flow_state(flow_t flow_tx, flow_t flow_rx, int *type);
flow_state_t *create_flow_state(flow_t flow);
