#ifndef PACKETP_H
#define PACKETP_H 

#include <pcap.h>
#include <dnet.h>
#include <pthread.h>

#include <packetp/addr_netcmp.h>
#include <packetp/hashtab.h>
#include <packetp/lookupa.h>
#include <packetp/recycle.h>
#include <packetp/standard.h>

#define IN 1
#define OUT 2
#define INTCHAR 60   /* Max length an interface name can be */

/* below are nodes used in linked lists that generally get allocated one
 * per interface. The packetp_ctx object-zilla has pointers to the heads of
 * the lists.
 */

struct route_node {
  struct route_entry route;
  struct intf_entry interface;
  eth_t *eth_handle;
  struct route_node *next;
};

struct pcap_node {
  pcap_t *pcap_handle;
  int pcap_fd;
  struct intf_entry interface;
  struct pcap_node *next;
};

struct fw_node {
  struct fw_rule rule;
  struct fw_node *next;
};

struct arp_node {
  time_t used_time;
  time_t set_time;
  struct addr mac;
};

/* Struct packetp_ctx is the object-zilla which gets passed around 
 * throughout most of Packet Purgatory. It enables me to initialize things 
 * up front, without having to keep track of things like route_t handles
 * and interfaces repeatedly.
 */

/* The following are currently valid wedge_type parameters */

#define PP_FAKEIP 1 /* This is the old lsrtunnel type of wedge, with
			a fake intermediate IP address */
#define PP_LOOPFW 2 /* This is the type of wedge recommended by Dug
		     *	at CanSecWest 02, wherein the outbound and
		     *	inbound packets to the target IP address are
		     *	blocked via route table and firewall chicanery */

struct packetp_ctx {
  int wedge_type;
  int verbose;
  int simplified;       /* 0 will just hand the captured packet to inbound
			 * and outbound handlers, the handlers must reinject
			 * if they want. 1 will munge the packet
			 * before handing to handlers, and will automatically
			 * write the packet out upon exit */
  struct addr proxy_ip;  /* Unused in TUN_LOOPFW */
  struct addr target_ip; /* Used when only some IP addresses should 
			  * be captured */
  struct addr my_ip;
  struct route_node *route_head;
  struct pcap_node *pcap_head;
  struct fw_node *fw_head;
  pthread_mutex_t arptab_mutex;
  htab *arp_table;
  ip_t *ip_handle;
  arp_t *arp_handle;
  fw_t *fw_handle;
  route_t *route_handle;
  intf_t *intf_handle;
};

struct thread_arg {
  struct packetp_ctx *ctx;
  uint8_t *frame;
  struct route_node *rnode;
  struct addr next_hop;
};

typedef int (*packet_handler)(struct packetp_ctx *ctx, 
			      uint8_t *packet, void *state);

struct packetp_ctx *packetp_init(void);

int packetp_start(struct packetp_ctx *ctx, packet_handler outbound, 
		  packet_handler inbound, void *state);
int packetp_set_target(struct packetp_ctx *ctx, struct addr *target);
int packetp_set_type(struct packetp_ctx *ctx, int type);
int packetp_set_proxy(struct packetp_ctx *ctx, struct addr *proxy);
int packetp_set_simplified(struct packetp_ctx *ctx, int simplified);
int packetp_set_verbose(struct packetp_ctx *ctx, int verbose);

/* Errors that packetp_start may return */
#define EPCAP      -1  /* Failed obtaining a pcap handle */
#define EARP       -2  /* Failed creating child to ARP for proxy IP */
#define EARPDIED   -3  /* The proxy IP ARP child terminated */
#define ESELECT    -4  /* Error reading in select (possible signal) */
#define EROUTE     -5  /* Failed saving state of route table */
#define EFIREWALL  -6  /* Failed opening fw handle */
#define EUNKNOWN   -7  /* wedge_type is unknown */
#define EOPEN      -8  /* Failed opening libdnet handles */
#define EMEM       -9  /* Failed allocating memory */

#include <packetp/firewallstate.h>
#include <packetp/forkarp.h>
#include <packetp/pcapf.h>
#include <packetp/routestate.h>

#endif /* PACKETP_H */
